Movement will now be handled by the movement manager instead of mob

This commit is contained in:
KimLS 2018-09-20 16:14:47 -07:00
parent f754cb1307
commit 7278c6294d
32 changed files with 323 additions and 306 deletions

View File

@ -126,7 +126,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
(npc_dup != nullptr) ? npc_dup : npc_type, //make sure we give the NPC the correct data pointer (npc_dup != nullptr) ? npc_dup : npc_type, //make sure we give the NPC the correct data pointer
0, 0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3); GravityBehavior::Ground);
if (followme) if (followme)
swarm_pet_npc->SetFollowID(GetID()); swarm_pet_npc->SetFollowID(GetID());
@ -225,7 +225,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0, 0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3); GravityBehavior::Ground);
if (followme) if (followme)
swarm_pet_npc->SetFollowID(GetID()); swarm_pet_npc->SetFollowID(GetID());
@ -413,7 +413,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
make_npc->d_melee_texture1 = 0; make_npc->d_melee_texture1 = 0;
make_npc->d_melee_texture2 = 0; make_npc->d_melee_texture2 = 0;
auto npca = new NPC(make_npc, 0, GetPosition(), FlyMode3); auto npca = new NPC(make_npc, 0, GetPosition(), GravityBehavior::Ground);
if(!npca->GetSwarmInfo()){ if(!npca->GetSwarmInfo()){
auto nSI = new SwarmPet; auto nSI = new SwarmPet;

View File

@ -966,7 +966,7 @@ bool Mob::CombatRange(Mob* other)
if (_DistNoRoot <= size_mod) if (_DistNoRoot <= size_mod)
{ {
//A hack to kill an exploit till we get something better. //A hack to kill an exploit till we get something better.
if (flymode == 0 && _zDist > 500 && !CheckLastLosState()) { if (flymode == GravityBehavior::Ground && _zDist > 500 && !CheckLastLosState()) {
return false; return false;
} }

View File

@ -6,7 +6,7 @@
#include "raids.h" #include "raids.h"
Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record) Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record)
: NPC(type_data, 0, owner->GetPosition(), FlyMode3), spell_id(record.spell_id), distance(record.distance), : NPC(type_data, 0, owner->GetPosition(), GravityBehavior::Flying), spell_id(record.spell_id), distance(record.distance),
remove_timer(record.duration), movement_timer(100), process_timer(100), aura_id(-1) remove_timer(record.duration), movement_timer(100), process_timer(100), aura_id(-1)
{ {
GiveNPCTypeData(type_data); // we will delete this later on GiveNPCTypeData(type_data); // we will delete this later on

View File

@ -6632,7 +6632,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0, 0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3); GravityBehavior::Ground);
if(!swarm_pet_npc->GetSwarmInfo()){ if(!swarm_pet_npc->GetSwarmInfo()){
auto nSI = new SwarmPet; auto nSI = new SwarmPet;

View File

@ -204,7 +204,7 @@ int command_init(void)
command_add("flag", "[status] [acctname] - Refresh your admin status, or set an account's admin status if arguments provided", 0, command_flag) || command_add("flag", "[status] [acctname] - Refresh your admin status, or set an account's admin status if arguments provided", 0, command_flag) ||
command_add("flagedit", "- Edit zone flags on your target", 100, command_flagedit) || command_add("flagedit", "- Edit zone flags on your target", 100, command_flagedit) ||
command_add("flags", "- displays the flags of you or your target", 0, command_flags) || command_add("flags", "- displays the flags of you or your target", 0, command_flags) ||
command_add("flymode", "[0/1/2] - Set your or your player target's flymode to off/on/levitate", 50, command_flymode) || command_add("flymode", "[0/1/2/3/4/5] - Set your or your player target's flymode to ground/flying/levitate/water/floating/levitate_running", 50, command_flymode) ||
command_add("fov", "- Check wether you're behind or in your target's field of view", 80, command_fov) || command_add("fov", "- Check wether you're behind or in your target's field of view", 80, command_fov) ||
command_add("freeze", "- Freeze your target", 80, command_freeze) || command_add("freeze", "- Freeze your target", 80, command_freeze) ||
command_add("gassign", "[id] - Assign targetted NPC to predefined wandering grid id", 100, command_gassign) || command_add("gassign", "[id] - Assign targetted NPC to predefined wandering grid id", 100, command_gassign) ||
@ -2067,7 +2067,7 @@ void command_grid(Client *c, const Seperator *sep)
static_cast<uint32>(atoi(row[4])), static_cast<uint32>(atoi(row[4])),
static_cast<uint32>(atoi(row[5])) static_cast<uint32>(atoi(row[5]))
); );
npc->SetFlyMode(1); npc->SetFlyMode(GravityBehavior::Flying);
npc->GMMove(node_position.x, node_position.y, node_position.z, node_position.w); npc->GMMove(node_position.x, node_position.y, node_position.z, node_position.w);
} }
} }
@ -2166,20 +2166,37 @@ void command_mana(Client *c, const Seperator *sep)
void command_flymode(Client *c, const Seperator *sep) void command_flymode(Client *c, const Seperator *sep)
{ {
Client *t=c; Mob *t = c;
if (strlen(sep->arg[1]) == 1 && !(sep->arg[1][0] == '0' || sep->arg[1][0] == '1' || sep->arg[1][0] == '2')) if (strlen(sep->arg[1]) == 1 && !(sep->arg[1][0] == '0' || sep->arg[1][0] == '1' || sep->arg[1][0] == '2' || sep->arg[1][0] == '3' || sep->arg[1][0] == '4' || sep->arg[1][0] == '5'))
c->Message(0, "#flymode [0/1/2]"); c->Message(0, "#flymode [0/1/2/3/4/5]");
else { else {
if(c->GetTarget() && c->GetTarget()->IsClient()) if (c->GetTarget()) {
t=c->GetTarget()->CastToClient(); t = c->GetTarget();
t->SendAppearancePacket(AT_Levitate, atoi(sep->arg[1])); }
if (sep->arg[1][0] == '1')
c->Message(0, "Turning %s's Flymode ON", t->GetName()); int fm = atoi(sep->arg[1]);
else if (sep->arg[1][0] == '2')
c->Message(0, "Turning %s's Flymode LEV", t->GetName()); t->SetFlyMode(static_cast<GravityBehavior>(fm));
else t->SendAppearancePacket(AT_Levitate, fm);
c->Message(0, "Turning %s's Flymode OFF", t->GetName()); if (sep->arg[1][0] == '0') {
c->Message(0, "Setting %s to Grounded", t->GetName());
}
else if (sep->arg[1][0] == '1') {
c->Message(0, "Setting %s to Flying", t->GetName());
}
else if (sep->arg[1][0] == '2') {
c->Message(0, "Setting %s to Levitating", t->GetName());
}
else if (sep->arg[1][0] == '3') {
c->Message(0, "Setting %s to In Water", t->GetName());
}
else if (sep->arg[1][0] == '4') {
c->Message(0, "Setting %s to Floating(Boat)", t->GetName());
}
else if (sep->arg[1][0] == '5') {
c->Message(0, "Setting %s to Levitating While Running", t->GetName());
}
} }
} }
@ -2521,7 +2538,7 @@ void command_npctypespawn(Client *c, const Seperator *sep)
const NPCType* tmp = 0; const NPCType* tmp = 0;
if ((tmp = database.LoadNPCTypesData(atoi(sep->arg[1])))) { if ((tmp = database.LoadNPCTypesData(atoi(sep->arg[1])))) {
//tmp->fixedZ = 1; //tmp->fixedZ = 1;
auto npc = new NPC(tmp, 0, c->GetPosition(), FlyMode3); auto npc = new NPC(tmp, 0, c->GetPosition(), GravityBehavior::Ground);
if (npc && sep->IsNumber(2)) if (npc && sep->IsNumber(2))
npc->SetNPCFactionID(atoi(sep->arg[2])); npc->SetNPCFactionID(atoi(sep->arg[2]));

View File

@ -206,8 +206,6 @@ typedef enum { //fear states
fearStateStuck //I cannot move somehow... fearStateStuck //I cannot move somehow...
} FearState; } FearState;
enum { FlyMode0 = 0, FlyMode1 = 1, Flymode2 = 2, FlyMode3 = 3 };
// This is actually FlyMode, from MQ2 // This is actually FlyMode, from MQ2
enum GravityBehavior { enum GravityBehavior {
Ground, Ground,

View File

@ -3083,9 +3083,9 @@ XS(XS__FlyMode);
XS(XS__FlyMode) { XS(XS__FlyMode) {
dXSARGS; dXSARGS;
if (items != 1) if (items != 1)
Perl_croak(aTHX_ "Usage: quest::FlyMode(uint8 mode [0-3])"); Perl_croak(aTHX_ "Usage: quest::FlyMode(uint8 mode [0-5])");
uint8 flymode = (int) SvUV(ST(0)); GravityBehavior flymode = (GravityBehavior) SvUV(ST(0));
quest_manager.FlyMode(flymode); quest_manager.FlyMode(flymode);
XSRETURN_EMPTY; XSRETURN_EMPTY;

View File

@ -284,7 +284,7 @@ void Client::GoFish()
if (tmp != nullptr) { if (tmp != nullptr) {
auto positionNPC = GetPosition(); auto positionNPC = GetPosition();
positionNPC.x = positionNPC.x + 3; positionNPC.x = positionNPC.x + 3;
auto npc = new NPC(tmp, nullptr, positionNPC, FlyMode3); auto npc = new NPC(tmp, nullptr, positionNPC, GravityBehavior::Ground);
npc->AddLootTable(); npc->AddLootTable();
if (npc->DropsGlobalLoot()) if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables(); npc->CheckGlobalLootTables();

View File

@ -30,7 +30,7 @@ std::map<uint16, const NPCType *> Horse::horse_types;
LinkedList<NPCType *> horses_auto_delete; LinkedList<NPCType *> horses_auto_delete;
Horse::Horse(Client *_owner, uint16 spell_id, const glm::vec4& position) Horse::Horse(Client *_owner, uint16 spell_id, const glm::vec4& position)
: NPC(GetHorseType(spell_id), nullptr, position, FlyMode3) : NPC(GetHorseType(spell_id), nullptr, position, GravityBehavior::Ground)
{ {
//give the horse its proper name. //give the horse its proper name.
strn0cpy(name, _owner->GetCleanName(), 55); strn0cpy(name, _owner->GetCleanName(), 55);

View File

@ -891,7 +891,7 @@ void lua_flag_instance_by_raid_leader(uint32 zone, uint32 version) {
} }
void lua_fly_mode(int flymode) { void lua_fly_mode(int flymode) {
quest_manager.FlyMode(flymode); quest_manager.FlyMode(static_cast<GravityBehavior>(flymode));
} }
int lua_faction_value() { int lua_faction_value() {
@ -1499,7 +1499,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
LuaCreateNPCParse(no_target_hotkey, bool, false); LuaCreateNPCParse(no_target_hotkey, bool, false);
LuaCreateNPCParse(raid_target, bool, false); LuaCreateNPCParse(raid_target, bool, false);
NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), FlyMode3); NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Ground);
npc->GiveNPCTypeData(npc_type); npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc); entity_list.AddNPC(npc);
} }

View File

@ -1124,15 +1124,9 @@ double Lua_Mob::CalculateHeadingToTarget(double in_x, double in_y) {
return self->CalculateHeadingToTarget(static_cast<float>(in_x), static_cast<float>(in_y)); return self->CalculateHeadingToTarget(static_cast<float>(in_x), static_cast<float>(in_y));
} }
bool Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed) { void Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed) {
Lua_Safe_Call_Bool(); Lua_Safe_Call_Void();
return self->CalculateNewPosition(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(speed)); self->CalculateNewPosition(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(speed));
}
bool Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed, bool check_z) {
Lua_Safe_Call_Bool();
return self->CalculateNewPosition(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(speed),
check_z);
} }
float Lua_Mob::CalculateDistance(double x, double y, double z) { float Lua_Mob::CalculateDistance(double x, double y, double z) {
@ -1430,7 +1424,7 @@ void Lua_Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uin
void Lua_Mob::SetFlyMode(int in) { void Lua_Mob::SetFlyMode(int in) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetFlyMode(in); self->SetFlyMode(static_cast<GravityBehavior>(in));
} }
void Lua_Mob::SetTexture(int in) { void Lua_Mob::SetTexture(int in) {
@ -2361,8 +2355,7 @@ luabind::scope lua_register_mob() {
.def("FaceTarget", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::FaceTarget) .def("FaceTarget", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::FaceTarget)
.def("SetHeading", (void(Lua_Mob::*)(double))&Lua_Mob::SetHeading) .def("SetHeading", (void(Lua_Mob::*)(double))&Lua_Mob::SetHeading)
.def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget) .def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget)
.def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition) .def("CalculateNewPosition", (void(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition)
.def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::CalculateNewPosition)
.def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance) .def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance)
.def("SendTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendTo) .def("SendTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendTo)
.def("SendToFixZ", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendToFixZ) .def("SendToFixZ", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendToFixZ)

