aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/Utilities/Util.h3
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp2
-rw-r--r--src/server/game/Entities/Object/G3DPosition.hpp (renamed from src/server/game/Movement/FollowerReference.cpp)25
-rw-r--r--src/server/game/Entities/Pet/PetDefines.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp59
-rw-r--r--src/server/game/Entities/Unit/Unit.h13
-rw-r--r--src/server/game/Loot/LootItemStorage.cpp30
-rw-r--r--src/server/game/Loot/LootItemStorage.h30
-rw-r--r--src/server/game/Movement/AbstractFollower.cpp (renamed from src/server/game/Movement/FollowerRefManager.h)24
-rw-r--r--src/server/game/Movement/AbstractFollower.h (renamed from src/server/game/Movement/FollowerReference.h)24
-rw-r--r--src/server/game/Movement/MotionMaster.cpp55
-rw-r--r--src/server/game/Movement/MotionMaster.h35
-rw-r--r--src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp187
-rw-r--r--src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.h56
-rw-r--r--src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp151
-rw-r--r--src/server/game/Movement/MovementGenerators/FollowMovementGenerator.h57
-rw-r--r--src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp418
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h120
-rw-r--r--src/server/game/Movement/PathGenerator.cpp57
-rw-r--r--src/server/game/Movement/PathGenerator.h3
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.h30
-rw-r--r--src/server/game/Petitions/PetitionMgr.cpp30
-rw-r--r--src/server/game/Petitions/PetitionMgr.h30
-rw-r--r--src/server/game/Spells/Spell.cpp3
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp15
-rw-r--r--src/server/scripts/Commands/cs_mmaps.cpp1
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp4
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp4
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);
}
}