diff options
author | Treeston <treeston.mmoc@gmail.com> | 2018-04-06 18:09:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-06 18:09:55 +0200 |
commit | 2a84562dc85516f432bb1e5de9add23c28b26ce4 (patch) | |
tree | 2b7414c164370c5144586beb76946db41061fad7 | |
parent | 9f03743d2d803cba553b2f95a87b106bf5e3f672 (diff) |
Core/Movement: Replace old TargetedMovementGenerator into ChaseMovementGenerator and FollowMovementGenerator, full rewrite for both.
- Chase to angle is now functional. Pets use this to chase behind the target. Closes #19925.
- Chase to arbitrary range interval works. Not used anywhere, but you can technically make hunter-like mobs.
- Pets now follow the hunter cleanly and without stutter stepping. Also fix some other things. Closes #8924.
28 files changed, 700 insertions, 768 deletions
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 1240ce4205f..195aa22ca22 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -89,6 +89,9 @@ inline T RoundToInterval(T& num, T floor, T ceil) return num = std::min(std::max(num, floor), ceil); } +template <class T> +inline T square(T x) { return x*x; } + // UTF8 handling TC_COMMON_API bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index b6b7aa09792..a16ffc6721d 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -482,7 +482,7 @@ void PetAI::DoAttack(Unit* target, bool chase) ClearCharmInfoFlags(); me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(target, me->GetPetChaseDistance()); + me->GetMotionMaster()->MoveChase(target, me->GetPetChaseDistance(), (float)M_PI); } else // (Stay && ((Aggressive || Defensive) && In Melee Range))) { diff --git a/src/server/game/Movement/FollowerReference.cpp b/src/server/game/Entities/Object/G3DPosition.hpp index 9921b9bb5ee..bfca424cb19 100644 --- a/src/server/game/Movement/FollowerReference.cpp +++ b/src/server/game/Entities/Object/G3DPosition.hpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,21 +15,15 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Unit.h" -#include "TargetedMovementGenerator.h" -#include "FollowerReference.h" +#ifndef TRINITY_G3DPOSITION_HPP +#define TRINITY_G3DPOSITION_HPP -void FollowerReference::targetObjectBuildLink() -{ - getTarget()->addFollower(this); -} +#include "Position.h" +#include <G3D/Vector3.h> +#include "Errors.h" -void FollowerReference::targetObjectDestroyLink() -{ - getTarget()->removeFollower(this); -} +inline G3D::Vector3 PositionToVector3(Position p) { return { p.m_positionX, p.m_positionY, p.m_positionZ }; } +inline G3D::Vector3 PositionToVector3(Position const* p) { return { ASSERT_NOTNULL(p)->m_positionX, p->m_positionY, p->m_positionZ }; } +inline Position Vector3ToPosition(G3D::Vector3 v) { return { v.x, v.y, v.z }; } -void FollowerReference::sourceObjectDestroyLink() -{ - GetSource()->stopFollowing(); -} +#endif diff --git a/src/server/game/Entities/Pet/PetDefines.h b/src/server/game/Entities/Pet/PetDefines.h index dd359dc6ee4..39475f49d40 100644 --- a/src/server/game/Entities/Pet/PetDefines.h +++ b/src/server/game/Entities/Pet/PetDefines.h @@ -75,6 +75,6 @@ enum PetTalk }; #define PET_FOLLOW_DIST 1.0f -#define PET_FOLLOW_ANGLE float(M_PI/2) +#define PET_FOLLOW_ANGLE float(M_PI) #endif diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0b31a125cd8..b5d04826d85 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17,6 +17,7 @@ */ #include "Unit.h" +#include "AbstractFollower.h" #include "Battlefield.h" #include "BattlefieldMgr.h" #include "Battleground.h" @@ -538,14 +539,14 @@ bool Unit::IsWithinCombatRange(Unit const* obj, float dist2compare) const return distsq < maxdist * maxdist; } -bool Unit::IsWithinMeleeRange(Unit const* obj) const +bool Unit::IsWithinMeleeRangeAt(Position const& pos, Unit const* obj) const { if (!obj || !IsInMap(obj) || !InSamePhase(obj)) return false; - float dx = GetPositionX() - obj->GetPositionX(); - float dy = GetPositionY() - obj->GetPositionY(); - float dz = GetPositionZ() - obj->GetPositionZ(); + float dx = pos.GetPositionX() - obj->GetPositionX(); + float dy = pos.GetPositionY() - obj->GetPositionY(); + float dz = pos.GetPositionZ() - obj->GetPositionZ(); float distsq = dx*dx + dy*dy + dz*dz; float maxdist = GetMeleeRange(obj); @@ -8509,25 +8510,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype) { // Set creature speed rate if (GetTypeId() == TYPEID_UNIT) - { - Unit* pOwner = GetCharmerOrOwner(); - if ((IsPet() || IsGuardian()) && !IsInCombat() && pOwner) // Must check for owner or crash on "Tame Beast" - { - // For every yard over 5, increase speed by 0.01 - // to help prevent pet from lagging behind and despawning - float dist = GetDistance(pOwner); - float base_rate = 1.00f; // base speed is 100% of owner speed - - if (dist < 5) - dist = 5; - - float mult = base_rate + ((dist - 5) * 0.01f); - - speed *= pOwner->GetSpeedRate(mtype) * mult; // pets derive speed from owner when not in combat - } - else - speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached - } + speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached // Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need /// @todo possible affect only on MOVE_RUN @@ -8551,11 +8534,27 @@ void Unit::UpdateSpeed(UnitMoveType mtype) break; } - // for creature case, we check explicit if mob searched for assistance - if (GetTypeId() == TYPEID_UNIT) + if (Creature* creature = ToCreature()) { - if (ToCreature()->HasSearchedAssistance()) + // for creature case, we check explicit if mob searched for assistance + if (creature->HasSearchedAssistance()) speed *= 0.66f; // best guessed value, so this will be 33% reduction. Based off initial speed, mob can then "run", "walk fast" or "walk". + + if (creature->HasUnitTypeMask(UNIT_MASK_MINION) && !creature->IsInCombat()) + { + MovementGenerator* top = creature->GetMotionMaster()->top(); + if (top && top->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE) + { + Unit* followed = ASSERT_NOTNULL(dynamic_cast<AbstractFollower*>(top))->GetTarget(); + if (followed && followed->GetGUID() == GetOwnerGUID() && !followed->IsInCombat()) + { + float ownerSpeed = followed->GetSpeedRate(mtype); + if (speed < ownerSpeed || creature->IsWithinDist3d(followed, 10.0f)) + speed = ownerSpeed; + speed *= std::min(std::max(1.0f, 0.75f + (GetDistance(followed) - PET_FOLLOW_DIST) * 0.05f), 1.3f); + } + } + } } // Apply strongest slow aura mod to speed @@ -8656,6 +8655,12 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate) } } +void Unit::RemoveAllFollowers() +{ + while (!m_followingMe.empty()) + (*m_followingMe.begin())->SetTarget(nullptr); +} + bool Unit::IsGhouled() const { return HasAura(SPELL_DK_RAISE_ALLY); @@ -9437,6 +9442,8 @@ void Unit::RemoveFromWorld() RemoveAreaAurasDueToLeaveWorld(); + RemoveAllFollowers(); + if (IsCharmed()) RemoveCharmedBy(nullptr); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index f01c476292a..1a910ba48b3 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -20,8 +20,6 @@ #define __UNIT_H #include "Object.h" -#include "FollowerReference.h" -#include "FollowerRefManager.h" #include "CombatManager.h" #include "OptionalFwd.h" #include "SpellAuraDefines.h" @@ -61,6 +59,7 @@ enum InventorySlot NULL_SLOT = 255 }; +struct AbstractFollower; struct FactionTemplateEntry; struct LiquidData; struct LiquidTypeEntry; @@ -789,7 +788,8 @@ class TC_GAME_API Unit : public WorldObject virtual void SetCanDualWield(bool value) { m_canDualWield = value; } float GetCombatReach() const override { return m_floatValues[UNIT_FIELD_COMBATREACH]; } bool IsWithinCombatRange(Unit const* obj, float dist2compare) const; - bool IsWithinMeleeRange(Unit const* obj) const; + bool IsWithinMeleeRange(Unit const* obj) const { return IsWithinMeleeRangeAt(GetPosition(), obj); } + bool IsWithinMeleeRangeAt(Position const& pos, Unit const* obj) const; float GetMeleeRange(Unit const* target) const; virtual SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const = 0; uint32 m_extraAttacks; @@ -1526,8 +1526,9 @@ class TC_GAME_API Unit : public WorldObject float CalculateSpellpowerCoefficientLevelPenalty(SpellInfo const* spellInfo) const; - void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } - void removeFollower(FollowerReference* /*pRef*/) { /* nothing to do yet */ } + void FollowerAdded(AbstractFollower* f) { m_followingMe.insert(f); } + void FollowerRemoved(AbstractFollower* f) { m_followingMe.erase(f); } + void RemoveAllFollowers(); MotionMaster* GetMotionMaster() { return i_motionMaster; } MotionMaster const* GetMotionMaster() const { return i_motionMaster; } @@ -1781,7 +1782,7 @@ class TC_GAME_API Unit : public WorldObject friend class ThreatManager; ThreatManager m_threatManager; - FollowerRefManager m_FollowingRefManager; + std::unordered_set<AbstractFollower*> m_followingMe; Unit* m_comboTarget; int8 m_comboPoints; diff --git a/src/server/game/Loot/LootItemStorage.cpp b/src/server/game/Loot/LootItemStorage.cpp index bd3d4653d4f..d452d1d556d 100644 --- a/src/server/game/Loot/LootItemStorage.cpp +++ b/src/server/game/Loot/LootItemStorage.cpp @@ -1,19 +1,19 @@ /* -* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see <http://www.gnu.org/licenses/>. -*/ + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ #include "LootItemStorage.h" #include "DatabaseEnv.h" diff --git a/src/server/game/Loot/LootItemStorage.h b/src/server/game/Loot/LootItemStorage.h index 898b2734cae..7ea13c5cd9c 100644 --- a/src/server/game/Loot/LootItemStorage.h +++ b/src/server/game/Loot/LootItemStorage.h @@ -1,19 +1,19 @@ /* -* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see <http://www.gnu.org/licenses/>. -*/ + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ #ifndef __LOOTITEMSTORAGE_H #define __LOOTITEMSTORAGE_H diff --git a/src/server/game/Movement/FollowerRefManager.h b/src/server/game/Movement/AbstractFollower.cpp index 53ed9acf6c9..ca02ac93bca 100644 --- a/src/server/game/Movement/FollowerRefManager.h +++ b/src/server/game/Movement/AbstractFollower.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -15,17 +14,18 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "AbstractFollower.h" +#include "Unit.h" -#ifndef _FOLLOWERREFMANAGER -#define _FOLLOWERREFMANAGER - -#include "RefManager.h" - -class Unit; -class TargetedMovementGeneratorBase; - -class FollowerRefManager : public RefManager<Unit, TargetedMovementGeneratorBase> +void AbstractFollower::SetTarget(Unit* unit) { + if (unit == _target) + return; -}; -#endif + if (_target) + _target->FollowerRemoved(this); + _target = unit; + if (_target) + _target->FollowerAdded(this); +} diff --git a/src/server/game/Movement/FollowerReference.h b/src/server/game/Movement/AbstractFollower.h index c7af0f13649..cde75aadaf5 100644 --- a/src/server/game/Movement/FollowerReference.h +++ b/src/server/game/Movement/AbstractFollower.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,19 +15,22 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _FOLLOWERREFERENCE_H -#define _FOLLOWERREFERENCE_H +#ifndef TRINITY_ABSTRACTFOLLOWER_H +#define TRINITY_ABSTRACTFOLLOWER_H -#include "Reference.h" - -class TargetedMovementGeneratorBase; class Unit; -class FollowerReference : public Reference<Unit, TargetedMovementGeneratorBase> +struct AbstractFollower { - protected: - void targetObjectBuildLink() override; - void targetObjectDestroyLink() override; - void sourceObjectDestroyLink() override; + public: + AbstractFollower(Unit* target = nullptr) { SetTarget(target); } + ~AbstractFollower() { SetTarget(nullptr); } + + void SetTarget(Unit* unit); + Unit* GetTarget() const { return _target; } + + private: + Unit* _target = nullptr; }; + #endif diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index cb00f455959..62396a0a315 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -17,12 +17,14 @@ */ #include "MotionMaster.h" +#include "ChaseMovementGenerator.h" #include "ConfusedMovementGenerator.h" #include "Creature.h" #include "CreatureAISelector.h" #include "DBCStores.h" #include "FleeingMovementGenerator.h" #include "FlightPathMovementGenerator.h" +#include "FollowMovementGenerator.h" #include "FormationMovementGenerator.h" #include "HomeMovementGenerator.h" #include "IdleMovementGenerator.h" @@ -36,7 +38,6 @@ #include "RandomMovementGenerator.h" #include "ScriptSystem.h" #include "SplineChainMovementGenerator.h" -#include "TargetedMovementGenerator.h" #include "Unit.h" #include "WaypointDefines.h" #include "WaypointMovementGenerator.h" @@ -219,7 +220,7 @@ void MotionMaster::MoveTargetedHome() if (target) { TC_LOG_DEBUG("misc", "Following %s (GUID: %u).", target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : ((Creature*)target)->GetSpawnId()); - Mutate(new FollowMovementGenerator<Creature>(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); + Mutate(new FollowMovementGenerator(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); } } else @@ -237,53 +238,33 @@ void MotionMaster::MoveRandom(float spawndist) } } -void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot) +void MotionMaster::MoveFollow(Unit* target, float dist, ChaseAngle angle, MovementSlot slot) { // ignore movement request if target not exist if (!target || target == _owner) return; - //_owner->AddUnitState(UNIT_STATE_FOLLOW); - if (_owner->GetTypeId() == TYPEID_PLAYER) - { - TC_LOG_DEBUG("misc", "Player (GUID: %u) follows %s (GUID: %u).", _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); - Mutate(new FollowMovementGenerator<Player>(target, dist, angle), slot); - } - else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) follows %s (GUID: %u).", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); - Mutate(new FollowMovementGenerator<Creature>(target, dist, angle), slot); - } + TC_LOG_DEBUG("misc", "%s (Entry: %u, GUID: %u) follows %s (Entry %u, GUID: %u).", + _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", + _owner->GetEntry(), _owner->GetGUID().GetCounter(), + target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", + target->GetEntry(), target->GetGUID().GetCounter()); + + Mutate(new FollowMovementGenerator(target, dist, angle), slot); } -void MotionMaster::MoveChase(Unit* target, float dist, float angle) +void MotionMaster::MoveChase(Unit* target, Optional<ChaseRange> dist, Optional<ChaseAngle> angle) { // ignore movement request if target not exist if (!target || target == _owner) return; - //_owner->ClearUnitState(UNIT_STATE_FOLLOW); - if (_owner->GetTypeId() == TYPEID_PLAYER) - { - TC_LOG_DEBUG("misc", "Player (GUID: %u) chase to %s (GUID: %u)", - _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); - Mutate(new ChaseMovementGenerator<Player>(target, dist, angle), MOTION_SLOT_ACTIVE); - } - else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) chase to %s (GUID: %u)", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); - Mutate(new ChaseMovementGenerator<Creature>(target, dist, angle), MOTION_SLOT_ACTIVE); - } + TC_LOG_DEBUG("misc", "%s (Entry: %u, GUID: %u) chase to %s (Entry: %u, GUID: %u)", + _owner->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature", + _owner->GetEntry(), _owner->GetGUID().GetCounter(), + target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", + target->GetEntry(), target->GetGUID().GetCounter()); + Mutate(new ChaseMovementGenerator(target, dist, angle), MOTION_SLOT_ACTIVE); } void MotionMaster::MoveConfused() diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index c5b5e9fb8c8..fa465319cdb 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -21,6 +21,7 @@ #include "Common.h" #include "Errors.h" +#include "ObjectDefines.h" #include "ObjectGuid.h" #include "Optional.h" #include "Position.h" @@ -84,6 +85,35 @@ enum RotateDirection ROTATE_DIRECTION_RIGHT }; +struct ChaseRange +{ + ChaseRange(float range) : MinRange(range > CONTACT_DISTANCE ? 0 : range - CONTACT_DISTANCE), MinTolerance(range), MaxRange(range + CONTACT_DISTANCE), MaxTolerance(range) {} + ChaseRange(float min, float max) : MinRange(min), MinTolerance(std::min(min + CONTACT_DISTANCE, (min + max) / 2)), MaxRange(max), MaxTolerance(std::max(max - CONTACT_DISTANCE, MinTolerance)) {} + ChaseRange(float min, float tMin, float tMax, float max) : MinRange(min), MinTolerance(tMin), MaxRange(max), MaxTolerance(tMax) {} + + // this contains info that informs how we should path! + float MinRange; // we have to move if we are within this range... (min. attack range) + float MinTolerance; // ...and if we are, we will move this far away + float MaxRange; // we have to move if we are outside this range... (max. attack range) + float MaxTolerance; // ...and if we are, we will move into this range +}; + +struct ChaseAngle +{ + ChaseAngle(float angle, float tol = M_PI_4) : RelativeAngle(Position::NormalizeOrientation(angle)), Tolerance(tol) {} + + float RelativeAngle; // we want to be at this angle relative to the target (0 = front, M_PI = back) + float Tolerance; // but we'll tolerate anything within +- this much + + float UpperBound() const { return Position::NormalizeOrientation(RelativeAngle + Tolerance); } + float LowerBound() const { return Position::NormalizeOrientation(RelativeAngle - Tolerance); } + bool IsAngleOkay(float relAngle) const + { + float const diff = std::abs(relAngle - RelativeAngle); + return (std::min(diff, float(2 * M_PI) - diff) <= Tolerance); + } +}; + class TC_GAME_API MotionMaster { public: @@ -121,8 +151,9 @@ class TC_GAME_API MotionMaster void MoveIdle(); void MoveTargetedHome(); void MoveRandom(float spawndist = 0.0f); - void MoveFollow(Unit* target, float dist, float angle, MovementSlot slot = MOTION_SLOT_ACTIVE); - void MoveChase(Unit* target, float dist = 0.0f, float angle = 0.0f); + void MoveFollow(Unit* target, float dist, ChaseAngle angle, MovementSlot slot = MOTION_SLOT_ACTIVE); + void MoveChase(Unit* target, Optional<ChaseRange> dist = {}, Optional<ChaseAngle> angle = {}); + void MoveChase(Unit* target, float dist, float angle = 0.0f) { MoveChase(target, Optional<ChaseRange>(dist), Optional<ChaseAngle>(angle)); } void MoveConfused(); void MoveFleeing(Unit* enemy, uint32 time = 0); void MovePoint(uint32 id, Position const& pos, bool generatePath = true, Optional<float> finalOrient = {}) diff --git a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp new file mode 100644 index 00000000000..a84139cca2d --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ChaseMovementGenerator.h" +#include "Creature.h" +#include "G3DPosition.hpp" +#include "MoveSpline.h" +#include "MoveSplineInit.h" +#include "PathGenerator.h" +#include "Unit.h" +#include "Util.h" + +static bool IsMutualChase(Unit* owner, Unit* target) +{ + MovementGenerator const* gen = target->GetMotionMaster()->top(); + if (!gen || gen->GetMovementGeneratorType() != CHASE_MOTION_TYPE) + return false; + return (static_cast<ChaseMovementGenerator const*>(gen)->GetTarget() == owner); +} + +static bool PositionOkay(Unit* owner, Unit* target, Optional<float> minDistance, Optional<float> maxDistance, Optional<ChaseAngle> angle) +{ + float const distSq = owner->GetExactDistSq(target); + if (minDistance && distSq < square(*minDistance)) + return false; + if (maxDistance && distSq > square(*maxDistance)) + return false; + return !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner)); +} + +ChaseMovementGenerator::ChaseMovementGenerator(Unit* target, Optional<ChaseRange> range, Optional<ChaseAngle> angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle) {} +ChaseMovementGenerator::~ChaseMovementGenerator() = default; + +void ChaseMovementGenerator::Initialize(Unit* owner) +{ + owner->AddUnitState(UNIT_STATE_CHASE); + owner->SetWalk(false); +} + +bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff) +{ + // owner might be dead or gone (can we even get nullptr here?) + if (!owner || !owner->IsAlive()) + return false; + + // our target might have gone away + Unit* const target = GetTarget(); + if (!target) + return false; + + // the owner might've selected a different target (feels like we shouldn't check this here...) + if (owner->GetVictim() != target) + return false; + + // the owner might be unable to move (rooted or casting), pause movement + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) + { + owner->StopMoving(); + return true; + } + + bool const mutualChase = IsMutualChase(owner, target); + float const hitboxSum = owner->GetCombatReach() + target->GetCombatReach(); + float const minRange = _range ? _range->MinRange + hitboxSum : CONTACT_DISTANCE; + float const minTarget = (_range ? _range->MinTolerance : 0.0f) + hitboxSum; + float const maxRange = _range ? _range->MaxRange + hitboxSum : owner->GetMeleeRange(target); // melee range already includes hitboxes + float const maxTarget = _range ? _range->MaxTolerance + hitboxSum : CONTACT_DISTANCE + hitboxSum; + Optional<ChaseAngle> angle = mutualChase ? Optional<ChaseAngle>() : _angle; + + // if we're already moving, periodically check if we're already in the expected range... + if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE)) + { + if (_rangeCheckTimer > diff) + _rangeCheckTimer -= diff; + else + { + _rangeCheckTimer = RANGE_CHECK_INTERVAL; + if (PositionOkay(owner, target, _movingTowards ? Optional<float>() : minTarget, _movingTowards ? maxTarget : Optional<float>(), angle)) + { + _path = nullptr; + owner->StopMoving(); + owner->SetInFront(target); + return true; + } + } + } + + // if we're done moving, we want to clean up + if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE) && owner->movespline->Finalized()) + { + _path = nullptr; + owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); + owner->SetInFront(target); + } + + // if the target moved, we have to consider whether to adjust + if (_lastTargetPosition != target->GetPosition() || mutualChase != _mutualChase) + { + _lastTargetPosition = target->GetPosition(); + _mutualChase = mutualChase; + if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE) || !PositionOkay(owner, target, minRange, maxRange, angle)) + { + Creature* const cOwner = owner->ToCreature(); + // can we get to the target? + if (cOwner && !target->isInAccessiblePlaceFor(cOwner)) + { + cOwner->SetCannotReachTarget(true); + cOwner->StopMoving(); + _path = nullptr; + return true; + } + + // figure out which way we want to move + bool const moveToward = !owner->IsInDist(target, maxRange); + + // make a new path if we have to... + if (!_path || moveToward != _movingTowards) + _path = std::make_unique<PathGenerator>(owner); + + float x, y, z; + bool shortenPath; + // if we want to move toward the target and there's no fixed angle... + if (moveToward && !angle) + { + // ...we'll pathfind to the center, then shorten the path + target->GetPosition(x, y, z); + shortenPath = true; + } + else + { + // otherwise, we fall back to nearpoint finding + target->GetNearPoint(owner, x, y, z, (moveToward ? maxTarget : minTarget) - hitboxSum, angle ? target->ToAbsoluteAngle(angle->RelativeAngle) : target->GetAbsoluteAngle(owner)); + shortenPath = false; + } + + if (owner->IsHovering()) + owner->UpdateAllowedPositionZ(x, y, z); + + bool success = _path->CalculatePath(x, y, z); + if (!success || (_path->GetPathType() & PATHFIND_NOPATH)) + { + if (cOwner) + cOwner->SetCannotReachTarget(true); + owner->StopMoving(); + return true; + } + + if (shortenPath) + _path->ShortenPathUntilDist(PositionToVector3(target), maxTarget); + + if (cOwner) + cOwner->SetCannotReachTarget(false); + owner->AddUnitState(UNIT_STATE_CHASE_MOVE); + + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); + init.SetWalk(false); + init.SetFacing(target); + + init.Launch(); + } + } + + // and then, finally, we're done for the tick + return true; +} + +void ChaseMovementGenerator::Finalize(Unit* owner) +{ + owner->ClearUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); + if (Creature* cOwner = owner->ToCreature()) + cOwner->SetCannotReachTarget(false); +} diff --git a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h new file mode 100644 index 00000000000..4a7269bf70d --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_CHASEMOVEMENTGENERATOR_H +#define TRINITY_CHASEMOVEMENTGENERATOR_H + +#include "AbstractFollower.h" +#include "MovementGenerator.h" +#include "Optional.h" + +class PathGenerator; +class Unit; + +class ChaseMovementGenerator : public MovementGenerator, public AbstractFollower +{ + public: + MovementGeneratorType GetMovementGeneratorType() const override { return CHASE_MOTION_TYPE; } + + ChaseMovementGenerator(Unit* target, Optional<ChaseRange> range = {}, Optional<ChaseAngle> angle = {}); + ~ChaseMovementGenerator(); + + void Initialize(Unit* owner) override; + void Reset(Unit* owner) override { Initialize(owner); } + bool Update(Unit* owner, uint32 diff) override; + void Finalize(Unit* owner) override; + + void UnitSpeedChanged() override { _lastTargetPosition.Relocate(0.0f,0.0f,0.0f); } + + private: + static constexpr uint32 RANGE_CHECK_INTERVAL = 100; // time (ms) until we attempt to recalculate + + Optional<ChaseRange> const _range; + Optional<ChaseAngle> const _angle; + + std::unique_ptr<PathGenerator> _path; + Position _lastTargetPosition; + uint32 _rangeCheckTimer = RANGE_CHECK_INTERVAL; + bool _movingTowards = true; + bool _mutualChase = true; +}; + +#endif diff --git a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp new file mode 100644 index 00000000000..5f4ce139dc1 --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "FollowMovementGenerator.h" +#include "MoveSpline.h" +#include "MoveSplineInit.h" +#include "PathGenerator.h" +#include "Pet.h" +#include "Unit.h" +#include "Util.h" + +FollowMovementGenerator::FollowMovementGenerator(Unit* target, float range, ChaseAngle angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle) {} +FollowMovementGenerator::~FollowMovementGenerator() {} + +static bool PositionOkay(Unit* owner, Unit* target, float range, Optional<ChaseAngle> angle = {}) +{ + if (owner->GetExactDistSq(target) > square(owner->GetCombatReach() + target->GetCombatReach() + range)) + return false; + return !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner)); +} + +void FollowMovementGenerator::Initialize(Unit* owner) +{ + owner->AddUnitState(UNIT_STATE_FOLLOW); + UpdatePetSpeed(owner); +} + +bool FollowMovementGenerator::Update(Unit* owner, uint32 diff) +{ + // owner might be dead or gone + if (!owner->IsAlive()) + return false; + + // our target might have gone away + Unit* const target = GetTarget(); + if (!target) + return false; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) + { + owner->StopMoving(); + return true; + } + + if (owner->HasUnitState(UNIT_STATE_FOLLOW_MOVE)) + { + if (_checkTimer > diff) + _checkTimer -= diff; + else + { + _checkTimer = CHECK_INTERVAL; + if (PositionOkay(owner, target, _range, _angle)) + { + _path = nullptr; + owner->StopMoving(); + return true; + } + } + } + + if (owner->HasUnitState(UNIT_STATE_FOLLOW_MOVE) && owner->movespline->Finalized()) + { + _path = nullptr; + owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); + } + + if (_lastTargetPosition.GetExactDistSq(target->GetPosition()) > 0.0f) + { + _lastTargetPosition = target->GetPosition(); + if (owner->HasUnitState(UNIT_STATE_FOLLOW_MOVE) || !PositionOkay(owner, target, _range + FOLLOW_RANGE_TOLERANCE)) + { + if (!_path) + _path = std::make_unique<PathGenerator>(owner); + + float x, y, z; + + // select angle + float tAngle; + float const curAngle = target->GetRelativeAngle(owner); + if (_angle.IsAngleOkay(curAngle)) + tAngle = curAngle; + else + { + float const diffUpper = Position::NormalizeOrientation(curAngle - _angle.UpperBound()); + float const diffLower = Position::NormalizeOrientation(_angle.LowerBound() - curAngle); + if (diffUpper < diffLower) + tAngle = _angle.UpperBound(); + else + tAngle = _angle.LowerBound(); + } + + target->GetNearPoint(owner, x, y, z, _range, target->ToAbsoluteAngle(tAngle)); + + if (owner->IsHovering()) + owner->UpdateAllowedPositionZ(x, y, z); + + // pets are allowed to "cheat" on pathfinding when following their master + bool allowShortcut = false; + if (Pet* oPet = owner->ToPet()) + if (target->GetGUID() == oPet->GetOwnerGUID()) + allowShortcut = true; + + bool success = _path->CalculatePath(x, y, z, allowShortcut); + if (!success || (_path->GetPathType() & PATHFIND_NOPATH)) + { + owner->StopMoving(); + return true; + } + + owner->AddUnitState(UNIT_STATE_FOLLOW_MOVE); + + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); + init.SetWalk(target->IsWalking()); + init.SetFacing(target->GetOrientation()); + init.Launch(); + } + } + return true; +} + +void FollowMovementGenerator::Finalize(Unit* owner) +{ + owner->ClearUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); + UpdatePetSpeed(owner); +} + +void FollowMovementGenerator::UpdatePetSpeed(Unit* owner) +{ + if (Pet* oPet = owner->ToPet()) + if (!GetTarget() || GetTarget()->GetGUID() == owner->GetOwnerGUID()) + { + oPet->UpdateSpeed(MOVE_RUN); + oPet->UpdateSpeed(MOVE_WALK); + oPet->UpdateSpeed(MOVE_SWIM); + } +} diff --git a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h new file mode 100644 index 00000000000..112161de95c --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_FOLLOWMOVEMENTGENERATOR_H +#define TRINITY_FOLLOWMOVEMENTGENERATOR_H + +#include "AbstractFollower.h" +#include "MovementGenerator.h" + +class PathGenerator; +class Unit; + +class FollowMovementGenerator : public MovementGenerator, public AbstractFollower +{ + public: + MovementGeneratorType GetMovementGeneratorType() const override { return FOLLOW_MOTION_TYPE; } + + FollowMovementGenerator(Unit* target, float range, ChaseAngle angle); + ~FollowMovementGenerator(); + + void Initialize(Unit* owner) override; + void Reset(Unit* owner) override { Initialize(owner); } + bool Update(Unit* owner, uint32 diff) override; + void Finalize(Unit* owner) override; + + void UnitSpeedChanged() override { _lastTargetPosition.Relocate(0.0f, 0.0f, 0.0f); } + + private: + static constexpr uint32 CHECK_INTERVAL = 500; +// static inline const when? +#define FOLLOW_RANGE_TOLERANCE 1.0f + + void UpdatePetSpeed(Unit* owner); + + float const _range; + ChaseAngle const _angle; + + uint32 _checkTimer = CHECK_INTERVAL; + std::unique_ptr<PathGenerator> _path; + Position _lastTargetPosition; +}; + +#endif diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp deleted file mode 100644 index 9a3a6c3dc70..00000000000 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "TargetedMovementGenerator.h" -#include "Creature.h" -#include "CreatureAI.h" -#include "MoveSpline.h" -#include "MoveSplineInit.h" -#include "PathGenerator.h" -#include "Player.h" -#include "VehicleDefines.h" -#include "World.h" - -template<class T, typename D> -TargetedMovementGenerator<T, D>::~TargetedMovementGenerator() -{ - delete _path; -} - -template<class T, typename D> -bool TargetedMovementGenerator<T, D>::DoUpdate(T* owner, uint32 diff) -{ - if (!IsTargetValid() || !GetTarget()->IsInWorld()) - return false; - - if (!owner || !owner->IsAlive()) - return false; - - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || HasLostTarget(owner)) - { - _interrupt = true; - owner->StopMoving(); - return true; - } - - if (_interrupt || _recalculateTravel) - { - _interrupt = false; - SetTargetLocation(owner, true); - return true; - } - - bool targetMoved = false; - _timer.Update(diff); - if (!_interrupt && _timer.Passed()) - { - _timer.Reset(100); - - // the allowed distance between target and mover before the mover needs to reposition in order to keep attacking - float distance = GetMaxDistanceBeforeRepositioning(owner); - if (owner->IsPet() && (owner->GetCharmerOrOwnerGUID() == GetTarget()->GetGUID())) - distance = 1.f + GetTarget()->GetCombatReach(); // pet following owner - - G3D::Vector3 destination = owner->movespline->FinalDestination(); - if (owner->movespline->onTransport) - if (TransportBase* transport = owner->GetDirectTransport()) - transport->CalculatePassengerPosition(destination.x, destination.y, destination.z); - - // First check distance - targetMoved = !GetTarget()->IsInDist(destination.x, destination.y, destination.z, distance); - - // then, if the target is in range, check also Line of Sight. - if (!targetMoved) - targetMoved = !GetTarget()->IsWithinLOSInMap(owner); - } - - if (targetMoved) - SetTargetLocation(owner, true); - else if (_speedChanged) - SetTargetLocation(owner, false); - - if (!_targetReached && owner->movespline->Finalized()) - { - MovementInform(owner); - if (_angle == 0.f && !owner->HasInArc(0.01f, GetTarget())) - owner->SetInFront(GetTarget()); - - if (!_targetReached) - { - _targetReached = true; - ReachTarget(owner); - } - } - - return true; -} - -template<class T, typename D> -void TargetedMovementGenerator<T, D>::SetTargetLocation(T* owner, bool updateDestination) -{ - if (!IsTargetValid() || !GetTarget()->IsInWorld()) - return; - - if (!owner || !owner->IsAlive()) - return; - - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || HasLostTarget(owner)) - { - _interrupt = true; - owner->StopMoving(); - return; - } - - if (owner->GetTypeId() == TYPEID_UNIT && !GetTarget()->isInAccessiblePlaceFor(owner->ToCreature())) - { - owner->ToCreature()->SetCannotReachTarget(true); - return; - } - - float x, y, z; - if (updateDestination || !_path) - { - if (!_offset) - { - if (GetTarget()->IsWithinDistInMap(owner, CONTACT_DISTANCE)) - return; - - GetTarget()->GetNearPoint(owner, x, y, z, CONTACT_DISTANCE, GetTarget()->GetAbsoluteAngle(owner)); - } - else - { - float distance = _offset + 1.0f; - - if (owner->IsPet() && GetTarget()->GetTypeId() == TYPEID_PLAYER) - distance = 1.0f; - - if (GetTarget()->IsWithinDistInMap(owner, distance)) - return; - - GetTarget()->GetClosePoint(x, y, z, _offset, _angle); - } - - if (owner->IsHovering()) - owner->UpdateAllowedPositionZ(x, y, z); - } - else - { - // the destination has not changed, we just need to refresh the path (usually speed change) - G3D::Vector3 end = _path->GetEndPosition(); - x = end.x; - y = end.y; - z = end.z; - } - - if (!_path) - _path = new PathGenerator(owner); - - // allow pets to use shortcut if no path found when following their master - bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)); - - bool result = _path->CalculatePath(x, y, z, forceDest); - if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) - { - // can't reach target - _recalculateTravel = true; - if (owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->SetCannotReachTarget(true); - return; - } - - _targetReached = false; - _recalculateTravel = false; - _speedChanged = false; - - AddUnitStateMove(owner); - - if (owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->SetCannotReachTarget(false); - - Movement::MoveSplineInit init(owner); - init.MovebyPath(_path->GetPath()); - init.SetWalk(EnableWalking()); - // Using the same condition for facing target as the one that is used for SetInFront on movement end - // - applies to ChaseMovementGenerator mostly - if (_angle == 0.f) - init.SetFacing(GetTarget()); - - init.Launch(); -} - -template<class T, typename D> -bool TargetedMovementGenerator<T, D>::IsReachable() const -{ - return (_path) ? (_path->GetPathType() & PATHFIND_NORMAL) : true; -} - -//---- ChaseMovementGenerator - -template<class T> -void ChaseMovementGenerator<T>::DoInitialize(T*) { } - -template<> -void ChaseMovementGenerator<Player>::DoInitialize(Player* owner) -{ - owner->AddUnitState(UNIT_STATE_CHASE); - SetTargetLocation(owner, true); -} - -template<> -void ChaseMovementGenerator<Creature>::DoInitialize(Creature* owner) -{ - owner->SetWalk(false); - owner->AddUnitState(UNIT_STATE_CHASE); - SetTargetLocation(owner, true); -} - -template<class T> -void ChaseMovementGenerator<T>::DoFinalize(T* owner) -{ - owner->ClearUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); -} - -template<class T> -void ChaseMovementGenerator<T>::DoReset(T* owner) -{ - DoInitialize(owner); -} - -template<class T> -void ChaseMovementGenerator<T>::ClearUnitStateMove(T* owner) -{ - owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); -} - -template<class T> -void ChaseMovementGenerator<T>::AddUnitStateMove(T* owner) -{ - owner->AddUnitState(UNIT_STATE_CHASE_MOVE); -} - -template<class T> -bool ChaseMovementGenerator<T>::HasLostTarget(T* owner) const -{ - return owner->GetVictim() != TargetedMovementGeneratorBase::GetTarget(); -} - -template<class T> -void ChaseMovementGenerator<T>::ReachTarget(T* owner) -{ - ClearUnitStateMove(owner); - - if (owner->IsWithinMeleeRange(TargetedMovementGeneratorBase::GetTarget())) - owner->Attack(TargetedMovementGeneratorBase::GetTarget(), true); - - if (owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->SetCannotReachTarget(false); -} - -template<class T> -void ChaseMovementGenerator<T>::MovementInform(T*) { } - -template<class T> -float ChaseMovementGenerator<T>::GetMaxDistanceBeforeRepositioning(T* owner) -{ - // the notion of melee range and melee attack is clearly separated from the notion of the movement. - // As a seperation of concern refactoring, this value should be passed into parameter by the caller (during creation of ChaseMoveGen) instead of defining it - // here (or a callback should be used since this value depends on dynamic fields (combat reach). - return owner->GetMeleeRange(TargetedMovementGeneratorBase::GetTarget()); -} - -template<> -void ChaseMovementGenerator<Creature>::MovementInform(Creature* owner) -{ - // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle - if (owner->AI()) - owner->AI()->MovementInform(CHASE_MOTION_TYPE, GetTarget()->GetGUID().GetCounter()); -} - -//---- FollowMovementGenerator - -template<class T> -void FollowMovementGenerator<T>::UpdateSpeed(T*) { } - -template<> -void FollowMovementGenerator<Player>::UpdateSpeed(Player* /*owner*/) { } - -template<> -void FollowMovementGenerator<Creature>::UpdateSpeed(Creature* owner) -{ - // Pet only sync speed with owner - // Make sure we are not in the process of a map change (IsInWorld) - if (!owner->IsPet() || !owner->IsInWorld() || !IsTargetValid() || GetTarget()->GetGUID() != owner->GetOwnerGUID()) - return; - - owner->UpdateSpeed(MOVE_RUN); - owner->UpdateSpeed(MOVE_WALK); - owner->UpdateSpeed(MOVE_SWIM); -} - -template<class T> -void FollowMovementGenerator<T>::DoInitialize(T* owner) -{ - owner->AddUnitState(UNIT_STATE_FOLLOW); - UpdateSpeed(owner); - TargetedMovementGenerator<T, FollowMovementGenerator<T>>::SetTargetLocation(owner, true); -} - -template<class T> -void FollowMovementGenerator<T>::DoFinalize(T* owner) -{ - owner->ClearUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - UpdateSpeed(owner); -} - -template<class T> -void FollowMovementGenerator<T>::DoReset(T* owner) -{ - DoInitialize(owner); -} - -template<class T> -void FollowMovementGenerator<T>::ClearUnitStateMove(T* owner) -{ - owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); -} - -template<class T> -void FollowMovementGenerator<T>::AddUnitStateMove(T* owner) -{ - owner->AddUnitState(UNIT_STATE_FOLLOW_MOVE); -} - -template<class T> -void FollowMovementGenerator<T>::ReachTarget(T* owner) -{ - ClearUnitStateMove(owner); -} - -template<> -bool FollowMovementGenerator<Creature>::EnableWalking() const -{ - return IsTargetValid() && GetTarget()->IsWalking(); -} - -template<> -bool FollowMovementGenerator<Player>::EnableWalking() const -{ - return false; -} - -template<class T> -void FollowMovementGenerator<T>::MovementInform(T*) { } - -template<class T> -float FollowMovementGenerator<T>::GetMaxDistanceBeforeRepositioning(T* owner) -{ - return owner->GetCombatReach() + TargetedMovementGeneratorBase::GetTarget()->GetCombatReach() + MOVE_FOLLOW_REPOSITIONING_DISTANCE; -} - -template<> -void FollowMovementGenerator<Creature>::MovementInform(Creature* unit) -{ - // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle - if (unit->AI()) - unit->AI()->MovementInform(FOLLOW_MOTION_TYPE, GetTarget()->GetGUID().GetCounter()); -} - -//-----------------------------------------------// - -template TargetedMovementGenerator<Player, ChaseMovementGenerator<Player> >::~TargetedMovementGenerator(); -template TargetedMovementGenerator<Player, FollowMovementGenerator<Player> >::~TargetedMovementGenerator(); -template TargetedMovementGenerator<Creature, ChaseMovementGenerator<Creature> >::~TargetedMovementGenerator(); -template TargetedMovementGenerator<Creature, FollowMovementGenerator<Creature> >::~TargetedMovementGenerator(); -template bool TargetedMovementGenerator<Player, ChaseMovementGenerator<Player> >::DoUpdate(Player*, uint32); -template bool TargetedMovementGenerator<Player, FollowMovementGenerator<Player> >::DoUpdate(Player*, uint32); -template bool TargetedMovementGenerator<Creature, ChaseMovementGenerator<Creature> >::DoUpdate(Creature*, uint32); -template bool TargetedMovementGenerator<Creature, FollowMovementGenerator<Creature> >::DoUpdate(Creature*, uint32); -template void TargetedMovementGenerator<Player, ChaseMovementGenerator<Player> >::SetTargetLocation(Player*, bool); -template void TargetedMovementGenerator<Player, FollowMovementGenerator<Player> >::SetTargetLocation(Player*, bool); -template void TargetedMovementGenerator<Creature, ChaseMovementGenerator<Creature> >::SetTargetLocation(Creature*, bool); -template void TargetedMovementGenerator<Creature, FollowMovementGenerator<Creature> >::SetTargetLocation(Creature*, bool); - -template void ChaseMovementGenerator<Player>::DoFinalize(Player*); -template void ChaseMovementGenerator<Creature>::DoFinalize(Creature*); -template void ChaseMovementGenerator<Player>::DoReset(Player*); -template void ChaseMovementGenerator<Creature>::DoReset(Creature*); -template void ChaseMovementGenerator<Player>::ClearUnitStateMove(Player*); -template void ChaseMovementGenerator<Creature>::ClearUnitStateMove(Creature*); -template void ChaseMovementGenerator<Player>::AddUnitStateMove(Player*); -template void ChaseMovementGenerator<Creature>::AddUnitStateMove(Creature*); -template bool ChaseMovementGenerator<Player>::HasLostTarget(Player*) const; -template bool ChaseMovementGenerator<Creature>::HasLostTarget(Creature*) const; -template void ChaseMovementGenerator<Player>::ReachTarget(Player*); -template void ChaseMovementGenerator<Creature>::ReachTarget(Creature*); -template void ChaseMovementGenerator<Player>::MovementInform(Player*); -template float ChaseMovementGenerator<Player>::GetMaxDistanceBeforeRepositioning(Player*); -template float ChaseMovementGenerator<Creature>::GetMaxDistanceBeforeRepositioning(Creature*); - -template void FollowMovementGenerator<Player>::DoInitialize(Player*); -template void FollowMovementGenerator<Creature>::DoInitialize(Creature*); -template void FollowMovementGenerator<Player>::DoFinalize(Player*); -template void FollowMovementGenerator<Creature>::DoFinalize(Creature*); -template void FollowMovementGenerator<Player>::DoReset(Player*); -template void FollowMovementGenerator<Creature>::DoReset(Creature*); -template void FollowMovementGenerator<Player>::ClearUnitStateMove(Player*); -template void FollowMovementGenerator<Creature>::ClearUnitStateMove(Creature*); -template void FollowMovementGenerator<Player>::AddUnitStateMove(Player*); -template void FollowMovementGenerator<Creature>::AddUnitStateMove(Creature*); -template void FollowMovementGenerator<Player>::ReachTarget(Player*); -template void FollowMovementGenerator<Creature>::ReachTarget(Creature*); -template void FollowMovementGenerator<Player>::MovementInform(Player*); -template float FollowMovementGenerator<Player>::GetMaxDistanceBeforeRepositioning(Player*); -template float FollowMovementGenerator<Creature>::GetMaxDistanceBeforeRepositioning(Creature*); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h deleted file mode 100755 index b4fdbab9292..00000000000 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef TRINITY_TARGETEDMOVEMENTGENERATOR_H -#define TRINITY_TARGETEDMOVEMENTGENERATOR_H - -#include "MovementGenerator.h" -#include "FollowerReference.h" -#include "Timer.h" - -#define MOVE_FOLLOW_REPOSITIONING_DISTANCE 1.5f - -class TargetedMovementGeneratorBase -{ - public: - TargetedMovementGeneratorBase(Unit* target) - { - _target.link(target, this); - } - - bool IsTargetValid() const { return _target.isValid(); } - Unit* GetTarget() const { return _target.getTarget(); } - void stopFollowing() { } - - private: - FollowerReference _target; -}; - -template<class T, typename D> -class TargetedMovementGenerator : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase -{ - public: - explicit TargetedMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGeneratorBase(target), _path(nullptr), _timer(0), _offset(offset), _angle(angle), _recalculateTravel(false), _speedChanged(false), _targetReached(false), _interrupt(false) { } - ~TargetedMovementGenerator(); - - bool DoUpdate(T*, uint32); - - void UnitSpeedChanged() override { _speedChanged = true; } - - virtual void ClearUnitStateMove(T*) { } - virtual void AddUnitStateMove(T*) { } - virtual bool HasLostTarget(T*) const { return false; } - virtual void ReachTarget(T*) { } - virtual bool EnableWalking() const { return false; } - virtual void MovementInform(T*) { } - virtual float GetMaxDistanceBeforeRepositioning(T*) { return 0.0f; } - - bool IsReachable() const; - void SetTargetLocation(T* owner, bool updateDestination); - - private: - PathGenerator* _path; - TimeTrackerSmall _timer; - float _offset; - float _angle; - bool _recalculateTravel; - bool _speedChanged; - bool _targetReached; - bool _interrupt; -}; - -template<class T> -class ChaseMovementGenerator : public TargetedMovementGenerator<T, ChaseMovementGenerator<T> > -{ - public: - explicit ChaseMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGenerator<T, ChaseMovementGenerator<T> >(target, offset, angle) { } - - MovementGeneratorType GetMovementGeneratorType() const override { return CHASE_MOTION_TYPE; } - - void DoInitialize(T*); - void DoFinalize(T*); - void DoReset(T*); - - void ClearUnitStateMove(T*) override; - void AddUnitStateMove(T*) override; - bool HasLostTarget(T*) const override; - void ReachTarget(T*) override; - void MovementInform(T*) override; - float GetMaxDistanceBeforeRepositioning(T*) override; -}; - -template<class T> -class FollowMovementGenerator : public TargetedMovementGenerator<T, FollowMovementGenerator<T> > -{ - public: - explicit FollowMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGenerator<T, FollowMovementGenerator<T> >(target, offset, angle) { } - - MovementGeneratorType GetMovementGeneratorType() const override { return FOLLOW_MOTION_TYPE; } - - void DoInitialize(T*); - void DoFinalize(T*); - void DoReset(T*); - - void ClearUnitStateMove(T*) override; - void AddUnitStateMove(T*) override; - bool HasLostTarget(T*) const override { return false; } - void ReachTarget(T*) override; - bool EnableWalking() const override; - void MovementInform(T*) override; - float GetMaxDistanceBeforeRepositioning(T*) override; - private: - void UpdateSpeed(T* owner); -}; - -#endif diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 5209c227c14..912de049261 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -904,43 +904,50 @@ float PathGenerator::Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) c return (p1 - p2).squaredLength(); } -void PathGenerator::ReducePathLenghtByDist(float dist) +void PathGenerator::ShortenPathUntilDist(G3D::Vector3 const& target, float dist) { - if (GetPathType() == PATHFIND_BLANK) + if (GetPathType() == PATHFIND_BLANK || _pathPoints.size() < 2) { - TC_LOG_ERROR("maps", "PathGenerator::ReducePathLenghtByDist called before path was built"); + TC_LOG_ERROR("maps", "PathGenerator::ReducePathLengthByDist called before path was successfully built"); return; } - if (_pathPoints.size() < 2) // path building failure + float const distSq = dist * dist; + + // the first point of the path must be outside the specified range + // (this should have really been checked by the caller...) + if ((_pathPoints[0] - target).squaredLength() < distSq) + return; + + // check if we even need to do anything + if ((*_pathPoints.rbegin() - target).squaredLength() >= distSq) return; - uint32 i = _pathPoints.size(); - G3D::Vector3 nextVec = _pathPoints[--i]; - while (i > 0) + size_t i = _pathPoints.size()-1; + // find the first i s.t.: + // - _pathPoints[i] is still too close + // - _pathPoints[i-1] is too far away + // => the end point is somewhere on the line between the two + while (1) { - G3D::Vector3 currVec = _pathPoints[--i]; - G3D::Vector3 diffVec = (nextVec - currVec); - float len = diffVec.length(); - if (len > dist) - { - float step = dist / len; - // same as nextVec - _pathPoints[i + 1] -= diffVec * step; - _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i + 1].x, _pathPoints[i + 1].y, _pathPoints[i + 1].z); - _pathPoints.resize(i + 2); - break; - } - else if (i == 0) // at second point + // we know that pathPoints[i] is too close already (from the previous iteration) + if ((_pathPoints[i-1] - target).squaredLength() >= distSq) + break; // bingo! + + if (!--i) { - _pathPoints[1] = _pathPoints[0]; + // no point found that fulfills the condition + _pathPoints[0] = _pathPoints[1]; _pathPoints.resize(2); - break; + return; } - - dist -= len; - nextVec = currVec; // we're going backwards } + + // ok, _pathPoints[i] is too close, _pathPoints[i-1] is not, so our target point is somewhere between the two... + // ... settle for a guesstimate since i'm not confident in doing trig on every chase motion tick... + // (@todo review this) + _pathPoints[i] += (_pathPoints[i - 1] - _pathPoints[i]).direction() * (dist - (_pathPoints[i] - target).length()); + _pathPoints.resize(i+1); } bool PathGenerator::IsInvalidDestinationZ(Unit const* target) const diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index e4ccfbceb3d..193102bfde8 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -74,7 +74,8 @@ class TC_GAME_API PathGenerator PathType GetPathType() const { return _type; } - void ReducePathLenghtByDist(float dist); // path must be already built + // shortens the path until the destination is the specified distance from the target point + void ShortenPathUntilDist(G3D::Vector3 const& point, float dist); private: diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 40f03a2128d..4d140f23569 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -1,19 +1,19 @@ /* -* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> -* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see <http://www.gnu.org/licenses/>. + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef TRINITYSERVER_MOVESPLINEINIT_H diff --git a/src/server/game/Petitions/PetitionMgr.cpp b/src/server/game/Petitions/PetitionMgr.cpp index df845745e9d..e0335416db9 100644 --- a/src/server/game/Petitions/PetitionMgr.cpp +++ b/src/server/game/Petitions/PetitionMgr.cpp @@ -1,19 +1,19 @@ /* -* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see <http://www.gnu.org/licenses/>. -*/ + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ #include "PetitionMgr.h" #include "DatabaseEnv.h" diff --git a/src/server/game/Petitions/PetitionMgr.h b/src/server/game/Petitions/PetitionMgr.h index 446c121bdac..8aaf65a52e5 100644 --- a/src/server/game/Petitions/PetitionMgr.h +++ b/src/server/game/Petitions/PetitionMgr.h @@ -1,19 +1,19 @@ /* -* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see <http://www.gnu.org/licenses/>. -*/ + * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ #ifndef _PETITIONMGR_H #define _PETITIONMGR_H diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f2f74aa8d58..ab4215970b6 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -27,6 +27,7 @@ #include "DBCStores.h" #include "DisableMgr.h" #include "DynamicObject.h" +#include "G3DPosition.hpp" #include "GameObjectAI.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -5498,7 +5499,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint else if (m_preGeneratedPath->IsInvalidDestinationZ(target)) // Check position z, if in a straight line return SPELL_FAILED_NOPATH; - m_preGeneratedPath->ReducePathLenghtByDist(objSize); // move back + m_preGeneratedPath->ShortenPathUntilDist(PositionToVector3(target), objSize); // move back } break; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index fb98d0a3304..4b434b03583 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -20,9 +20,11 @@ #include "ArenaTeamMgr.h" #include "CellImpl.h" #include "CharacterCache.h" +#include "ChaseMovementGenerator.h" #include "Chat.h" #include "DatabaseEnv.h" #include "DisableMgr.h" +#include "FollowMovementGenerator.h" #include "GridNotifiers.h" #include "Group.h" #include "GroupMgr.h" @@ -43,7 +45,6 @@ #include "SpellAuras.h" #include "SpellHistory.h" #include "SpellMgr.h" -#include "TargetedMovementGenerator.h" #include "Transport.h" #include "Weather.h" #include "WeatherMgr.h" @@ -2164,11 +2165,7 @@ public: break; case CHASE_MOTION_TYPE: { - Unit* target = nullptr; - if (unit->GetTypeId() == TYPEID_PLAYER) - target = static_cast<ChaseMovementGenerator<Player> const*>(movementGenerator)->GetTarget(); - else - target = static_cast<ChaseMovementGenerator<Creature> const*>(movementGenerator)->GetTarget(); + Unit* target = static_cast<ChaseMovementGenerator const*>(movementGenerator)->GetTarget(); if (!target) handler->SendSysMessage(LANG_MOVEGENS_CHASE_NULL); @@ -2180,11 +2177,7 @@ public: } case FOLLOW_MOTION_TYPE: { - Unit* target = nullptr; - if (unit->GetTypeId() == TYPEID_PLAYER) - target = static_cast<FollowMovementGenerator<Player> const*>(movementGenerator)->GetTarget(); - else - target = static_cast<FollowMovementGenerator<Creature> const*>(movementGenerator)->GetTarget(); + Unit* target = static_cast<FollowMovementGenerator const*>(movementGenerator)->GetTarget(); if (!target) handler->SendSysMessage(LANG_MOVEGENS_FOLLOW_NULL); diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index e33e17b9251..f5b35559460 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -34,7 +34,6 @@ #include "Player.h" #include "PointMovementGenerator.h" #include "RBAC.h" -#include "TargetedMovementGenerator.h" class mmaps_commandscript : public CommandScript { diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 02dc899c02a..1f1f64ad8ec 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -27,6 +27,7 @@ EndScriptData */ #include "CreatureAI.h" #include "CreatureGroups.h" #include "DatabaseEnv.h" +#include "FollowMovementGenerator.h" #include "GameTime.h" #include "Language.h" #include "Log.h" @@ -36,7 +37,6 @@ EndScriptData */ #include "Pet.h" #include "Player.h" #include "RBAC.h" -#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand #include "Transport.h" #include "World.h" #include "WorldSession.h" @@ -1309,7 +1309,7 @@ public: return false; } - FollowMovementGenerator<Creature> const* mgen = static_cast<FollowMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top())); + FollowMovementGenerator const* mgen = static_cast<FollowMovementGenerator const*>((creature->GetMotionMaster()->top())); if (mgen->GetTarget() != player) { diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 2a96c031ead..64aab1bab0e 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -549,7 +549,7 @@ public: if (ShadowBolt_Timer <= diff) { if (!me->IsWithinDist(me->GetVictim(), 45.0f)) - me->GetMotionMaster()->MoveChase(me->GetVictim(), VEKLOR_DIST, 0); + me->GetMotionMaster()->MoveChase(me->GetVictim(), VEKLOR_DIST); else DoCastVictim(SPELL_SHADOWBOLT); ShadowBolt_Timer = 2000; @@ -599,7 +599,7 @@ public: // VL doesn't melee if (me->Attack(who, false)) { - me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); + me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST); AddThreat(who, 0.0f); } } |