View File

@ -240,8 +240,7 @@ public:
void FaceTarget(Lua_Mob target); void FaceTarget(Lua_Mob target);
void SetHeading(double in); void SetHeading(double in);
double CalculateHeadingToTarget(double in_x, double in_y); double CalculateHeadingToTarget(double in_x, double in_y);
bool CalculateNewPosition(double x, double y, double z, double speed); void CalculateNewPosition(double x, double y, double z, double speed);
bool CalculateNewPosition(double x, double y, double z, double speed, bool check_z);
float CalculateDistance(double x, double y, double z); float CalculateDistance(double x, double y, double z);
void SendTo(double x, double y, double z); void SendTo(double x, double y, double z);
void SendToFixZ(double x, double y, double z); void SendToFixZ(double x, double y, double z);

View File

@ -29,7 +29,7 @@ extern volatile bool is_zone_loaded;
#endif #endif
Merc::Merc(const NPCType* d, float x, float y, float z, float heading) Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
: NPC(d, nullptr, glm::vec4(x, y, z, heading), 0, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000) : NPC(d, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Ground, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000)
{ {
base_hp = d->max_hp; base_hp = d->max_hp;
base_mana = d->Mana; base_mana = d->Mana;

View File

@ -427,7 +427,7 @@ Mob::Mob(const char* in_name,
m_TargetRing = glm::vec3(); m_TargetRing = glm::vec3();
flymode = FlyMode3; flymode = GravityBehavior::Ground;
DistractedFromGrid = false; DistractedFromGrid = false;
hate_list.SetHateOwner(this); hate_list.SetHateOwner(this);
@ -1167,7 +1167,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
ns->spawn.flymode = flymode; ns->spawn.flymode = flymode;
if(IsBoat()) { if(IsBoat()) {
ns->spawn.flymode = 1; ns->spawn.flymode = GravityBehavior::Floating;
} }
ns->spawn.lastName[0] = '\0'; ns->spawn.lastName[0] = '\0';
@ -3566,17 +3566,9 @@ bool Mob::EntityVariableExists(const char *id)
return false; return false;
} }
void Mob::SetFlyMode(uint8 flymode) void Mob::SetFlyMode(GravityBehavior flymode)
{ {
if(IsClient() && flymode >= 0 && flymode < 3) this->flymode = flymode;
{
this->SendAppearancePacket(AT_Levitate, flymode);
}
else if(IsNPC() && flymode >= 0 && flymode <= 3)
{
this->SendAppearancePacket(AT_Levitate, flymode);
this->CastToNPC()->SetFlyMode(flymode);
}
} }
bool Mob::IsNimbusEffectActive(uint32 nimbus_effect) bool Mob::IsNimbusEffectActive(uint32 nimbus_effect)
@ -6014,6 +6006,13 @@ float Mob::GetDefaultRaceSize() const {
return GetRaceGenderDefaultHeight(race, gender); return GetRaceGenderDefaultHeight(race, gender);
} }
void Mob::TryFixZ(int32 z_find_offset, bool fix_client_z)
{
if (fix_z_timer.Check() && flymode == GravityBehavior::Ground) {
FixZ();
}
}
#ifdef BOTS #ifdef BOTS
bool Mob::JoinHealRotationTargetPool(std::shared_ptr<HealRotation>* heal_rotation) bool Mob::JoinHealRotationTargetPool(std::shared_ptr<HealRotation>* heal_rotation)

