diff --git a/zone/aa.cpp b/zone/aa.cpp index 9fa76a9d4..5a2b87bb5 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -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 0, GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), - FlyMode3); + GravityBehavior::Ground); if (followme) 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 0, GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), - FlyMode3); + GravityBehavior::Ground); if (followme) 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_texture2 = 0; - auto npca = new NPC(make_npc, 0, GetPosition(), FlyMode3); + auto npca = new NPC(make_npc, 0, GetPosition(), GravityBehavior::Ground); if(!npca->GetSwarmInfo()){ auto nSI = new SwarmPet; diff --git a/zone/aggro.cpp b/zone/aggro.cpp index f8162322e..30e3b9e0f 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -966,7 +966,7 @@ bool Mob::CombatRange(Mob* other) if (_DistNoRoot <= size_mod) { //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; } diff --git a/zone/aura.cpp b/zone/aura.cpp index 8a885c67b..ccb37a3a3 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -6,7 +6,7 @@ #include "raids.h" 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) { GiveNPCTypeData(type_data); // we will delete this later on diff --git a/zone/client.cpp b/zone/client.cpp index 8477c6fc6..0bc42f8b0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -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 0, GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), - FlyMode3); + GravityBehavior::Ground); if(!swarm_pet_npc->GetSwarmInfo()){ auto nSI = new SwarmPet; diff --git a/zone/command.cpp b/zone/command.cpp index 4cc17c6ca..9d4604dc2 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -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("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("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("freeze", "- Freeze your target", 80, command_freeze) || 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(atoi(row[4])), static_cast(atoi(row[5])) ); - npc->SetFlyMode(1); + npc->SetFlyMode(GravityBehavior::Flying); 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) { - 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')) - c->Message(0, "#flymode [0/1/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/3/4/5]"); else { - if(c->GetTarget() && c->GetTarget()->IsClient()) - t=c->GetTarget()->CastToClient(); - t->SendAppearancePacket(AT_Levitate, atoi(sep->arg[1])); - if (sep->arg[1][0] == '1') - c->Message(0, "Turning %s's Flymode ON", t->GetName()); - else if (sep->arg[1][0] == '2') - c->Message(0, "Turning %s's Flymode LEV", t->GetName()); - else - c->Message(0, "Turning %s's Flymode OFF", t->GetName()); + if (c->GetTarget()) { + t = c->GetTarget(); + } + + int fm = atoi(sep->arg[1]); + + t->SetFlyMode(static_cast(fm)); + t->SendAppearancePacket(AT_Levitate, fm); + 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; if ((tmp = database.LoadNPCTypesData(atoi(sep->arg[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)) npc->SetNPCFactionID(atoi(sep->arg[2])); diff --git a/zone/common.h b/zone/common.h index df6b22637..030ad716a 100644 --- a/zone/common.h +++ b/zone/common.h @@ -206,8 +206,6 @@ typedef enum { //fear states fearStateStuck //I cannot move somehow... } FearState; -enum { FlyMode0 = 0, FlyMode1 = 1, Flymode2 = 2, FlyMode3 = 3 }; - // This is actually FlyMode, from MQ2 enum GravityBehavior { Ground, diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 18c84ccdd..e1f2c1c12 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3083,9 +3083,9 @@ XS(XS__FlyMode); XS(XS__FlyMode) { dXSARGS; 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); XSRETURN_EMPTY; diff --git a/zone/forage.cpp b/zone/forage.cpp index e5248cf01..ede05c59f 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -284,7 +284,7 @@ void Client::GoFish() if (tmp != nullptr) { auto positionNPC = GetPosition(); positionNPC.x = positionNPC.x + 3; - auto npc = new NPC(tmp, nullptr, positionNPC, FlyMode3); + auto npc = new NPC(tmp, nullptr, positionNPC, GravityBehavior::Ground); npc->AddLootTable(); if (npc->DropsGlobalLoot()) npc->CheckGlobalLootTables(); diff --git a/zone/horse.cpp b/zone/horse.cpp index fe5762d5a..d7d242e83 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -30,7 +30,7 @@ std::map Horse::horse_types; LinkedList horses_auto_delete; 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. strn0cpy(name, _owner->GetCleanName(), 55); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index da62dc305..f65e6f2ad 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -891,7 +891,7 @@ void lua_flag_instance_by_raid_leader(uint32 zone, uint32 version) { } void lua_fly_mode(int flymode) { - quest_manager.FlyMode(flymode); + quest_manager.FlyMode(static_cast(flymode)); } 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(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); entity_list.AddNPC(npc); } diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 50d973b61..4a5932db2 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1124,15 +1124,9 @@ double Lua_Mob::CalculateHeadingToTarget(double in_x, double in_y) { return self->CalculateHeadingToTarget(static_cast(in_x), static_cast(in_y)); } -bool Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed) { - Lua_Safe_Call_Bool(); - return self->CalculateNewPosition(static_cast(x), static_cast(y), static_cast(z), static_cast(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(x), static_cast(y), static_cast(z), static_cast(speed), - check_z); +void Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed) { + Lua_Safe_Call_Void(); + self->CalculateNewPosition(static_cast(x), static_cast(y), static_cast(z), static_cast(speed)); } 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) { Lua_Safe_Call_Void(); - self->SetFlyMode(in); + self->SetFlyMode(static_cast(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("SetHeading", (void(Lua_Mob::*)(double))&Lua_Mob::SetHeading) .def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget) - .def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition) - .def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::CalculateNewPosition) + .def("CalculateNewPosition", (void(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition) .def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance) .def("SendTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendTo) .def("SendToFixZ", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendToFixZ) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 564277ac7..ed3f869ed 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -240,8 +240,7 @@ public: void FaceTarget(Lua_Mob target); void SetHeading(double in); double CalculateHeadingToTarget(double in_x, double in_y); - bool CalculateNewPosition(double x, double y, double z, double speed); - bool CalculateNewPosition(double x, double y, double z, double speed, bool check_z); + void CalculateNewPosition(double x, double y, double z, double speed); float CalculateDistance(double x, double y, double z); void SendTo(double x, double y, double z); void SendToFixZ(double x, double y, double z); diff --git a/zone/merc.cpp b/zone/merc.cpp index 7cb480a2f..09bd78622 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -29,7 +29,7 @@ extern volatile bool is_zone_loaded; #endif 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_mana = d->Mana; diff --git a/zone/mob.cpp b/zone/mob.cpp index 63a1c47ca..3921d91f5 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -427,7 +427,7 @@ Mob::Mob(const char* in_name, m_TargetRing = glm::vec3(); - flymode = FlyMode3; + flymode = GravityBehavior::Ground; DistractedFromGrid = false; hate_list.SetHateOwner(this); @@ -1167,7 +1167,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.flymode = flymode; if(IsBoat()) { - ns->spawn.flymode = 1; + ns->spawn.flymode = GravityBehavior::Floating; } ns->spawn.lastName[0] = '\0'; @@ -3566,17 +3566,9 @@ bool Mob::EntityVariableExists(const char *id) return false; } -void Mob::SetFlyMode(uint8 flymode) +void Mob::SetFlyMode(GravityBehavior flymode) { - if(IsClient() && flymode >= 0 && flymode < 3) - { - this->SendAppearancePacket(AT_Levitate, flymode); - } - else if(IsNPC() && flymode >= 0 && flymode <= 3) - { - this->SendAppearancePacket(AT_Levitate, flymode); - this->CastToNPC()->SetFlyMode(flymode); - } + this->flymode = flymode; } bool Mob::IsNimbusEffectActive(uint32 nimbus_effect) @@ -6014,6 +6006,13 @@ float Mob::GetDefaultRaceSize() const { 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 bool Mob::JoinHealRotationTargetPool(std::shared_ptr* heal_rotation) diff --git a/zone/mob.h b/zone/mob.h index 52d404049..82aaa81e4 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -529,7 +529,7 @@ public: inline const float GetHeading() const { return m_Position.w; } inline const float GetSize() const { return size; } inline const float GetBaseSize() const { return base_size; } - inline const int8 GetFlyMode() const { return static_cast(flymode); } + inline const GravityBehavior GetFlyMode() const { return flymode; } bool IsBoat() const; //Group @@ -567,8 +567,8 @@ public: void SetSpawned() { spawned = true; }; bool Spawned() { return spawned; }; virtual bool ShouldISpawnFor(Client *c) { return true; } - void SetFlyMode(uint8 flymode); - inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y; + void SetFlyMode(GravityBehavior flymode); + inline void Teleport(const glm::vec3 &NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y; m_Position.z = NewPosition.z; }; void TryMoveAlong(float distance, float angle, bool send = true); void ProcessForcedMovement(); @@ -801,8 +801,9 @@ public: void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true); inline EmuAppearance GetAppearance() const { return _appearance; } inline const int GetAnimation() const { return animation; } + inline void SetAnimation(int a) { animation = a; } 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; } void SetDestructibleObject(bool in) { destructibleobject = in; } @@ -968,13 +969,14 @@ public: inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);} 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 GetGroundZ(float new_x, float new_y, float z_offset=0.0); void SendTo(float new_x, float new_y, float new_z); void SendToFixZ(float new_x, float new_y, float new_z); float GetZOffset() 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); 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::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 #ifdef BOTS 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 _GetRunSpeed() 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_PursueCastCheck() { return(false); } @@ -1288,7 +1292,6 @@ protected: void CalculateNewFearpoint(); float FindGroundZ(float new_x, float new_y, 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); 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 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; int QGVarDuration(const char *fmt); void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 9ecb96719..b9582d712 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1520,7 +1520,6 @@ void Mob::AI_Process() { } else { - bool waypoint_changed, node_reached; auto &Goal = owner->GetPosition(); CalculateNewPosition(Goal.x, Goal.y, Goal.z, pet_speed, true); @@ -1792,16 +1791,13 @@ void NPC::AI_DoMovement() { } 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))) { - CP2Moved = CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, move_speed); - } - else { - CP2Moved = false; - } + bool at_gp = CalculateDistance(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z) < 0.1f; - if (!CP2Moved) { + if (at_gp) { if (moved) { Log(Logs::Detail, Logs::AI, diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 00a2536bb..2b5821ab0 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -4,19 +4,20 @@ #include "../common/timer.h" #include +#include #include -struct MobMovementEntry +extern uint64_t frame_time; + +struct MovementEntry { - Mob *m; int animation; float heading; bool dirty; double last_sent_time; double last_sent_time_long_distance; - MobMovementEntry(Mob *m) { - this->m = m; + MovementEntry(Mob *m) { animation = 0; heading = m->GetHeading(); 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 { - std::vector Entries; + std::map Entries; + std::map MoveEntries; std::vector Clients; }; @@ -44,9 +63,18 @@ void MobMovementManager::Process() { double current_time = static_cast(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) { - SendUpdate(ent.m, ent.animation, ent.heading); + SendUpdate(iter.first, ent.animation, ent.heading); ent.dirty = false; 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; 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; } 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; } } @@ -70,20 +98,14 @@ void MobMovementManager::Process() 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) { - auto iter = _impl->Entries.begin(); - while (iter != _impl->Entries.end()) { - auto &ent = *iter; - if (ent.m == m) { - _impl->Entries.erase(iter); - return; - } - ++iter; - } + _impl->Entries.erase(m); + _impl->MoveEntries.erase(m); } void MobMovementManager::AddClient(Client *c) @@ -107,60 +129,62 @@ void MobMovementManager::RemoveClient(Client *c) void MobMovementManager::SendPosition(Mob *who) { - auto iter = _impl->Entries.begin(); - while (iter != _impl->Entries.end()) { - 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; - } + auto iter = _impl->Entries.find(who); + auto &ent = iter->second; - return; - } - - ++iter; + auto anim = 0; + auto heading = who->GetHeading(); + + 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) { - auto iter = _impl->Entries.begin(); - while (iter != _impl->Entries.end()) { - auto &ent = *iter; + auto iter = _impl->Entries.find(who); + auto &ent = iter->second; - if (ent.m == who) { - auto anim = 0; - auto heading = who->GetHeading(); - if (who->IsMoving()) { - if (who->IsClient()) { - anim = who->GetAnimation(); - } - else { - 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; + auto anim = 0; + auto heading = who->GetHeading(); + if (who->IsMoving()) { + if (who->IsClient()) { + anim = who->GetAnimation(); + } + else { + anim = who->GetRunAnimSpeed(); } - - ++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) @@ -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(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(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(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); + } +} diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h index 69ea2ee80..e45bcec55 100644 --- a/zone/mob_movement_manager.h +++ b/zone/mob_movement_manager.h @@ -16,6 +16,8 @@ public: void SendPosition(Mob *who); 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 inst; @@ -32,6 +34,7 @@ private: void SendUpdate(Mob *who, int anim, float heading); void SendUpdateShortDistance(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; std::unique_ptr _impl; diff --git a/zone/npc.cpp b/zone/npc.cpp index bf1508858..0bb1bc10d 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -57,7 +57,7 @@ extern Zone* zone; extern volatile bool is_zone_loaded; 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, d->lastname, d->max_hp, @@ -977,7 +977,7 @@ bool NPC::SpawnZoneController(){ point.y = 1000; 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); entity_list.AddNPC(npc); @@ -1020,7 +1020,7 @@ NPC * NPC::SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32 npc_type->findable = true; 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); 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->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); 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() SetAttackTimer(); CalcAC(); -} \ No newline at end of file +} diff --git a/zone/npc.h b/zone/npc.h index ec2676f60..7d2c5a9c8 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -106,7 +106,7 @@ public: static bool SpawnZoneController(); 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(); @@ -229,9 +229,6 @@ public: EmuAppearance GetGuardPointAnim() const { return guard_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 GetSecSkill() const { return sec_melee_type; } uint8 GetRangedSkill() const { return ranged_type; } diff --git a/zone/pathfinder_waypoint.cpp b/zone/pathfinder_waypoint.cpp index 86dd4a4a4..c3a85418e 100644 --- a/zone/pathfinder_waypoint.cpp +++ b/zone/pathfinder_waypoint.cpp @@ -557,7 +557,7 @@ void PathfinderWaypoint::ShowNode(const Node &n) { npc_type->findable = 1; 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); entity_list.AddNPC(npc, true, true); diff --git a/zone/pathing.cpp b/zone/pathing.cpp index ff1963720..a2885c1f1 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -13,7 +13,7 @@ void AdjustRoute(std::list &nodes, int flymode, float of } 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); if (best_z != BEST_Z_INVALID) { 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; - if (flymode == 1) { + if (flymode == GravityBehavior::Flying) { AtNextNode = DistanceSquared(From, (*Route.begin()).pos) < 4.0f; } else { diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index e61f6ec81..2e2c9a6cb 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -5531,15 +5531,13 @@ XS(XS_Mob_CalculateNewPosition) { dXSARGS; if (items < 5 || items > 6) 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; - bool RETVAL; float x = (float) SvNV(ST(1)); float y = (float) SvNV(ST(2)); float z = (float) SvNV(ST(3)); float speed = (float) SvNV(ST(4)); - bool checkZ; if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV *) SvRV(ST(0))); @@ -5549,17 +5547,10 @@ XS(XS_Mob_CalculateNewPosition) { if (THIS == nullptr) 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); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); + THIS->CalculateNewPosition(x, y, z, speed); } - XSRETURN(1); + XSRETURN_EMPTY; } 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) { dXSARGS; 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; - uint8 flymode = (uint8) SvIV(ST(1)); + GravityBehavior flymode = (GravityBehavior) SvIV(ST(1)); if (sv_derived_from(ST(0), "Mob")) { 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, "CheckAggro"), XS_Mob_CheckAggro, 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, "SendTo"), XS_Mob_SendTo, file, "$$$$"); newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$"); diff --git a/zone/pets.cpp b/zone/pets.cpp index e4f7c417b..a436b0097 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -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 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) -: 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); typeofpet = type; diff --git a/zone/position.cpp b/zone/position.cpp index 22885b4b1..83d1491b2 100644 --- a/zone/position.cpp +++ b/zone/position.cpp @@ -160,3 +160,9 @@ float GetReciprocalHeading(const float heading) 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; +} diff --git a/zone/position.h b/zone/position.h index 4081f50e0..479f43bb4 100644 --- a/zone/position.h +++ b/zone/position.h @@ -50,4 +50,6 @@ float DistanceSquaredNoZ(const glm::vec4& point1, const glm::vec4& point2); float GetReciprocalHeading(const glm::vec4& point1); float GetReciprocalHeading(const float heading); +bool IsPositionEqual(float x1, float y1, float z1, float x2, float y2, float z2); + #endif diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 1393b0221..39d5b9f5d 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -208,7 +208,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p const NPCType* tmp = 0; 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(); if (npc->DropsGlobalLoot()) npc->CheckGlobalLootTables(); @@ -232,7 +232,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v const NPCType* tmp = 0; 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(); if (npc->DropsGlobalLoot()) npc->CheckGlobalLootTables(); @@ -308,22 +308,22 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id) found_spawn->SetCurrentNPCID(npcid); 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); - npc->AddLootTable(); - if (npc->DropsGlobalLoot()) - npc->CheckGlobalLootTables(); - npc->SetSp2(found_spawn->SpawnGroupID()); - entity_list.AddNPC(npc); - entity_list.LimitAddNPC(npc); + found_spawn->SetNPCPointer(npc); + npc->AddLootTable(); + if (npc->DropsGlobalLoot()) + npc->CheckGlobalLootTables(); + npc->SetSp2(found_spawn->SpawnGroupID()); + entity_list.AddNPC(npc); + entity_list.LimitAddNPC(npc); - if (sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay && - sg->min_delay) - npc->AI_SetRoambox(sg->roamdist, sg->roambox[0], sg->roambox[1], sg->roambox[2], sg->roambox[3], - sg->delay, sg->min_delay); - if (zone->InstantGrids()) { - found_spawn->LoadGrid(); + if (sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay && + sg->min_delay) + npc->AI_SetRoambox(sg->roamdist, sg->roambox[0], sg->roambox[1], sg->roambox[2], sg->roambox[3], + sg->delay, sg->min_delay); + if (zone->InstantGrids()) { + found_spawn->LoadGrid(); } return npc; @@ -1686,7 +1686,7 @@ void QuestManager::respawn(int npcTypeID, int grid) { const NPCType* npcType = nullptr; 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(); if (owner->CastToNPC()->DropsGlobalLoot()) owner->CastToNPC()->CheckGlobalLootTables(); @@ -2827,22 +2827,18 @@ bool QuestManager::IsRunning() return owner->IsRunning(); } -void QuestManager::FlyMode(uint8 flymode) +void QuestManager::FlyMode(GravityBehavior flymode) { QuestManagerCurrentQuestVars(); if(initiator) { - if (flymode >= 0 && flymode < 3) { - initiator->SendAppearancePacket(AT_Levitate, flymode); - return; - } + initiator->SendAppearancePacket(AT_Levitate, static_cast(flymode)); + initiator->SetFlyMode(flymode); } - if(owner) + else if(owner) { - if (flymode >= 0 && flymode < 3) { - owner->SendAppearancePacket(AT_Levitate, flymode); - return; - } + owner->SendAppearancePacket(AT_Levitate, static_cast(flymode)); + owner->SetFlyMode(flymode); } } diff --git a/zone/questmgr.h b/zone/questmgr.h index a3b9fac43..d227b27d1 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -249,7 +249,7 @@ public: const char* getguildnamebyid(int guild_id); void SetRunning(bool val); bool IsRunning(); - void FlyMode(uint8 flymode); + void FlyMode(GravityBehavior flymode); uint8 FactionValue(); 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); diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 71101dff8..05e7e7926 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -255,7 +255,7 @@ bool Spawn2::Process() { } 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); diff --git a/zone/trap.cpp b/zone/trap.cpp index 687d3ded3..191d80fce 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -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 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(); if (new_npc->DropsGlobalLoot()) 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 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(); if (new_npc->DropsGlobalLoot()) new_npc->CheckGlobalLootTables(); @@ -469,7 +469,7 @@ void Trap::CreateHiddenTrigger() make_npc->trackable = 0; make_npc->level = level; 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); entity_list.AddNPC(npca); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 74bb57c36..e6fbbef5a 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -30,12 +30,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "quest_parser_collection.h" #include "water_map.h" #include "fastmath.h" +#include "mob_movement_manager.h" #include #include extern FastMath g_Math; -extern uint64_t frame_time; struct wp_distance { @@ -427,11 +427,8 @@ void NPC::SaveGuardSpot(bool iClearGuardSpot) { } void NPC::NextGuardPosition() { - if (!CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed())) { - SetHeading(m_GuardPoint.w); - 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)) + CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed()); + if ((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z)) { 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))); } -bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool check_z, bool calculate_heading) { - if (GetID() == 0) - 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(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(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(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 Mob::CalculateNewPosition(float x, float y, float z, float speed, bool check_z, bool calculate_heading) { + mMovementManager->NavigateTo(this, x, y, z, speed); } 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; Log(Logs::Detail, Logs::AI, "Sent To (%.3f, %.3f, %.3f)", new_x, new_y, new_z); - if (flymode == FlyMode1) + if (flymode == GravityBehavior::Flying) return; //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 (flymode == 1 || flymode == 2) + if (flymode != GravityBehavior::Ground) return new_z; - if (this->IsBoat()) - return new_z; - - if (zone->HasWaterMap() && zone->watermap->InWater(glm::vec3(m_Position))) + if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position))) return new_z; /* diff --git a/zone/zone.cpp b/zone/zone.cpp index 2acb0fa6b..1781dd819 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -2258,7 +2258,7 @@ void Zone::DoAdventureActions() const NPCType* tmp = database.LoadNPCTypesData(ds->data_id); 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(); if (npc->DropsGlobalLoot()) npc->CheckGlobalLootTables();