View File

@ -529,7 +529,7 @@ public:
inline const float GetHeading() const { return m_Position.w; } inline const float GetHeading() const { return m_Position.w; }
inline const float GetSize() const { return size; } inline const float GetSize() const { return size; }
inline const float GetBaseSize() const { return base_size; } inline const float GetBaseSize() const { return base_size; }
inline const int8 GetFlyMode() const { return static_cast<const int8>(flymode); } inline const GravityBehavior GetFlyMode() const { return flymode; }
bool IsBoat() const; bool IsBoat() const;
//Group //Group
@ -567,8 +567,8 @@ public:
void SetSpawned() { spawned = true; }; void SetSpawned() { spawned = true; };
bool Spawned() { return spawned; }; bool Spawned() { return spawned; };
virtual bool ShouldISpawnFor(Client *c) { return true; } virtual bool ShouldISpawnFor(Client *c) { return true; }
void SetFlyMode(uint8 flymode); void SetFlyMode(GravityBehavior flymode);
inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y; inline void Teleport(const glm::vec3 &NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y;
m_Position.z = NewPosition.z; }; m_Position.z = NewPosition.z; };
void TryMoveAlong(float distance, float angle, bool send = true); void TryMoveAlong(float distance, float angle, bool send = true);
void ProcessForcedMovement(); void ProcessForcedMovement();
@ -801,8 +801,9 @@ public:
void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true); void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true);
inline EmuAppearance GetAppearance() const { return _appearance; } inline EmuAppearance GetAppearance() const { return _appearance; }
inline const int GetAnimation() const { return animation; } inline const int GetAnimation() const { return animation; }
inline void SetAnimation(int a) { animation = a; }
inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; } inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; }
inline void SetRunAnimSpeed(int8 in) { if (pRunAnimSpeed != in) { pRunAnimSpeed = in; } } inline void SetRunAnimSpeed(int8 in) { pRunAnimSpeed = in; }
bool IsDestructibleObject() { return destructibleobject; } bool IsDestructibleObject() { return destructibleobject; }
void SetDestructibleObject(bool in) { destructibleobject = in; } void SetDestructibleObject(bool in) { destructibleobject = in; }
@ -968,13 +969,14 @@ public:
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);} inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); } float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); }
virtual bool CalculateNewPosition(float x, float y, float z, float speed, bool check_z = true, bool calculate_heading = true); virtual void CalculateNewPosition(float x, float y, float z, float speed, bool check_z = true, bool calculate_heading = true);
float CalculateDistance(float x, float y, float z); float CalculateDistance(float x, float y, float z);
float GetGroundZ(float new_x, float new_y, float z_offset=0.0); float GetGroundZ(float new_x, float new_y, float z_offset=0.0);
void SendTo(float new_x, float new_y, float new_z); void SendTo(float new_x, float new_y, float new_z);
void SendToFixZ(float new_x, float new_y, float new_z); void SendToFixZ(float new_x, float new_y, float new_z);
float GetZOffset() const; float GetZOffset() const;
float GetDefaultRaceSize() const; float GetDefaultRaceSize() const;
void TryFixZ(int32 z_find_offset = 5, bool fix_client_z = false);
void FixZ(int32 z_find_offset = 5, bool fix_client_z = false); void FixZ(int32 z_find_offset = 5, bool fix_client_z = false);
float GetFixedZ(glm::vec3 destination, int32 z_find_offset = 5); float GetFixedZ(glm::vec3 destination, int32 z_find_offset = 5);
@ -1131,6 +1133,9 @@ public:
int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item);
int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr); int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr);
//Pathing
glm::vec3 UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
// Bots HealRotation methods // Bots HealRotation methods
#ifdef BOTS #ifdef BOTS
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); } bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }
@ -1152,7 +1157,6 @@ protected:
int _GetWalkSpeed() const; int _GetWalkSpeed() const;
int _GetRunSpeed() const; int _GetRunSpeed() const;
int _GetFearSpeed() const; int _GetFearSpeed() const;
virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool check_z = true, bool calculate_heading = true);
virtual bool AI_EngagedCastCheck() { return(false); } virtual bool AI_EngagedCastCheck() { return(false); }
virtual bool AI_PursueCastCheck() { return(false); } virtual bool AI_PursueCastCheck() { return(false); }
@ -1288,7 +1292,6 @@ protected:
void CalculateNewFearpoint(); void CalculateNewFearpoint();
float FindGroundZ(float new_x, float new_y, float z_offset=0.0); float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
float FindDestGroundZ(glm::vec3 dest, float z_offset=0.0); float FindDestGroundZ(glm::vec3 dest, float z_offset=0.0);
glm::vec3 UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
glm::vec3 HandleStuckPath(const glm::vec3 &To, const glm::vec3 &From); glm::vec3 HandleStuckPath(const glm::vec3 &To, const glm::vec3 &From);
virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0); virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0);
@ -1509,7 +1512,7 @@ protected:
// we might want to do this differently, we gotta do max NPC buffs ... which is 97 // we might want to do this differently, we gotta do max NPC buffs ... which is 97
uint32 m_spellHitsLeft[EQEmu::constants::TotalBuffs]; // Used to track which spells will have their numhits incremented when spell finishes casting uint32 m_spellHitsLeft[EQEmu::constants::TotalBuffs]; // Used to track which spells will have their numhits incremented when spell finishes casting
int flymode; GravityBehavior flymode;
bool m_targetable; bool m_targetable;
int QGVarDuration(const char *fmt); int QGVarDuration(const char *fmt);
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate); void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);

View File

@ -1520,7 +1520,6 @@ void Mob::AI_Process() {
} }
else { else {
bool waypoint_changed, node_reached;
auto &Goal = owner->GetPosition(); auto &Goal = owner->GetPosition();
CalculateNewPosition(Goal.x, Goal.y, Goal.z, pet_speed, true); CalculateNewPosition(Goal.x, Goal.y, Goal.z, pet_speed, true);
@ -1792,16 +1791,13 @@ void NPC::AI_DoMovement() {
} }
else if (IsGuarding()) { else if (IsGuarding()) {
bool CP2Moved; CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, move_speed);
//if(Distance(m_GuardPoint, m_Position))
if (!((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z))) { bool at_gp = CalculateDistance(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z) < 0.1f;
CP2Moved = CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, move_speed);
}
else {
CP2Moved = false;
}
if (!CP2Moved) { if (at_gp) {
if (moved) { if (moved) {
Log(Logs::Detail, Log(Logs::Detail,
Logs::AI, Logs::AI,

View File

@ -4,19 +4,20 @@
#include "../common/timer.h" #include "../common/timer.h"
#include <vector> #include <vector>
#include <map>
#include <stdlib.h> #include <stdlib.h>
struct MobMovementEntry extern uint64_t frame_time;
struct MovementEntry
{ {
Mob *m;
int animation; int animation;
float heading; float heading;
bool dirty; bool dirty;
double last_sent_time; double last_sent_time;
double last_sent_time_long_distance; double last_sent_time_long_distance;
MobMovementEntry(Mob *m) { MovementEntry(Mob *m) {
this->m = m;
animation = 0; animation = 0;
heading = m->GetHeading(); heading = m->GetHeading();
dirty = false; dirty = false;
@ -25,9 +26,27 @@ struct MobMovementEntry
} }
}; };
struct MoveToEntry
{
float x;
float y;
float z;
float speed;
bool active;
MoveToEntry() {
x = 0.0f;
y = 0.0f;
z = 0.0f;
speed = 0.0f;
active = false;
}
};
struct MobMovementManager::Implementation struct MobMovementManager::Implementation
{ {
std::vector<MobMovementEntry> Entries; std::map<Mob*, MovementEntry> Entries;
std::map<Mob*, MoveToEntry> MoveEntries;
std::vector<Client*> Clients; std::vector<Client*> Clients;
}; };
@ -44,9 +63,18 @@ void MobMovementManager::Process()
{ {
double current_time = static_cast<double>(Timer::GetCurrentTime()) / 1000.0; double current_time = static_cast<double>(Timer::GetCurrentTime()) / 1000.0;
for (auto &ent : _impl->Entries) { for (auto &mov : _impl->MoveEntries) {
auto &ent = mov.second;
if (ent.active) {
ProcessMovement(mov.first, ent.x, ent.y, ent.z, ent.speed);
}
}
for (auto &iter : _impl->Entries) {
auto &ent = iter.second;
if (ent.dirty) { if (ent.dirty) {
SendUpdate(ent.m, ent.animation, ent.heading); SendUpdate(iter.first, ent.animation, ent.heading);
ent.dirty = false; ent.dirty = false;
ent.last_sent_time = current_time; ent.last_sent_time = current_time;
@ -56,12 +84,12 @@ void MobMovementManager::Process()
double diff_long_range = current_time - ent.last_sent_time_long_distance; double diff_long_range = current_time - ent.last_sent_time_long_distance;
if (diff_short_range >= 2.0) { if (diff_short_range >= 2.0) {
SendUpdateShortDistance(ent.m, ent.animation, ent.heading); SendUpdateShortDistance(iter.first, ent.animation, ent.heading);
ent.last_sent_time = current_time; ent.last_sent_time = current_time;
} }
if (diff_long_range >= 6.0) { if (diff_long_range >= 6.0) {
SendUpdateLongDistance(ent.m, ent.animation, ent.heading); SendUpdateLongDistance(iter.first, ent.animation, ent.heading);
ent.last_sent_time_long_distance = current_time; ent.last_sent_time_long_distance = current_time;
} }
} }
@ -70,20 +98,14 @@ void MobMovementManager::Process()
void MobMovementManager::AddMob(Mob *m) void MobMovementManager::AddMob(Mob *m)
{ {
_impl->Entries.push_back(MobMovementEntry(m)); _impl->Entries.insert(std::make_pair(m, MovementEntry(m)));
_impl->MoveEntries.insert(std::make_pair(m, MoveToEntry()));
} }
void MobMovementManager::RemoveMob(Mob *m) void MobMovementManager::RemoveMob(Mob *m)
{ {
auto iter = _impl->Entries.begin(); _impl->Entries.erase(m);
while (iter != _impl->Entries.end()) { _impl->MoveEntries.erase(m);
auto &ent = *iter;
if (ent.m == m) {
_impl->Entries.erase(iter);
return;
}
++iter;
}
} }
void MobMovementManager::AddClient(Client *c) void MobMovementManager::AddClient(Client *c)
@ -107,60 +129,62 @@ void MobMovementManager::RemoveClient(Client *c)
void MobMovementManager::SendPosition(Mob *who) void MobMovementManager::SendPosition(Mob *who)
{ {
auto iter = _impl->Entries.begin(); auto iter = _impl->Entries.find(who);
while (iter != _impl->Entries.end()) { auto &ent = iter->second;
auto &ent = *iter;
if (ent.m == who) {
auto anim = 0;
auto heading = who->GetHeading();
if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) {
ent.animation = anim;
ent.heading = heading;
ent.dirty = true;
}
return; auto anim = 0;
} auto heading = who->GetHeading();
++iter; if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) {
ent.animation = anim;
ent.heading = heading;
ent.dirty = true;
} }
} }
void MobMovementManager::SendPositionUpdate(Mob *who, bool send_to_self) void MobMovementManager::SendPositionUpdate(Mob *who, bool send_to_self)
{ {
auto iter = _impl->Entries.begin(); auto iter = _impl->Entries.find(who);
while (iter != _impl->Entries.end()) { auto &ent = iter->second;
auto &ent = *iter;
if (ent.m == who) { auto anim = 0;
auto anim = 0; auto heading = who->GetHeading();
auto heading = who->GetHeading(); if (who->IsMoving()) {
if (who->IsMoving()) { if (who->IsClient()) {
if (who->IsClient()) { anim = who->GetAnimation();
anim = who->GetAnimation(); }
} else {
else { anim = who->GetRunAnimSpeed();
anim = who->GetRunAnimSpeed();
}
}
if (send_to_self && who->IsClient()) {
SendUpdateTo(who, who->CastToClient(), anim, heading);
}
if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) {
ent.animation = anim;
ent.heading = heading;
ent.dirty = true;
}
return;
} }
++iter;
} }
if (send_to_self && who->IsClient()) {
SendUpdateTo(who, who->CastToClient(), anim, heading);
}
if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) {
ent.animation = anim;
ent.heading = heading;
ent.dirty = true;
}
}
void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, float speed)
{
auto iter = _impl->MoveEntries.find(who);
auto &ent = iter->second;
ent.x = x;
ent.y = y;
ent.z = z;
ent.speed = speed;
ent.active = true;
}
void MobMovementManager::StopNavigation(Mob *who) {
auto iter = _impl->MoveEntries.find(who);
auto &ent = iter->second;
ent.active = false;
} }
bool MobMovementManager::HeadingEqual(float a, float b) bool MobMovementManager::HeadingEqual(float a, float b)
@ -257,3 +281,96 @@ void MobMovementManager::SendUpdateLongDistance(Mob *who, int anim, float headin
} }
} }
} }
void MobMovementManager::ProcessMovement(Mob *who, float x, float y, float z, float speed)
{
if (who->GetID() == 0) {
return;
}
if (speed <= 0) {
who->SetCurrentSpeed(0);
return;
}
if (IsPositionEqual(x, y, z, who->GetX(), who->GetY(), who->GetZ())) {
StopNavigation(who);
return;
}
bool calculate_heading = false;
bool WaypointChanged = false;
bool NodeReached = false;
glm::vec3 Goal = who->UpdatePath(
x, y, z, speed, WaypointChanged, NodeReached
);
if (WaypointChanged || NodeReached) {
calculate_heading = true;
entity_list.OpenDoorsNear(who);
}
who->SetCurrentSpeed(static_cast<int>(speed));
who->SetRunAnimSpeed(speed);
#ifdef BOTS
if (who->IsClient() || who->IsBot())
#else
if (who->IsClient())
#endif
{
who->SetAnimation(speed * 0.55f);
}
auto &p = who->GetPosition();
//Setup Vectors
glm::vec3 tar(Goal.x, Goal.y, Goal.z);
glm::vec3 pos(p.x, p.y, p.z);
double len = glm::distance(pos, tar);
if (len == 0) {
return;
}
glm::vec3 dir = tar - pos;
glm::vec3 ndir = glm::normalize(dir);
double time_since_last = static_cast<double>(frame_time) / 1000.0;
double distance_moved = time_since_last * speed * 0.4f * 1.4f;
if (distance_moved > len) {
who->Teleport(Goal);
if (who->IsNPC()) {
entity_list.ProcessMove(who->CastToNPC(), Goal.x, Goal.y, Goal.z);
}
who->TryFixZ();
return;
}
else {
glm::vec3 npos = pos + (ndir * static_cast<float>(distance_moved));
who->Teleport(npos);
if (who->IsNPC()) {
entity_list.ProcessMove(who->CastToNPC(), npos.x, npos.y, npos.z);
}
}
if (calculate_heading) {
who->SetHeading(who->CalculateHeadingToTarget(Goal.x, Goal.y));
}
who->TryFixZ();
who->SetMoving(true);
if (who->IsClient()) {
who->SendPositionUpdate();
who->CastToClient()->ResetPositionTimer();
}
else {
who->SendPositionUpdate();
who->SetAppearance(eaStanding, false);
}
}

View File

@ -16,6 +16,8 @@ public:
void SendPosition(Mob *who); void SendPosition(Mob *who);
void SendPositionUpdate(Mob *who, bool send_to_self); void SendPositionUpdate(Mob *who, bool send_to_self);
void NavigateTo(Mob *who, float x, float y, float z, float speed);
void StopNavigation(Mob *who);
static MobMovementManager &Get() { static MobMovementManager &Get() {
static MobMovementManager inst; static MobMovementManager inst;
@ -32,6 +34,7 @@ private:
void SendUpdate(Mob *who, int anim, float heading); void SendUpdate(Mob *who, int anim, float heading);
void SendUpdateShortDistance(Mob *who, int anim, float heading); void SendUpdateShortDistance(Mob *who, int anim, float heading);
void SendUpdateLongDistance(Mob *who, int anim, float heading); void SendUpdateLongDistance(Mob *who, int anim, float heading);
void ProcessMovement(Mob *who, float x, float y, float z, float speed);
struct Implementation; struct Implementation;
std::unique_ptr<Implementation> _impl; std::unique_ptr<Implementation> _impl;

View File

@ -57,7 +57,7 @@ extern Zone* zone;
extern volatile bool is_zone_loaded; extern volatile bool is_zone_loaded;
extern EntityList entity_list; extern EntityList entity_list;
NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int iflymode, bool IsCorpse) NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, GravityBehavior iflymode, bool IsCorpse)
: Mob(d->name, : Mob(d->name,
d->lastname, d->lastname,
d->max_hp, d->max_hp,
@ -977,7 +977,7 @@ bool NPC::SpawnZoneController(){
point.y = 1000; point.y = 1000;
point.z = 500; point.z = 500;
auto npc = new NPC(npc_type, nullptr, point, FlyMode3); auto npc = new NPC(npc_type, nullptr, point, GravityBehavior::Flying);
npc->GiveNPCTypeData(npc_type); npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc); entity_list.AddNPC(npc);
@ -1020,7 +1020,7 @@ NPC * NPC::SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32
npc_type->findable = true; npc_type->findable = true;
auto node_position = glm::vec4(position.x, position.y, position.z, position.w); auto node_position = glm::vec4(position.x, position.y, position.z, position.w);
auto npc = new NPC(npc_type, nullptr, node_position, FlyMode1); auto npc = new NPC(npc_type, nullptr, node_position, GravityBehavior::Flying);
npc->GiveNPCTypeData(npc_type); npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc, true, true); entity_list.AddNPC(npc, true, true);
@ -1187,7 +1187,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
npc_type->prim_melee_type = 28; npc_type->prim_melee_type = 28;
npc_type->sec_melee_type = 28; npc_type->sec_melee_type = 28;
auto npc = new NPC(npc_type, nullptr, position, FlyMode3); auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Ground);
npc->GiveNPCTypeData(npc_type); npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc); entity_list.AddNPC(npc);
@ -2819,4 +2819,4 @@ void NPC::ModifyStatsOnCharm(bool bRemoved)
// the rest of the stats aren't cached, so lets just do these two instead of full CalcBonuses() // the rest of the stats aren't cached, so lets just do these two instead of full CalcBonuses()
SetAttackTimer(); SetAttackTimer();
CalcAC(); CalcAC();
} }

View File

@ -106,7 +106,7 @@ public:
static bool SpawnZoneController(); static bool SpawnZoneController();
static int8 GetAILevel(bool iForceReRead = false); static int8 GetAILevel(bool iForceReRead = false);
NPC(const NPCType* data, Spawn2* respawn, const glm::vec4& position, int iflymode, bool IsCorpse = false); NPC(const NPCType* data, Spawn2* respawn, const glm::vec4& position, GravityBehavior iflymode, bool IsCorpse = false);
virtual ~NPC(); virtual ~NPC();
@ -229,9 +229,6 @@ public:
EmuAppearance GetGuardPointAnim() const { return guard_anim; } EmuAppearance GetGuardPointAnim() const { return guard_anim; }
void SaveGuardPointAnim(EmuAppearance anim) { guard_anim = anim; } void SaveGuardPointAnim(EmuAppearance anim) { guard_anim = anim; }
void SetFlyMode(uint8 FlyMode){ flymode=FlyMode; }
uint32 GetFlyMode() const { return flymode; }
uint8 GetPrimSkill() const { return prim_melee_type; } uint8 GetPrimSkill() const { return prim_melee_type; }
uint8 GetSecSkill() const { return sec_melee_type; } uint8 GetSecSkill() const { return sec_melee_type; }
uint8 GetRangedSkill() const { return ranged_type; } uint8 GetRangedSkill() const { return ranged_type; }

View File

@ -557,7 +557,7 @@ void PathfinderWaypoint::ShowNode(const Node &n) {
npc_type->findable = 1; npc_type->findable = 1;
auto position = glm::vec4(n.v.x, n.v.y, n.v.z, 0.0f); auto position = glm::vec4(n.v.x, n.v.y, n.v.z, 0.0f);
auto npc = new NPC(npc_type, nullptr, position, FlyMode1); auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Flying);
npc->GiveNPCTypeData(npc_type); npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc, true, true); entity_list.AddNPC(npc, true, true);

View File

@ -13,7 +13,7 @@ void AdjustRoute(std::list<IPathfinder::IPathNode> &nodes, int flymode, float of
} }
for (auto &node : nodes) { for (auto &node : nodes) {
if (flymode == 0 || !zone->watermap->InLiquid(node.pos)) { if (flymode == GravityBehavior::Ground || !zone->watermap->InLiquid(node.pos)) {
auto best_z = zone->zonemap->FindBestZ(node.pos, nullptr); auto best_z = zone->zonemap->FindBestZ(node.pos, nullptr);
if (best_z != BEST_Z_INVALID) { if (best_z != BEST_Z_INVALID) {
node.pos.z = best_z + offset; node.pos.z = best_z + offset;
@ -114,7 +114,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa
} }
bool AtNextNode = false; bool AtNextNode = false;
if (flymode == 1) { if (flymode == GravityBehavior::Flying) {
AtNextNode = DistanceSquared(From, (*Route.begin()).pos) < 4.0f; AtNextNode = DistanceSquared(From, (*Route.begin()).pos) < 4.0f;
} }
else { else {

View File

@ -5531,15 +5531,13 @@ XS(XS_Mob_CalculateNewPosition) {
dXSARGS; dXSARGS;
if (items < 5 || items > 6) if (items < 5 || items > 6)
Perl_croak(aTHX_ Perl_croak(aTHX_
"Usage: Mob::CalculateNewPosition(THIS, float x, float y, float z, float speed, [bool check_z = false])"); "Usage: Mob::CalculateNewPosition(THIS, float x, float y, float z, float speed)");
{ {
Mob *THIS; Mob *THIS;
bool RETVAL;
float x = (float) SvNV(ST(1)); float x = (float) SvNV(ST(1));
float y = (float) SvNV(ST(2)); float y = (float) SvNV(ST(2));
float z = (float) SvNV(ST(3)); float z = (float) SvNV(ST(3));
float speed = (float) SvNV(ST(4)); float speed = (float) SvNV(ST(4));
bool checkZ;
if (sv_derived_from(ST(0), "Mob")) { if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV *) SvRV(ST(0))); IV tmp = SvIV((SV *) SvRV(ST(0)));
@ -5549,17 +5547,10 @@ XS(XS_Mob_CalculateNewPosition) {
if (THIS == nullptr) if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
if (items < 6)
checkZ = false;
else {
checkZ = (bool) SvTRUE(ST(5));
}
RETVAL = THIS->CalculateNewPosition(x, y, z, speed, checkZ); THIS->CalculateNewPosition(x, y, z, speed);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
} }
XSRETURN(1); XSRETURN_EMPTY;
} }
XS(XS_Mob_CalculateDistance); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_CalculateDistance); /* prototype to pass -Wmissing-prototypes */
@ -6652,10 +6643,10 @@ XS(XS_Mob_SetFlyMode); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_SetFlyMode) { XS(XS_Mob_SetFlyMode) {
dXSARGS; dXSARGS;
if (items != 2) if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::SetFlyMode(THIS, uint8 flymode[0|1|2|3])"); Perl_croak(aTHX_ "Usage: Mob::SetFlyMode(THIS, uint8 flymode[0|1|2|3|4|5])");
{ {
Mob *THIS; Mob *THIS;
uint8 flymode = (uint8) SvIV(ST(1)); GravityBehavior flymode = (GravityBehavior) SvIV(ST(1));
if (sv_derived_from(ST(0), "Mob")) { if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV *) SvRV(ST(0))); IV tmp = SvIV((SV *) SvRV(ST(0)));
@ -8696,7 +8687,7 @@ XS(boot_Mob) {
newXSproto(strcpy(buf, "WipeHateList"), XS_Mob_WipeHateList, file, "$"); newXSproto(strcpy(buf, "WipeHateList"), XS_Mob_WipeHateList, file, "$");
newXSproto(strcpy(buf, "CheckAggro"), XS_Mob_CheckAggro, file, "$$"); newXSproto(strcpy(buf, "CheckAggro"), XS_Mob_CheckAggro, file, "$$");
newXSproto(strcpy(buf, "CalculateHeadingToTarget"), XS_Mob_CalculateHeadingToTarget, file, "$$$"); newXSproto(strcpy(buf, "CalculateHeadingToTarget"), XS_Mob_CalculateHeadingToTarget, file, "$$$");
newXSproto(strcpy(buf, "CalculateNewPosition"), XS_Mob_CalculateNewPosition, file, "$$$$$;$"); newXSproto(strcpy(buf, "CalculateNewPosition"), XS_Mob_CalculateNewPosition, file, "$$$$$");
newXSproto(strcpy(buf, "CalculateDistance"), XS_Mob_CalculateDistance, file, "$$$$"); newXSproto(strcpy(buf, "CalculateDistance"), XS_Mob_CalculateDistance, file, "$$$$");
newXSproto(strcpy(buf, "SendTo"), XS_Mob_SendTo, file, "$$$$"); newXSproto(strcpy(buf, "SendTo"), XS_Mob_SendTo, file, "$$$$");
newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$"); newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$");

View File

@ -425,7 +425,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
into walls or objects (+10), this sometimes creates the "ghost" effect. I changed to +2 (as close as I into walls or objects (+10), this sometimes creates the "ghost" effect. I changed to +2 (as close as I
could get while it still looked good). I also noticed this can happen if an NPC is spawned on the same spot of another or in a related bad spot.*/ could get while it still looked good). I also noticed this can happen if an NPC is spawned on the same spot of another or in a related bad spot.*/
Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power) Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power)
: NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), FlyMode3) : NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), GravityBehavior::Ground)
{ {
GiveNPCTypeData(type_data); GiveNPCTypeData(type_data);
typeofpet = type; typeofpet = type;

View File

@ -160,3 +160,9 @@ float GetReciprocalHeading(const float heading)
return result; return result;
} }
bool IsPositionEqual(float x1, float y1, float z1, float x2, float y2, float z2)
{
static const float eps = 0.0001f;
return std::abs(x1 - x2) < eps && std::abs(y1 - y2) < eps && std::abs(z1 - z2) < eps;
}

View File

@ -50,4 +50,6 @@ float DistanceSquaredNoZ(const glm::vec4& point1, const glm::vec4& point2);
float GetReciprocalHeading(const glm::vec4& point1); float GetReciprocalHeading(const glm::vec4& point1);
float GetReciprocalHeading(const float heading); float GetReciprocalHeading(const float heading);
bool IsPositionEqual(float x1, float y1, float z1, float x2, float y2, float z2);
#endif #endif

View File

@ -208,7 +208,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p
const NPCType* tmp = 0; const NPCType* tmp = 0;
if (tmp = database.LoadNPCTypesData(npc_type)) if (tmp = database.LoadNPCTypesData(npc_type))
{ {
auto npc = new NPC(tmp, nullptr, position, FlyMode3); auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Ground);
npc->AddLootTable(); npc->AddLootTable();
if (npc->DropsGlobalLoot()) if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables(); npc->CheckGlobalLootTables();
@ -232,7 +232,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v
const NPCType* tmp = 0; const NPCType* tmp = 0;
if (tmp = database.LoadNPCTypesData(npc_type)) if (tmp = database.LoadNPCTypesData(npc_type))
{ {
auto npc = new NPC(tmp, nullptr, position, FlyMode3); auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Ground);
npc->AddLootTable(); npc->AddLootTable();
if (npc->DropsGlobalLoot()) if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables(); npc->CheckGlobalLootTables();
@ -308,22 +308,22 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id)
found_spawn->SetCurrentNPCID(npcid); found_spawn->SetCurrentNPCID(npcid);
auto position = glm::vec4(found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(), found_spawn->GetHeading()); auto position = glm::vec4(found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(), found_spawn->GetHeading());
auto npc = new NPC(tmp, found_spawn, position, FlyMode3); auto npc = new NPC(tmp, found_spawn, position, GravityBehavior::Ground);
found_spawn->SetNPCPointer(npc); found_spawn->SetNPCPointer(npc);
npc->AddLootTable(); npc->AddLootTable();
if (npc->DropsGlobalLoot()) if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables(); npc->CheckGlobalLootTables();
npc->SetSp2(found_spawn->SpawnGroupID()); npc->SetSp2(found_spawn->SpawnGroupID());
entity_list.AddNPC(npc); entity_list.AddNPC(npc);
entity_list.LimitAddNPC(npc); entity_list.LimitAddNPC(npc);
if (sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay && if (sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay &&
sg->min_delay) sg->min_delay)
npc->AI_SetRoambox(sg->roamdist, sg->roambox[0], sg->roambox[1], sg->roambox[2], sg->roambox[3], npc->AI_SetRoambox(sg->roamdist, sg->roambox[0], sg->roambox[1], sg->roambox[2], sg->roambox[3],
sg->delay, sg->min_delay); sg->delay, sg->min_delay);
if (zone->InstantGrids()) { if (zone->InstantGrids()) {
found_spawn->LoadGrid(); found_spawn->LoadGrid();
} }
return npc; return npc;
@ -1686,7 +1686,7 @@ void QuestManager::respawn(int npcTypeID, int grid) {
const NPCType* npcType = nullptr; const NPCType* npcType = nullptr;
if ((npcType = database.LoadNPCTypesData(npcTypeID))) if ((npcType = database.LoadNPCTypesData(npcTypeID)))
{ {
owner = new NPC(npcType, nullptr, owner->GetPosition(), FlyMode3); owner = new NPC(npcType, nullptr, owner->GetPosition(), GravityBehavior::Ground);
owner->CastToNPC()->AddLootTable(); owner->CastToNPC()->AddLootTable();
if (owner->CastToNPC()->DropsGlobalLoot()) if (owner->CastToNPC()->DropsGlobalLoot())
owner->CastToNPC()->CheckGlobalLootTables(); owner->CastToNPC()->CheckGlobalLootTables();
@ -2827,22 +2827,18 @@ bool QuestManager::IsRunning()
return owner->IsRunning(); return owner->IsRunning();
} }
void QuestManager::FlyMode(uint8 flymode) void QuestManager::FlyMode(GravityBehavior flymode)
{ {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
if(initiator) if(initiator)
{ {
if (flymode >= 0 && flymode < 3) { initiator->SendAppearancePacket(AT_Levitate, static_cast<int>(flymode));
initiator->SendAppearancePacket(AT_Levitate, flymode); initiator->SetFlyMode(flymode);
return;
}
} }
if(owner) else if(owner)
{ {
if (flymode >= 0 && flymode < 3) { owner->SendAppearancePacket(AT_Levitate, static_cast<int>(flymode));
owner->SendAppearancePacket(AT_Levitate, flymode); owner->SetFlyMode(flymode);
return;
}
} }
} }

View File

@ -249,7 +249,7 @@ public:
const char* getguildnamebyid(int guild_id); const char* getguildnamebyid(int guild_id);
void SetRunning(bool val); void SetRunning(bool val);
bool IsRunning(); bool IsRunning();
void FlyMode(uint8 flymode); void FlyMode(GravityBehavior flymode);
uint8 FactionValue(); uint8 FactionValue();
void wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0); void wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0);
void voicetell(const char *str, int macronum, int racenum, int gendernum); void voicetell(const char *str, int macronum, int racenum, int gendernum);

View File

@ -255,7 +255,7 @@ bool Spawn2::Process() {
} }
currentnpcid = npcid; currentnpcid = npcid;
NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), FlyMode3); NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), GravityBehavior::Ground);
npc->mod_prespawn(this); npc->mod_prespawn(this);

View File

@ -166,7 +166,7 @@ void Trap::Trigger(Mob* trigger)
{ {
auto randomOffset = glm::vec4(zone->random.Int(-5, 5),zone->random.Int(-5, 5),zone->random.Int(-5, 5), zone->random.Int(0, 249)); auto randomOffset = glm::vec4(zone->random.Int(-5, 5),zone->random.Int(-5, 5),zone->random.Int(-5, 5), zone->random.Int(0, 249));
auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f); auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f);
auto new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3); auto new_npc = new NPC(tmp, nullptr, spawnPosition, GravityBehavior::Flying);
new_npc->AddLootTable(); new_npc->AddLootTable();
if (new_npc->DropsGlobalLoot()) if (new_npc->DropsGlobalLoot())
new_npc->CheckGlobalLootTables(); new_npc->CheckGlobalLootTables();
@ -191,7 +191,7 @@ void Trap::Trigger(Mob* trigger)
{ {
auto randomOffset = glm::vec4(zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(0, 249)); auto randomOffset = glm::vec4(zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(0, 249));
auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f); auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f);
auto new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3); auto new_npc = new NPC(tmp, nullptr, spawnPosition, GravityBehavior::Flying);
new_npc->AddLootTable(); new_npc->AddLootTable();
if (new_npc->DropsGlobalLoot()) if (new_npc->DropsGlobalLoot())
new_npc->CheckGlobalLootTables(); new_npc->CheckGlobalLootTables();
@ -469,7 +469,7 @@ void Trap::CreateHiddenTrigger()
make_npc->trackable = 0; make_npc->trackable = 0;
make_npc->level = level; make_npc->level = level;
strcpy(make_npc->special_abilities, "19,1^20,1^24,1^25,1"); strcpy(make_npc->special_abilities, "19,1^20,1^24,1^25,1");
NPC* npca = new NPC(make_npc, nullptr, glm::vec4(m_Position, 0.0f), FlyMode3); NPC* npca = new NPC(make_npc, nullptr, glm::vec4(m_Position, 0.0f), GravityBehavior::Flying);
npca->GiveNPCTypeData(make_npc); npca->GiveNPCTypeData(make_npc);
entity_list.AddNPC(npca); entity_list.AddNPC(npca);

View File

@ -30,12 +30,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "quest_parser_collection.h" #include "quest_parser_collection.h"
#include "water_map.h" #include "water_map.h"
#include "fastmath.h" #include "fastmath.h"
#include "mob_movement_manager.h"
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
extern FastMath g_Math; extern FastMath g_Math;
extern uint64_t frame_time;
struct wp_distance struct wp_distance
{ {
@ -427,11 +427,8 @@ void NPC::SaveGuardSpot(bool iClearGuardSpot) {
} }
void NPC::NextGuardPosition() { void NPC::NextGuardPosition() {
if (!CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed())) { CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed());
SetHeading(m_GuardPoint.w); if ((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z))
Log(Logs::Detail, Logs::AI, "Unable to move to next guard position. Probably rooted.");
}
else if ((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z))
{ {
if (moved) if (moved)
{ {
@ -445,102 +442,8 @@ float Mob::CalculateDistance(float x, float y, float z) {
return (float)sqrtf(((m_Position.x - x)*(m_Position.x - x)) + ((m_Position.y - y)*(m_Position.y - y)) + ((m_Position.z - z)*(m_Position.z - z))); return (float)sqrtf(((m_Position.x - x)*(m_Position.x - x)) + ((m_Position.y - y)*(m_Position.y - y)) + ((m_Position.z - z)*(m_Position.z - z)));
} }
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool check_z, bool calculate_heading) { void Mob::CalculateNewPosition(float x, float y, float z, float speed, bool check_z, bool calculate_heading) {
if (GetID() == 0) mMovementManager->NavigateTo(this, x, y, z, speed);
return true;
if (speed <= 0) {
SetCurrentSpeed(0);
return true;
}
bool WaypointChanged = false;
bool NodeReached = false;
glm::vec3 Goal = UpdatePath(
x, y, z, speed, WaypointChanged, NodeReached
);
if (WaypointChanged || NodeReached) {
calculate_heading = true;
entity_list.OpenDoorsNear(this);
}
SetCurrentSpeed(static_cast<int>(speed));
pRunAnimSpeed = speed;
#ifdef BOTS
if (IsClient() || IsBot())
#else
if (IsClient())
#endif
{
animation = speed * 0.55f;
}
//Setup Vectors
glm::vec3 tar(Goal.x, Goal.y, Goal.z);
glm::vec3 pos(m_Position.x, m_Position.y, m_Position.z);
double len = glm::distance(pos, tar);
if (len == 0) {
return true;
}
glm::vec3 dir = tar - pos;
glm::vec3 ndir = glm::normalize(dir);
double time_since_last = static_cast<double>(frame_time) / 1000.0;
double distance_moved = time_since_last * speed * 2.275f;
if (distance_moved > len) {
m_Position.x = Goal.x;
m_Position.y = Goal.y;
m_Position.z = Goal.z;
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), Goal.x, Goal.y, Goal.z);
}
if (check_z && fix_z_timer.Check() && (!IsEngaged() || flee_mode || currently_fleeing)) {
FixZ();
}
return true;
}
else {
glm::vec3 npos = pos + (ndir * static_cast<float>(distance_moved));
m_Position.x = npos.x;
m_Position.y = npos.y;
m_Position.z = npos.z;
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), npos.x, npos.y, npos.z);
}
}
if (calculate_heading) {
m_Position.w = CalculateHeadingToTarget(Goal.x, Goal.y);
}
if (check_z && fix_z_timer.Check() && !IsEngaged()) {
FixZ();
}
SetMoving(true);
m_Delta = glm::vec4(m_Position.x - pos.x, m_Position.y - pos.y, m_Position.z - pos.z, 0.0f);
if (IsClient()) {
SendPositionUpdate();
CastToClient()->ResetPositionTimer();
}
else {
SendPositionUpdate();
SetAppearance(eaStanding, false);
}
return true;
}
bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool check_z, bool calculate_heading) {
return MakeNewPositionAndSendUpdate(x, y, z, speed, check_z);
} }
void NPC::AssignWaypoints(int32 grid) void NPC::AssignWaypoints(int32 grid)
@ -620,7 +523,7 @@ void Mob::SendTo(float new_x, float new_y, float new_z) {
m_Position.z = new_z; m_Position.z = new_z;
Log(Logs::Detail, Logs::AI, "Sent To (%.3f, %.3f, %.3f)", new_x, new_y, new_z); Log(Logs::Detail, Logs::AI, "Sent To (%.3f, %.3f, %.3f)", new_x, new_y, new_z);
if (flymode == FlyMode1) if (flymode == GravityBehavior::Flying)
return; return;
//fix up pathing Z, this shouldent be needed IF our waypoints //fix up pathing Z, this shouldent be needed IF our waypoints
@ -678,13 +581,10 @@ float Mob::GetFixedZ(glm::vec3 destination, int32 z_find_offset) {
if (zone->HasMap() && RuleB(Map, FixZWhenMoving)) { if (zone->HasMap() && RuleB(Map, FixZWhenMoving)) {
if (flymode == 1 || flymode == 2) if (flymode != GravityBehavior::Ground)
return new_z; return new_z;
if (this->IsBoat()) if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position)))
return new_z;
if (zone->HasWaterMap() && zone->watermap->InWater(glm::vec3(m_Position)))
return new_z; return new_z;
/* /*

View File

@ -2258,7 +2258,7 @@ void Zone::DoAdventureActions()
const NPCType* tmp = database.LoadNPCTypesData(ds->data_id); const NPCType* tmp = database.LoadNPCTypesData(ds->data_id);
if(tmp) if(tmp)
{ {
NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), FlyMode3); NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), GravityBehavior::Ground);
npc->AddLootTable(); npc->AddLootTable();
if (npc->DropsGlobalLoot()) if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables(); npc->CheckGlobalLootTables();