mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
[3.3.5] Core/Movement: MotionMaster & MovementGenerators cleaning (#19361)
(cherry picked from commit 21b8c4997a)
This commit is contained in:
@@ -8658,7 +8658,7 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate)
|
||||
|
||||
m_speed_rate[mtype] = rate;
|
||||
|
||||
propagateSpeedChange();
|
||||
PropagateSpeedChange();
|
||||
|
||||
// Spline packets are for creatures and move_update are for players
|
||||
static OpcodeServer const moveTypeToOpcode[MAX_MOVE_TYPE][3] =
|
||||
@@ -10661,9 +10661,9 @@ void Unit::SendPetAIReaction(ObjectGuid guid)
|
||||
owner->ToPlayer()->SendDirectMessage(packet.Write());
|
||||
}
|
||||
|
||||
void Unit::propagateSpeedChange()
|
||||
void Unit::PropagateSpeedChange()
|
||||
{
|
||||
GetMotionMaster()->propagateSpeedChange();
|
||||
GetMotionMaster()->PropagateSpeedChange();
|
||||
}
|
||||
|
||||
///----------End of Pet responses methods----------
|
||||
|
||||
@@ -1915,7 +1915,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
void SendPetAIReaction(ObjectGuid guid);
|
||||
///----------End of Pet responses methods----------
|
||||
|
||||
void propagateSpeedChange();
|
||||
void PropagateSpeedChange();
|
||||
|
||||
// reactive attacks
|
||||
void ClearAllReactives();
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "SplineChainMovementGenerator.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "PathGenerator.h"
|
||||
|
||||
inline bool IsStatic(MovementGenerator* movement)
|
||||
{
|
||||
@@ -76,7 +77,7 @@ void MotionMaster::InitDefault()
|
||||
if (_owner->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
MovementGenerator* movement = FactorySelector::selectMovementGenerator(_owner->ToCreature());
|
||||
Mutate(movement == NULL ? &si_idleMovement : movement, MOTION_SLOT_IDLE);
|
||||
Mutate(movement == nullptr ? &si_idleMovement : movement, MOTION_SLOT_IDLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -89,9 +90,6 @@ void MotionMaster::UpdateMotion(uint32 diff)
|
||||
if (!_owner)
|
||||
return;
|
||||
|
||||
if (_owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) // what about UNIT_STATE_DISTRACTED? Why is this not included?
|
||||
return;
|
||||
|
||||
ASSERT(!empty());
|
||||
|
||||
_cleanFlag |= MMCF_UPDATE;
|
||||
@@ -174,12 +172,12 @@ MovementGenerator* MotionMaster::GetMotionSlot(int slot) const
|
||||
return _slot[slot];
|
||||
}
|
||||
|
||||
void MotionMaster::propagateSpeedChange()
|
||||
void MotionMaster::PropagateSpeedChange()
|
||||
{
|
||||
for (int i = 0; i <= _top; ++i)
|
||||
{
|
||||
if (_slot[i])
|
||||
_slot[i]->unitSpeedChanged();
|
||||
_slot[i]->UnitSpeedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ class TC_GAME_API MotionMaster
|
||||
MovementGeneratorType GetMotionSlotType(int slot) const;
|
||||
MovementGenerator* GetMotionSlot(int slot) const;
|
||||
|
||||
void propagateSpeedChange();
|
||||
void PropagateSpeedChange();
|
||||
|
||||
bool GetDestination(float &x, float &y, float &z);
|
||||
|
||||
|
||||
@@ -33,14 +33,12 @@ class TC_GAME_API MovementGenerator
|
||||
|
||||
virtual void Initialize(Unit*) = 0;
|
||||
virtual void Finalize(Unit*) = 0;
|
||||
|
||||
virtual void Reset(Unit*) = 0;
|
||||
|
||||
virtual bool Update(Unit*, uint32 time_diff) = 0;
|
||||
virtual bool Update(Unit*, uint32 diff) = 0;
|
||||
|
||||
virtual MovementGeneratorType GetMovementGeneratorType() const = 0;
|
||||
|
||||
virtual void unitSpeedChanged() { }
|
||||
virtual void UnitSpeedChanged() { }
|
||||
|
||||
// used by Evade code for select point to evade with expected restart default movement
|
||||
virtual bool GetResetPosition(Unit*, float& /*x*/, float& /*y*/, float& /*z*/) { return false; }
|
||||
@@ -52,42 +50,39 @@ class MovementGeneratorMedium : public MovementGenerator
|
||||
public:
|
||||
void Initialize(Unit* u) override
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
(static_cast<D*>(this))->DoInitialize(static_cast<T*>(u));
|
||||
}
|
||||
|
||||
void Finalize(Unit* u) override
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
(static_cast<D*>(this))->DoFinalize(static_cast<T*>(u));
|
||||
}
|
||||
|
||||
void Reset(Unit* u) override
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
(static_cast<D*>(this))->DoReset(static_cast<T*>(u));
|
||||
}
|
||||
|
||||
bool Update(Unit* u, uint32 time_diff) override
|
||||
{
|
||||
//u->AssertIsType<T>();
|
||||
return (static_cast<D*>(this))->DoUpdate(static_cast<T*>(u), time_diff);
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectableMovement : public FactoryHolder<MovementGenerator, MovementGeneratorType>
|
||||
{
|
||||
SelectableMovement(MovementGeneratorType mgt) : FactoryHolder<MovementGenerator, MovementGeneratorType>(mgt) { }
|
||||
SelectableMovement(MovementGeneratorType movementGeneratorType) : FactoryHolder<MovementGenerator, MovementGeneratorType>(movementGeneratorType) { }
|
||||
};
|
||||
|
||||
template<class REAL_MOVEMENT>
|
||||
template<class Movement>
|
||||
struct MovementGeneratorFactory : public SelectableMovement
|
||||
{
|
||||
MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) { }
|
||||
MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : SelectableMovement(movementGeneratorType) { }
|
||||
|
||||
MovementGenerator* Create(void *) const override;
|
||||
};
|
||||
|
||||
typedef FactoryHolder<MovementGenerator, MovementGeneratorType> MovementGeneratorCreator;
|
||||
typedef FactoryHolder<MovementGenerator, MovementGeneratorType>::FactoryHolderRegistry MovementGeneratorRegistry;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
template<class MOVEMENT_GEN>
|
||||
inline MovementGenerator*
|
||||
MovementGeneratorFactory<MOVEMENT_GEN>::Create(void * /*data*/) const
|
||||
template<class Movement>
|
||||
inline MovementGenerator* MovementGeneratorFactory<Movement>::Create(void * /*data*/) const
|
||||
{
|
||||
return (new MOVEMENT_GEN());
|
||||
return (new Movement());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,92 +16,95 @@
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "ConfusedMovementGenerator.h"
|
||||
#include "Player.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "Player.h"
|
||||
#include "Random.h"
|
||||
#include "ConfusedMovementGenerator.h"
|
||||
|
||||
template<class T>
|
||||
void ConfusedMovementGenerator<T>::DoInitialize(T* unit)
|
||||
ConfusedMovementGenerator<T>::~ConfusedMovementGenerator()
|
||||
{
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED);
|
||||
unit->AddUnitFlag(UNIT_FLAG_CONFUSED);
|
||||
unit->GetPosition(i_x, i_y, i_z);
|
||||
|
||||
if (!unit->IsAlive() || unit->IsStopped())
|
||||
return;
|
||||
|
||||
unit->StopMoving();
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
|
||||
delete _path;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ConfusedMovementGenerator<T>::DoReset(T* unit)
|
||||
void ConfusedMovementGenerator<T>::DoInitialize(T* owner)
|
||||
{
|
||||
i_nextMoveTime.Reset(0);
|
||||
|
||||
if (!unit->IsAlive() || unit->IsStopped())
|
||||
if (!owner || !owner->IsAlive())
|
||||
return;
|
||||
|
||||
unit->StopMoving();
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
|
||||
owner->AddUnitState(UNIT_STATE_CONFUSED);
|
||||
owner->AddUnitFlag(UNIT_FLAG_CONFUSED);
|
||||
owner->StopMoving();
|
||||
|
||||
_timer.Reset(0);
|
||||
owner->GetPosition(_reference.m_positionX, _reference.m_positionY, _reference.m_positionZ);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff)
|
||||
void ConfusedMovementGenerator<T>::DoReset(T* owner)
|
||||
{
|
||||
if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
|
||||
return true;
|
||||
DoInitialize(owner);
|
||||
}
|
||||
|
||||
if (i_nextMoveTime.Passed())
|
||||
template<class T>
|
||||
bool ConfusedMovementGenerator<T>::DoUpdate(T* owner, uint32 diff)
|
||||
{
|
||||
if (!owner || !owner->IsAlive())
|
||||
return false;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
// currently moving, update location
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
|
||||
|
||||
if (unit->movespline->Finalized())
|
||||
i_nextMoveTime.Reset(urand(800, 1500));
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
_interrupt = false;
|
||||
|
||||
// waiting for next move
|
||||
_timer.Update(diff);
|
||||
if (!_interrupt && _timer.Passed() && owner->movespline->Finalized())
|
||||
{
|
||||
// waiting for next move
|
||||
i_nextMoveTime.Update(diff);
|
||||
if (i_nextMoveTime.Passed())
|
||||
// start moving
|
||||
owner->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
|
||||
|
||||
Position destination(_reference);
|
||||
float distance = 4.0f * frand(0.0f, 1.0f) - 2.0f;
|
||||
float angle = frand(0.0f, 1.0f) * float(M_PI) * 2.0f;
|
||||
owner->MovePositionToFirstCollision(destination, distance, angle);
|
||||
|
||||
if (!_path)
|
||||
_path = new PathGenerator(owner);
|
||||
|
||||
_path->SetPathLengthLimit(30.0f);
|
||||
bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
|
||||
if (!result || (_path->GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
// start moving
|
||||
unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE);
|
||||
|
||||
float dest = 4.0f * (float)rand_norm() - 2.0f;
|
||||
|
||||
Position pos;
|
||||
pos.Relocate(i_x, i_y, i_z);
|
||||
unit->MovePositionToFirstCollision(pos, dest, 0.0f);
|
||||
|
||||
PathGenerator path(unit);
|
||||
path.SetPathLengthLimit(30.0f);
|
||||
bool result = path.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
|
||||
if (!result || (path.GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
i_nextMoveTime.Reset(100);
|
||||
return true;
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.MovebyPath(path.GetPath());
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
_timer.Reset(100);
|
||||
return true;
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(_path->GetPath());
|
||||
init.SetWalk(true);
|
||||
int32 traveltime = init.Launch();
|
||||
_timer.Reset(traveltime + urand(800, 1500));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ConfusedMovementGenerator<T>::DoFinalize(T*) { }
|
||||
|
||||
template<>
|
||||
void ConfusedMovementGenerator<Player>::DoFinalize(Player* unit)
|
||||
{
|
||||
unit->RemoveUnitFlag(UNIT_FLAG_CONFUSED);
|
||||
unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE);
|
||||
unit->ClearUnitState(UNIT_STATE_CONFUSED);
|
||||
unit->StopMoving();
|
||||
}
|
||||
|
||||
@@ -114,6 +117,8 @@ void ConfusedMovementGenerator<Creature>::DoFinalize(Creature* unit)
|
||||
unit->SetTarget(unit->EnsureVictim()->GetGUID());
|
||||
}
|
||||
|
||||
template ConfusedMovementGenerator<Player>::~ConfusedMovementGenerator();
|
||||
template ConfusedMovementGenerator<Creature>::~ConfusedMovementGenerator();
|
||||
template void ConfusedMovementGenerator<Player>::DoInitialize(Player*);
|
||||
template void ConfusedMovementGenerator<Creature>::DoInitialize(Creature*);
|
||||
template void ConfusedMovementGenerator<Player>::DoReset(Player*);
|
||||
|
||||
@@ -25,16 +25,21 @@ template<class T>
|
||||
class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
explicit ConfusedMovementGenerator() : i_nextMoveTime(0), i_x(0), i_y(0), i_z(0) { }
|
||||
explicit ConfusedMovementGenerator() : _path(nullptr), _timer(0), _reference(0.f, 0.f, 0.f), _interrupt(false) { }
|
||||
~ConfusedMovementGenerator();
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return CONFUSED_MOTION_TYPE; }
|
||||
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, uint32);
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return CONFUSED_MOTION_TYPE; }
|
||||
private:
|
||||
TimeTracker i_nextMoveTime;
|
||||
float i_x, i_y, i_z;
|
||||
PathGenerator* _path;
|
||||
TimeTracker _timer;
|
||||
Position _reference;
|
||||
bool _interrupt;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,106 +15,24 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "VMapFactory.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "FleeingMovementGenerator.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Creature.h"
|
||||
#include "Player.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "PhasingHandler.h"
|
||||
#include "Player.h"
|
||||
#include "VMapFactory.h"
|
||||
#include "FleeingMovementGenerator.h"
|
||||
|
||||
#define MIN_QUIET_DISTANCE 28.0f
|
||||
#define MAX_QUIET_DISTANCE 43.0f
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
|
||||
FleeingMovementGenerator<T>::~FleeingMovementGenerator()
|
||||
{
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
||||
return;
|
||||
|
||||
if (owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
owner->CastStop();
|
||||
return;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
|
||||
float x, y, z;
|
||||
_getPoint(owner, x, y, z);
|
||||
|
||||
// Add LOS check for target point
|
||||
Position mypos = owner->GetPosition();
|
||||
bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(
|
||||
PhasingHandler::GetTerrainMapId(owner->GetPhaseShift(), owner->GetMap(), mypos.m_positionX, mypos.m_positionY),
|
||||
mypos.m_positionX, mypos.m_positionY, mypos.m_positionZ + 2.0f, x, y, z + 2.0f, VMAP::ModelIgnoreFlags::Nothing);
|
||||
if (!isInLOS)
|
||||
{
|
||||
i_nextCheckTime.Reset(200);
|
||||
return;
|
||||
}
|
||||
|
||||
PathGenerator path(owner);
|
||||
path.SetPathLengthLimit(30.0f);
|
||||
bool result = path.CalculatePath(x, y, z);
|
||||
if (!result || (path.GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
i_nextCheckTime.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(path.GetPath());
|
||||
init.SetWalk(false);
|
||||
int32 traveltime = init.Launch();
|
||||
i_nextCheckTime.Reset(traveltime + urand(800, 1500));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float &z)
|
||||
{
|
||||
float dist_from_caster, angle_to_caster;
|
||||
if (Unit* fright = ObjectAccessor::GetUnit(*owner, i_frightGUID))
|
||||
{
|
||||
dist_from_caster = fright->GetDistance(owner);
|
||||
if (dist_from_caster > 0.2f)
|
||||
angle_to_caster = fright->GetAngle(owner);
|
||||
else
|
||||
angle_to_caster = frand(0, 2 * static_cast<float>(M_PI));
|
||||
}
|
||||
else
|
||||
{
|
||||
dist_from_caster = 0.0f;
|
||||
angle_to_caster = frand(0, 2 * static_cast<float>(M_PI));
|
||||
}
|
||||
|
||||
float dist, angle;
|
||||
if (dist_from_caster < MIN_QUIET_DISTANCE)
|
||||
{
|
||||
dist = frand(0.4f, 1.3f)*(MIN_QUIET_DISTANCE - dist_from_caster);
|
||||
angle = angle_to_caster + frand(-static_cast<float>(M_PI)/8, static_cast<float>(M_PI)/8);
|
||||
}
|
||||
else if (dist_from_caster > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
dist = frand(0.4f, 1.0f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE);
|
||||
angle = -angle_to_caster + frand(-static_cast<float>(M_PI)/4, static_cast<float>(M_PI)/4);
|
||||
}
|
||||
else // we are inside quiet range
|
||||
{
|
||||
dist = frand(0.6f, 1.2f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE);
|
||||
angle = frand(0, 2*static_cast<float>(M_PI));
|
||||
}
|
||||
|
||||
Position pos = owner->GetFirstCollisionPosition(dist, angle);
|
||||
x = pos.m_positionX;
|
||||
y = pos.m_positionY;
|
||||
z = pos.m_positionZ;
|
||||
delete _path;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -124,15 +42,20 @@ void FleeingMovementGenerator<T>::DoInitialize(T* owner)
|
||||
return;
|
||||
|
||||
owner->AddUnitFlag(UNIT_FLAG_FLEEING);
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
|
||||
_setTargetLocation(owner);
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING);
|
||||
SetTargetLocation(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::DoFinalize(T *)
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
void FleeingMovementGenerator<Player>::DoFinalize(Player* owner)
|
||||
{
|
||||
owner->RemoveUnitFlag(UNIT_FLAG_FLEEING);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING);
|
||||
owner->StopMoving();
|
||||
}
|
||||
|
||||
@@ -140,7 +63,7 @@ template<>
|
||||
void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
{
|
||||
owner->RemoveUnitFlag(UNIT_FLAG_FLEEING);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
|
||||
if (owner->GetVictim())
|
||||
owner->SetTarget(owner->EnsureVictim()->GetGUID());
|
||||
}
|
||||
@@ -152,39 +75,143 @@ void FleeingMovementGenerator<T>::DoReset(T* owner)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||
bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 diff)
|
||||
{
|
||||
if (!owner || !owner->IsAlive())
|
||||
return false;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
_interrupt = false;
|
||||
|
||||
i_nextCheckTime.Update(time_diff);
|
||||
if (i_nextCheckTime.Passed() && owner->movespline->Finalized())
|
||||
_setTargetLocation(owner);
|
||||
_timer.Update(diff);
|
||||
if (!_interrupt && _timer.Passed() && owner->movespline->Finalized())
|
||||
SetTargetLocation(owner);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::SetTargetLocation(T* owner)
|
||||
{
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
|
||||
Position destination = owner->GetPosition();
|
||||
GetPoint(owner, destination);
|
||||
|
||||
// Add LOS check for target point
|
||||
Position currentPosition = owner->GetPosition();
|
||||
if (!VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(owner->GetPhaseShift(), owner->GetMap(), currentPosition.m_positionX, currentPosition.m_positionY), currentPosition.m_positionX, currentPosition.m_positionY, currentPosition.m_positionZ + 2.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 2.0f, VMAP::ModelIgnoreFlags::Nothing))
|
||||
{
|
||||
_timer.Reset(200);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_path)
|
||||
_path = new PathGenerator(owner);
|
||||
|
||||
_path->SetPathLengthLimit(30.0f);
|
||||
bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
|
||||
if (!result || (_path->GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
_timer.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(_path->GetPath());
|
||||
init.SetWalk(false);
|
||||
int32 traveltime = init.Launch();
|
||||
_timer.Reset(traveltime + urand(800, 1500));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FleeingMovementGenerator<T>::GetPoint(T* owner, Position &position)
|
||||
{
|
||||
float casterDistance, casterAngle;
|
||||
if (Unit* fleeTarget = ObjectAccessor::GetUnit(*owner, _fleeTargetGUID))
|
||||
{
|
||||
casterDistance = fleeTarget->GetDistance(owner);
|
||||
if (casterDistance > 0.2f)
|
||||
casterAngle = fleeTarget->GetAngle(owner);
|
||||
else
|
||||
casterAngle = frand(0.0f, 2.0f * float(M_PI));
|
||||
}
|
||||
else
|
||||
{
|
||||
casterDistance = 0.0f;
|
||||
casterAngle = frand(0.0f, 2.0f * float(M_PI));
|
||||
}
|
||||
|
||||
float distance, angle;
|
||||
if (casterDistance < MIN_QUIET_DISTANCE)
|
||||
{
|
||||
distance = frand(0.4f, 1.3f) * (MIN_QUIET_DISTANCE - casterDistance);
|
||||
angle = casterAngle + frand(-float(M_PI) / 8.0f, float(M_PI) / 8.0f);
|
||||
}
|
||||
else if (casterDistance > MAX_QUIET_DISTANCE)
|
||||
{
|
||||
distance = frand(0.4f, 1.0f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE);
|
||||
angle = -casterAngle + frand(-float(M_PI) / 4.0f, float(M_PI) / 4.0f);
|
||||
}
|
||||
else // we are inside quiet range
|
||||
{
|
||||
distance = frand(0.6f, 1.2f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE);
|
||||
angle = frand(0.0f, 2.0f * float(M_PI));
|
||||
}
|
||||
|
||||
owner->MovePositionToFirstCollision(position, distance, angle);
|
||||
}
|
||||
|
||||
template FleeingMovementGenerator<Player>::~FleeingMovementGenerator();
|
||||
template FleeingMovementGenerator<Creature>::~FleeingMovementGenerator();
|
||||
template void FleeingMovementGenerator<Player>::DoInitialize(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::DoInitialize(Creature*);
|
||||
template void FleeingMovementGenerator<Player>::_getPoint(Player*, float&, float&, float&);
|
||||
template void FleeingMovementGenerator<Creature>::_getPoint(Creature*, float&, float&, float&);
|
||||
template void FleeingMovementGenerator<Player>::_setTargetLocation(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::_setTargetLocation(Creature*);
|
||||
template void FleeingMovementGenerator<Player>::DoReset(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::DoReset(Creature*);
|
||||
template bool FleeingMovementGenerator<Player>::DoUpdate(Player*, uint32);
|
||||
template bool FleeingMovementGenerator<Creature>::DoUpdate(Creature*, uint32);
|
||||
template void FleeingMovementGenerator<Player>::SetTargetLocation(Player*);
|
||||
template void FleeingMovementGenerator<Creature>::SetTargetLocation(Creature*);
|
||||
template void FleeingMovementGenerator<Player>::GetPoint(Player*, Position &);
|
||||
template void FleeingMovementGenerator<Creature>::GetPoint(Creature*, Position &);
|
||||
|
||||
//---- TimedFleeingMovementGenerator
|
||||
|
||||
bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff)
|
||||
{
|
||||
if (!owner->IsAlive())
|
||||
return false;
|
||||
|
||||
_totalFleeTime.Update(time_diff);
|
||||
if (_totalFleeTime.Passed())
|
||||
return false;
|
||||
|
||||
// This calls grant-parent Update method hiden by FleeingMovementGenerator::Update(Creature &, uint32) version
|
||||
// This is done instead of casting Unit& to Creature& and call parent method, then we can use Unit directly
|
||||
return MovementGeneratorMedium< Creature, FleeingMovementGenerator<Creature> >::Update(owner, time_diff);
|
||||
}
|
||||
|
||||
void TimedFleeingMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
owner->RemoveUnitFlag(UNIT_FLAG_FLEEING);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE);
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING);
|
||||
owner->StopMoving();
|
||||
if (Unit* victim = owner->GetVictim())
|
||||
{
|
||||
if (owner->IsAlive())
|
||||
@@ -194,23 +221,3 @@ void TimedFleeingMovementGenerator::Finalize(Unit* owner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff)
|
||||
{
|
||||
if (!owner->IsAlive())
|
||||
return false;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE);
|
||||
return true;
|
||||
}
|
||||
|
||||
i_totalFleeTime.Update(time_diff);
|
||||
if (i_totalFleeTime.Passed())
|
||||
return false;
|
||||
|
||||
// This calls grant-parent Update method hiden by FleeingMovementGenerator::Update(Creature &, uint32) version
|
||||
// This is done instead of casting Unit& to Creature& and call parent method, then we can use Unit directly
|
||||
return MovementGeneratorMedium< Creature, FleeingMovementGenerator<Creature> >::Update(owner, time_diff);
|
||||
}
|
||||
|
||||
@@ -19,41 +19,43 @@
|
||||
#define TRINITY_FLEEINGMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "Timer.h"
|
||||
|
||||
template<class T>
|
||||
class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
FleeingMovementGenerator(ObjectGuid fright) : i_frightGUID(fright), i_nextCheckTime(0) { }
|
||||
explicit FleeingMovementGenerator(ObjectGuid fleeTargetGUID) : _path(nullptr), _fleeTargetGUID(fleeTargetGUID), _timer(0), _interrupt(false) { }
|
||||
~FleeingMovementGenerator();
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return FLEEING_MOTION_TYPE; }
|
||||
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, uint32);
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return FLEEING_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
void _setTargetLocation(T*);
|
||||
void _getPoint(T*, float &x, float &y, float &z);
|
||||
void SetTargetLocation(T*);
|
||||
void GetPoint(T*, Position &position);
|
||||
|
||||
ObjectGuid i_frightGUID;
|
||||
TimeTracker i_nextCheckTime;
|
||||
PathGenerator* _path;
|
||||
ObjectGuid _fleeTargetGUID;
|
||||
TimeTracker _timer;
|
||||
bool _interrupt;
|
||||
};
|
||||
|
||||
class TimedFleeingMovementGenerator : public FleeingMovementGenerator<Creature>
|
||||
{
|
||||
public:
|
||||
TimedFleeingMovementGenerator(ObjectGuid fright, uint32 time) :
|
||||
FleeingMovementGenerator<Creature>(fright),
|
||||
i_totalFleeTime(time) { }
|
||||
explicit TimedFleeingMovementGenerator(ObjectGuid fleeTargetGUID, uint32 time) : FleeingMovementGenerator<Creature>(fleeTargetGUID), _totalFleeTime(time) { }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return TIMED_FLEEING_MOTION_TYPE; }
|
||||
bool Update(Unit*, uint32) override;
|
||||
void Finalize(Unit*) override;
|
||||
|
||||
private:
|
||||
TimeTracker i_totalFleeTime;
|
||||
TimeTracker _totalFleeTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,36 +15,31 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "HomeMovementGenerator.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "HomeMovementGenerator.h"
|
||||
|
||||
void HomeMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
template<class T>
|
||||
HomeMovementGenerator<T>::~HomeMovementGenerator() { }
|
||||
|
||||
template<>
|
||||
HomeMovementGenerator<Creature>::~HomeMovementGenerator()
|
||||
{
|
||||
_setTargetLocation(owner);
|
||||
delete _path;
|
||||
}
|
||||
|
||||
void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
{
|
||||
if (arrived)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_EVADE);
|
||||
owner->SetWalk(true);
|
||||
owner->LoadCreaturesAddon();
|
||||
owner->AI()->JustReachedHome();
|
||||
owner->SetSpawnHealth();
|
||||
}
|
||||
}
|
||||
template<class T>
|
||||
void HomeMovementGenerator<T>::SetTargetLocation(T*) { }
|
||||
|
||||
void HomeMovementGenerator<Creature>::DoReset(Creature*) { }
|
||||
|
||||
void HomeMovementGenerator<Creature>::_setTargetLocation(Creature* owner)
|
||||
template<>
|
||||
void HomeMovementGenerator<Creature>::SetTargetLocation(Creature* owner)
|
||||
{
|
||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
|
||||
{ // if we are ROOT/STUNNED/DISTRACTED even after aura clear, finalize on next update - otherwise we would get stuck in evade
|
||||
skipToHome = true;
|
||||
_skipToHome = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,14 +55,55 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature* owner)
|
||||
init.SetWalk(false);
|
||||
init.Launch();
|
||||
|
||||
skipToHome = false;
|
||||
arrived = false;
|
||||
_skipToHome = false;
|
||||
_arrived = false;
|
||||
|
||||
owner->ClearUnitState(UNIT_STATE_ALL_ERASABLE & ~UNIT_STATE_EVADE);
|
||||
}
|
||||
|
||||
bool HomeMovementGenerator<Creature>::DoUpdate(Creature* owner, const uint32 /*time_diff*/)
|
||||
template<class T>
|
||||
void HomeMovementGenerator<T>::DoInitialize(T*) { }
|
||||
|
||||
template<>
|
||||
void HomeMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
{
|
||||
arrived = skipToHome || owner->movespline->Finalized();
|
||||
return !arrived;
|
||||
SetTargetLocation(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void HomeMovementGenerator<T>::DoFinalize(T*) { }
|
||||
|
||||
template<>
|
||||
void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
{
|
||||
if (_arrived)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_EVADE);
|
||||
owner->SetWalk(true);
|
||||
owner->LoadCreaturesAddon();
|
||||
owner->AI()->JustReachedHome();
|
||||
owner->SetSpawnHealth();
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void HomeMovementGenerator<T>::DoReset(T*) { }
|
||||
|
||||
template<>
|
||||
void HomeMovementGenerator<Creature>::DoReset(Creature* owner)
|
||||
{
|
||||
DoInitialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool HomeMovementGenerator<T>::DoUpdate(T*, uint32)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HomeMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 /*diff*/)
|
||||
{
|
||||
_arrived = _skipToHome || owner->movespline->Finalized();
|
||||
return !_arrived;
|
||||
}
|
||||
|
||||
@@ -20,28 +20,26 @@
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
class Creature;
|
||||
|
||||
template < class T >
|
||||
class HomeMovementGenerator;
|
||||
|
||||
template <>
|
||||
class HomeMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, HomeMovementGenerator<Creature> >
|
||||
template <class T>
|
||||
class HomeMovementGenerator : public MovementGeneratorMedium< T, HomeMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
explicit HomeMovementGenerator() : _path(nullptr), _arrived(false), _skipToHome(false) { }
|
||||
~HomeMovementGenerator();
|
||||
|
||||
HomeMovementGenerator() : arrived(false), skipToHome(false) { }
|
||||
~HomeMovementGenerator() { }
|
||||
|
||||
void DoInitialize(Creature*);
|
||||
void DoFinalize(Creature*);
|
||||
void DoReset(Creature*);
|
||||
bool DoUpdate(Creature*, const uint32);
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return HOME_MOTION_TYPE; }
|
||||
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, uint32);
|
||||
|
||||
private:
|
||||
void _setTargetLocation(Creature*);
|
||||
bool arrived;
|
||||
bool skipToHome;
|
||||
void SetTargetLocation(T*);
|
||||
|
||||
PathGenerator* _path;
|
||||
bool _arrived;
|
||||
bool _skipToHome;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,8 @@ void IdleMovementGenerator::Reset(Unit* owner)
|
||||
owner->StopMoving();
|
||||
}
|
||||
|
||||
//----------------------------------------------------//
|
||||
|
||||
void RotateMovementGenerator::Initialize(Unit* owner)
|
||||
{
|
||||
if (!owner->IsStopped())
|
||||
@@ -50,27 +52,29 @@ void RotateMovementGenerator::Initialize(Unit* owner)
|
||||
bool RotateMovementGenerator::Update(Unit* owner, uint32 diff)
|
||||
{
|
||||
float angle = owner->GetOrientation();
|
||||
angle += (float(diff) * static_cast<float>(M_PI * 2) / m_maxDuration) * (m_direction == ROTATE_DIRECTION_LEFT ? 1.0f : -1.0f);
|
||||
angle += (float(diff) * static_cast<float>(M_PI * 2) / _maxDuration) * (_direction == ROTATE_DIRECTION_LEFT ? 1.0f : -1.0f);
|
||||
angle = G3D::wrap(angle, 0.0f, float(G3D::twoPi()));
|
||||
|
||||
owner->SetOrientation(angle); // UpdateSplinePosition does not set orientation with UNIT_STATE_ROTATING
|
||||
owner->SetFacingTo(angle); // Send spline movement to clients
|
||||
|
||||
if (m_duration > diff)
|
||||
m_duration -= diff;
|
||||
if (_duration > diff)
|
||||
_duration -= diff;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RotateMovementGenerator::Finalize(Unit* unit)
|
||||
void RotateMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
unit->ClearUnitState(UNIT_STATE_ROTATING);
|
||||
if (unit->GetTypeId() == TYPEID_UNIT)
|
||||
unit->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0);
|
||||
owner->ClearUnitState(UNIT_STATE_ROTATING);
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
owner->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------//
|
||||
|
||||
void DistractMovementGenerator::Initialize(Unit* owner)
|
||||
{
|
||||
// Distracted creatures stand up if not standing
|
||||
@@ -92,17 +96,19 @@ void DistractMovementGenerator::Finalize(Unit* owner)
|
||||
}
|
||||
}
|
||||
|
||||
bool DistractMovementGenerator::Update(Unit* /*owner*/, uint32 time_diff)
|
||||
bool DistractMovementGenerator::Update(Unit* /*owner*/, uint32 diff)
|
||||
{
|
||||
if (time_diff > m_timer)
|
||||
if (diff > _timer)
|
||||
return false;
|
||||
|
||||
m_timer -= time_diff;
|
||||
_timer -= diff;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssistanceDistractMovementGenerator::Finalize(Unit* unit)
|
||||
//----------------------------------------------------//
|
||||
|
||||
void AssistanceDistractMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
unit->ClearUnitState(UNIT_STATE_DISTRACTED);
|
||||
unit->ToCreature()->SetReactState(REACT_AGGRESSIVE);
|
||||
owner->ClearUnitState(UNIT_STATE_DISTRACTED);
|
||||
owner->ToCreature()->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
#define TRINITY_IDLEMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "Timer.h"
|
||||
|
||||
class IdleMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
|
||||
void Initialize(Unit*) override;
|
||||
void Finalize(Unit*) override { }
|
||||
void Reset(Unit*) override;
|
||||
@@ -36,7 +36,7 @@ TC_GAME_API extern IdleMovementGenerator si_idleMovement;
|
||||
class RotateMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : m_duration(time), m_maxDuration(time), m_direction(direction) { }
|
||||
explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : _duration(time), _maxDuration(time), _direction(direction) { }
|
||||
|
||||
void Initialize(Unit*) override;
|
||||
void Finalize(Unit*) override;
|
||||
@@ -45,14 +45,14 @@ class RotateMovementGenerator : public MovementGenerator
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return ROTATE_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
uint32 m_duration, m_maxDuration;
|
||||
RotateDirection m_direction;
|
||||
uint32 _duration, _maxDuration;
|
||||
RotateDirection _direction;
|
||||
};
|
||||
|
||||
class DistractMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) { }
|
||||
explicit DistractMovementGenerator(uint32 timer) : _timer(timer) { }
|
||||
|
||||
void Initialize(Unit*) override;
|
||||
void Finalize(Unit*) override;
|
||||
@@ -61,14 +61,13 @@ class DistractMovementGenerator : public MovementGenerator
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return DISTRACT_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
uint32 m_timer;
|
||||
uint32 _timer;
|
||||
};
|
||||
|
||||
class AssistanceDistractMovementGenerator : public DistractMovementGenerator
|
||||
{
|
||||
public:
|
||||
AssistanceDistractMovementGenerator(uint32 timer) :
|
||||
DistractMovementGenerator(timer) { }
|
||||
explicit AssistanceDistractMovementGenerator(uint32 timer) : DistractMovementGenerator(timer) { }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return ASSISTANCE_DISTRACT_MOTION_TYPE; }
|
||||
void Finalize(Unit*) override;
|
||||
|
||||
@@ -15,33 +15,42 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PointMovementGenerator.h"
|
||||
#include "Errors.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "World.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "Player.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "Player.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "World.h"
|
||||
#include "PointMovementGenerator.h"
|
||||
|
||||
//----- Point Movement Generator
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||
void PointMovementGenerator<T>::DoInitialize(T* owner)
|
||||
{
|
||||
if (!unit->IsStopped())
|
||||
unit->StopMoving();
|
||||
|
||||
unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (id == EVENT_CHARGE_PREPATH)
|
||||
if (_movementId == EVENT_CHARGE_PREPATH)
|
||||
{
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
return;
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.MoveTo(i_x, i_y, i_z, m_generatePath);
|
||||
if (speed > 0.0f)
|
||||
init.SetVelocity(speed);
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING);
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ(), _generatePath);
|
||||
if (_speed > 0.0f)
|
||||
init.SetVelocity(_speed);
|
||||
if (i_faceTarget)
|
||||
init.SetFacing(i_faceTarget);
|
||||
if (i_spellEffectExtra)
|
||||
@@ -49,69 +58,73 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||
init.Launch();
|
||||
|
||||
// Call for creature group update
|
||||
if (Creature* creature = unit->ToCreature())
|
||||
if (Creature* creature = owner->ToCreature())
|
||||
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
|
||||
creature->GetFormation()->LeaderMoveTo(i_x, i_y, i_z);
|
||||
creature->GetFormation()->LeaderMoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
||||
bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/)
|
||||
{
|
||||
if (!unit)
|
||||
if (!owner)
|
||||
return false;
|
||||
|
||||
if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
||||
if (_movementId == EVENT_CHARGE_PREPATH)
|
||||
return !owner->movespline->Finalized();
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
unit->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
|
||||
unit->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (id != EVENT_CHARGE_PREPATH && i_recalculateSpeed && !unit->movespline->Finalized())
|
||||
if ((_interrupt && owner->movespline->Finalized()) || (_recalculateSpeed && !owner->movespline->Finalized()))
|
||||
{
|
||||
i_recalculateSpeed = false;
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.MoveTo(i_x, i_y, i_z, m_generatePath);
|
||||
if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit
|
||||
init.SetVelocity(speed);
|
||||
_recalculateSpeed = false;
|
||||
_interrupt = false;
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ(), _generatePath);
|
||||
if (_speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit
|
||||
init.SetVelocity(_speed);
|
||||
init.Launch();
|
||||
|
||||
// Call for creature group update
|
||||
if (Creature* creature = unit->ToCreature())
|
||||
if (Creature* creature = owner->ToCreature())
|
||||
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
|
||||
creature->GetFormation()->LeaderMoveTo(i_x, i_y, i_z);
|
||||
creature->GetFormation()->LeaderMoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ());
|
||||
}
|
||||
|
||||
return !unit->movespline->Finalized();
|
||||
return !owner->movespline->Finalized();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::DoFinalize(T* unit)
|
||||
void PointMovementGenerator<T>::DoFinalize(T* owner)
|
||||
{
|
||||
if (unit->HasUnitState(UNIT_STATE_CHARGING))
|
||||
unit->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (unit->movespline->Finalized())
|
||||
MovementInform(unit);
|
||||
if (owner->movespline->Finalized())
|
||||
MovementInform(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::DoReset(T* unit)
|
||||
void PointMovementGenerator<T>::DoReset(T* owner)
|
||||
{
|
||||
if (!unit->IsStopped())
|
||||
unit->StopMoving();
|
||||
|
||||
unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
|
||||
owner->StopMoving();
|
||||
DoInitialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PointMovementGenerator<T>::MovementInform(T* /*unit*/) { }
|
||||
void PointMovementGenerator<T>::MovementInform(T*) { }
|
||||
|
||||
template <> void PointMovementGenerator<Creature>::MovementInform(Creature* unit)
|
||||
template <>
|
||||
void PointMovementGenerator<Creature>::MovementInform(Creature* owner)
|
||||
{
|
||||
if (unit->AI())
|
||||
unit->AI()->MovementInform(POINT_MOTION_TYPE, id);
|
||||
if (owner->AI())
|
||||
owner->AI()->MovementInform(POINT_MOTION_TYPE, _movementId);
|
||||
}
|
||||
|
||||
template void PointMovementGenerator<Player>::DoInitialize(Player*);
|
||||
@@ -123,34 +136,36 @@ template void PointMovementGenerator<Creature>::DoReset(Creature*);
|
||||
template bool PointMovementGenerator<Player>::DoUpdate(Player*, uint32);
|
||||
template bool PointMovementGenerator<Creature>::DoUpdate(Creature*, uint32);
|
||||
|
||||
void AssistanceMovementGenerator::Finalize(Unit* unit)
|
||||
//---- AssistanceMovementGenerator
|
||||
|
||||
void AssistanceMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
unit->ToCreature()->SetNoCallAssistance(false);
|
||||
unit->ToCreature()->CallAssistance();
|
||||
if (unit->IsAlive())
|
||||
unit->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY));
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING);
|
||||
owner->StopMoving();
|
||||
owner->ToCreature()->SetNoCallAssistance(false);
|
||||
owner->ToCreature()->CallAssistance();
|
||||
if (owner->IsAlive())
|
||||
owner->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY));
|
||||
}
|
||||
|
||||
bool EffectMovementGenerator::Update(Unit* unit, uint32)
|
||||
//---- EffectMovementGenerator
|
||||
|
||||
bool EffectMovementGenerator::Update(Unit* owner, uint32 /*diff*/)
|
||||
{
|
||||
return !unit->movespline->Finalized();
|
||||
return !owner->movespline->Finalized();
|
||||
}
|
||||
|
||||
void EffectMovementGenerator::Finalize(Unit* unit)
|
||||
void EffectMovementGenerator::Finalize(Unit* owner)
|
||||
{
|
||||
MovementInform(owner);
|
||||
}
|
||||
|
||||
void EffectMovementGenerator::MovementInform(Unit* owner)
|
||||
{
|
||||
if (_arrivalSpellId)
|
||||
unit->CastSpell(ObjectAccessor::GetUnit(*unit, _arrivalSpellTargetGuid), _arrivalSpellId, true);
|
||||
owner->CastSpell(ObjectAccessor::GetUnit(*owner, _arrivalSpellTargetGuid), _arrivalSpellId, true);
|
||||
|
||||
if (unit->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
|
||||
// Need restore previous movement since we have no proper states system
|
||||
if (unit->IsAlive() && !unit->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING))
|
||||
{
|
||||
if (Unit* victim = unit->GetVictim())
|
||||
unit->GetMotionMaster()->MoveChase(victim);
|
||||
}
|
||||
|
||||
if (unit->ToCreature()->AI())
|
||||
unit->ToCreature()->AI()->MovementInform(EFFECT_MOTION_TYPE, _id);
|
||||
if (Creature* creature = owner->ToCreature())
|
||||
if (creature->AI())
|
||||
creature->AI()->MovementInform(EFFECT_MOTION_TYPE, _pointId);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#define TRINITY_POINTMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "FollowerReference.h"
|
||||
|
||||
class Creature;
|
||||
namespace Movement
|
||||
@@ -31,56 +30,54 @@ template<class T>
|
||||
class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
PointMovementGenerator(uint32 _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f, Unit const* faceTarget = nullptr,
|
||||
Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr) : id(_id),
|
||||
i_x(_x), i_y(_y), i_z(_z), speed(_speed), i_faceTarget(faceTarget), i_spellEffectExtra(spellEffectExtraData),
|
||||
m_generatePath(_generatePath), i_recalculateSpeed(false) { }
|
||||
explicit PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, float speed = 0.0f, Unit const* faceTarget = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr) : _movementId(id), _destination(x, y, z), _speed(speed), i_faceTarget(faceTarget), i_spellEffectExtra(spellEffectExtraData), _generatePath(generatePath), _recalculateSpeed(false), _interrupt(false) { }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return POINT_MOTION_TYPE; }
|
||||
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, uint32);
|
||||
|
||||
void UnitSpeedChanged() override { _recalculateSpeed = true; }
|
||||
|
||||
private:
|
||||
void MovementInform(T*);
|
||||
|
||||
void unitSpeedChanged() override { i_recalculateSpeed = true; }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return POINT_MOTION_TYPE; }
|
||||
|
||||
void GetDestination(float& x, float& y, float& z) const { x = i_x; y = i_y; z = i_z; }
|
||||
private:
|
||||
uint32 id;
|
||||
float i_x, i_y, i_z;
|
||||
float speed;
|
||||
uint32 _movementId;
|
||||
Position _destination;
|
||||
float _speed;
|
||||
Unit const* i_faceTarget;
|
||||
Movement::SpellEffectExtraData const* i_spellEffectExtra;
|
||||
bool m_generatePath;
|
||||
bool i_recalculateSpeed;
|
||||
bool _generatePath;
|
||||
bool _recalculateSpeed;
|
||||
bool _interrupt;
|
||||
};
|
||||
|
||||
class AssistanceMovementGenerator : public PointMovementGenerator<Creature>
|
||||
{
|
||||
public:
|
||||
AssistanceMovementGenerator(float _x, float _y, float _z) :
|
||||
PointMovementGenerator<Creature>(0, _x, _y, _z, true) { }
|
||||
explicit AssistanceMovementGenerator(float _x, float _y, float _z) : PointMovementGenerator<Creature>(0, _x, _y, _z, true) { }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return ASSISTANCE_MOTION_TYPE; }
|
||||
void Finalize(Unit*) override;
|
||||
};
|
||||
|
||||
// Does almost nothing - just doesn't allows previous movegen interrupt current effect.
|
||||
class EffectMovementGenerator : public MovementGenerator
|
||||
{
|
||||
public:
|
||||
EffectMovementGenerator(uint32 id, uint32 arrivalSpellId = 0, ObjectGuid const& arrivalSpellTargetGuid = ObjectGuid::Empty)
|
||||
: _id(id), _arrivalSpellId(arrivalSpellId), _arrivalSpellTargetGuid(arrivalSpellTargetGuid) { }
|
||||
explicit EffectMovementGenerator(uint32 id, uint32 arrivalSpellId = 0, ObjectGuid const& arrivalSpellTargetGuid = ObjectGuid::Empty) : _pointId(id), _arrivalSpellId(arrivalSpellId), _arrivalSpellTargetGuid(arrivalSpellTargetGuid) { }
|
||||
|
||||
void Initialize(Unit*) override { }
|
||||
void Finalize(Unit*) override;
|
||||
void Reset(Unit*) override { }
|
||||
bool Update(Unit*, uint32) override;
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return EFFECT_MOTION_TYPE; }
|
||||
|
||||
private:
|
||||
uint32 _id;
|
||||
void MovementInform(Unit*);
|
||||
|
||||
uint32 _pointId;
|
||||
uint32 _arrivalSpellId;
|
||||
ObjectGuid _arrivalSpellTargetGuid;
|
||||
};
|
||||
|
||||
@@ -16,165 +16,133 @@
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "RandomMovementGenerator.h"
|
||||
#include "Map.h"
|
||||
#include "Util.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "Map.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "Random.h"
|
||||
#include "RandomMovementGenerator.h"
|
||||
|
||||
#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV"
|
||||
template<class T>
|
||||
RandomMovementGenerator<T>::~RandomMovementGenerator() { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
|
||||
RandomMovementGenerator<Creature>::~RandomMovementGenerator()
|
||||
{
|
||||
if (creature->IsMovementPreventedByCasting())
|
||||
delete _path;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void RandomMovementGenerator<T>::DoInitialize(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
{
|
||||
if (!owner || !owner->IsAlive())
|
||||
return;
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING);
|
||||
owner->GetPosition(_reference.m_positionX, _reference.m_positionY, _reference.m_positionZ);
|
||||
owner->StopMoving();
|
||||
|
||||
if (!_wanderDistance)
|
||||
_wanderDistance = owner->GetRespawnRadius();
|
||||
|
||||
_timer.Reset(0);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void RandomMovementGenerator<T>::DoFinalize(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING);
|
||||
owner->StopMoving();
|
||||
owner->SetWalk(false);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void RandomMovementGenerator<T>::DoReset(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoReset(Creature* owner)
|
||||
{
|
||||
DoInitialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void RandomMovementGenerator<T>::SetRandomLocation(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner)
|
||||
{
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
creature->CastStop();
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return;
|
||||
}
|
||||
|
||||
float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ;
|
||||
creature->GetHomePosition(respX, respY, respZ, respO);
|
||||
Map const* map = creature->GetMap();
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
// For 2D/3D system selection
|
||||
//bool is_land_ok = creature.CanWalk(); // not used?
|
||||
//bool is_water_ok = creature.CanSwim(); // not used?
|
||||
bool is_air_ok = creature->CanFly();
|
||||
Position position(_reference);
|
||||
float distance = frand(0.f, 1.f) * _wanderDistance;
|
||||
float angle = frand(0.f, 1.f) * float(M_PI) * 2.f;
|
||||
owner->MovePositionToFirstCollision(position, distance, angle);
|
||||
|
||||
const float angle = float(rand_norm()) * static_cast<float>(M_PI*2.0f);
|
||||
const float range = float(rand_norm()) * wander_distance;
|
||||
const float distanceX = range * std::cos(angle);
|
||||
const float distanceY = range * std::sin(angle);
|
||||
uint32 resetTimer = roll_chance_i(50) ? urand(5000, 10000) : urand(1000, 2000);
|
||||
|
||||
destX = respX + distanceX;
|
||||
destY = respY + distanceY;
|
||||
if (!_path)
|
||||
_path = new PathGenerator(owner);
|
||||
|
||||
// prevent invalid coordinates generation
|
||||
Trinity::NormalizeMapCoord(destX);
|
||||
Trinity::NormalizeMapCoord(destY);
|
||||
|
||||
travelDistZ = range; // sin^2+cos^2=1, so travelDistZ=range^2; no need for sqrt below
|
||||
|
||||
if (is_air_ok) // 3D system above ground and above water (flying mode)
|
||||
_path->SetPathLengthLimit(30.0f);
|
||||
bool result = _path->CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ());
|
||||
if (!result || (_path->GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
// Limit height change
|
||||
const float distanceZ = float(rand_norm()) * travelDistZ/2.0f;
|
||||
destZ = respZ + distanceZ;
|
||||
float levelZ = map->GetWaterOrGroundLevel(creature->GetPhaseShift(), destX, destY, destZ-2.5f);
|
||||
|
||||
// Problem here, we must fly above the ground and water, not under. Let's try on next tick
|
||||
if (levelZ >= destZ)
|
||||
return;
|
||||
}
|
||||
//else if (is_water_ok) // 3D system under water and above ground (swimming mode)
|
||||
else // 2D only
|
||||
{
|
||||
// 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
|
||||
travelDistZ = travelDistZ >= 10.0f ? 10.0f : travelDistZ;
|
||||
|
||||
// The fastest way to get an accurate result 90% of the time.
|
||||
// Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
|
||||
destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ+travelDistZ-2.0f, false);
|
||||
|
||||
if (std::fabs(destZ - respZ) > travelDistZ) // Map check
|
||||
{
|
||||
// Vmap Horizontal or above
|
||||
destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ - 2.0f, true);
|
||||
|
||||
if (std::fabs(destZ - respZ) > travelDistZ)
|
||||
{
|
||||
// Vmap Higher
|
||||
destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ+travelDistZ-2.0f, true);
|
||||
|
||||
// let's forget this bad coords where a z cannot be find and retry at next tick
|
||||
if (std::fabs(destZ - respZ) > travelDistZ)
|
||||
return;
|
||||
}
|
||||
}
|
||||
_timer.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_air_ok)
|
||||
i_nextMoveTime.Reset(0);
|
||||
else
|
||||
{
|
||||
if (roll_chance_i(50))
|
||||
i_nextMoveTime.Reset(urand(5000, 10000));
|
||||
else
|
||||
i_nextMoveTime.Reset(urand(50, 400));
|
||||
}
|
||||
|
||||
creature->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
Movement::MoveSplineInit init(creature);
|
||||
init.MoveTo(destX, destY, destZ);
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(_path->GetPath());
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
int32 traveltime = init.Launch();
|
||||
_timer.Reset(traveltime + resetTimer);
|
||||
|
||||
//Call for creature group update
|
||||
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
|
||||
creature->GetFormation()->LeaderMoveTo(destX, destY, destZ);
|
||||
// Call for creature group update
|
||||
if (owner->GetFormation() && owner->GetFormation()->getLeader() == owner)
|
||||
owner->GetFormation()->LeaderMoveTo(position.m_positionX, position.m_positionY, position.m_positionZ);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool RandomMovementGenerator<T>::DoUpdate(T*, uint32)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoInitialize(Creature* creature)
|
||||
bool RandomMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff)
|
||||
{
|
||||
if (!creature->IsAlive())
|
||||
return;
|
||||
|
||||
if (!wander_distance)
|
||||
wander_distance = creature->GetRespawnRadius();
|
||||
|
||||
creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
_setRandomLocation(creature);
|
||||
}
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoReset(Creature* creature)
|
||||
{
|
||||
DoInitialize(creature);
|
||||
}
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoFinalize(Creature* creature)
|
||||
{
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
|
||||
creature->SetWalk(false);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool RandomMovementGenerator<Creature>::DoUpdate(Creature* creature, const uint32 diff)
|
||||
{
|
||||
if (!creature || !creature->IsAlive())
|
||||
if (!owner || !owner->IsAlive())
|
||||
return false;
|
||||
|
||||
if (creature->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
i_nextMoveTime.Reset(0); // Expire the timer
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
_interrupt = false;
|
||||
|
||||
if (creature->movespline->Finalized())
|
||||
{
|
||||
i_nextMoveTime.Update(diff);
|
||||
if (i_nextMoveTime.Passed())
|
||||
_setRandomLocation(creature);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool RandomMovementGenerator<Creature>::GetResetPos(Creature* creature, float& x, float& y, float& z)
|
||||
{
|
||||
float radius;
|
||||
creature->GetRespawnPosition(x, y, z, NULL, &radius);
|
||||
|
||||
// use current if in range
|
||||
if (creature->IsWithinDist2d(x, y, radius))
|
||||
creature->GetPosition(x, y, z);
|
||||
_timer.Update(diff);
|
||||
if (!_interrupt && _timer.Passed() && owner->movespline->Finalized())
|
||||
SetRandomLocation(owner);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,23 +19,30 @@
|
||||
#define TRINITY_RANDOMMOTIONGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
#include "Timer.h"
|
||||
|
||||
template<class T>
|
||||
class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) { }
|
||||
explicit RandomMovementGenerator(float distance = 0.0f) : _path(nullptr), _timer(0), _reference(0.f, 0.f, 0.f), _wanderDistance(distance), _interrupt(false) { }
|
||||
~RandomMovementGenerator();
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; }
|
||||
|
||||
void _setRandomLocation(T*);
|
||||
void DoInitialize(T*);
|
||||
void DoFinalize(T*);
|
||||
void DoReset(T*);
|
||||
bool DoUpdate(T*, const uint32);
|
||||
bool GetResetPos(T*, float& x, float& y, float& z);
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; }
|
||||
private:
|
||||
TimeTrackerSmall i_nextMoveTime;
|
||||
bool DoUpdate(T*, uint32);
|
||||
|
||||
float wander_distance;
|
||||
private:
|
||||
void SetRandomLocation(T*);
|
||||
|
||||
PathGenerator* _path;
|
||||
TimeTracker _timer;
|
||||
Position _reference;
|
||||
float _wanderDistance;
|
||||
bool _interrupt;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,226 +15,209 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ByteBuffer.h"
|
||||
#include "TargetedMovementGenerator.h"
|
||||
#include "Errors.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "World.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "Creature.h"
|
||||
#include "Player.h"
|
||||
#include "VehicleDefines.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "World.h"
|
||||
#include "TargetedMovementGenerator.h"
|
||||
|
||||
template<class T, typename D>
|
||||
void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool updateDestination)
|
||||
TargetedMovementGenerator<T, D>::~TargetedMovementGenerator()
|
||||
{
|
||||
if (!i_target.isValid() || !i_target->IsInWorld())
|
||||
return;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))
|
||||
return;
|
||||
|
||||
if (owner->IsMovementPreventedByCasting())
|
||||
return;
|
||||
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature()))
|
||||
{
|
||||
owner->ToCreature()->SetCannotReachTarget(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true))
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
|
||||
if (updateDestination || !i_path)
|
||||
{
|
||||
if (!i_offset)
|
||||
{
|
||||
if (i_target->IsWithinDistInMap(owner, CONTACT_DISTANCE))
|
||||
return;
|
||||
|
||||
// to nearest contact position
|
||||
i_target->GetContactPoint(owner, x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
float dist;
|
||||
float size;
|
||||
|
||||
// Pets need special handling.
|
||||
// We need to subtract GetCombatReach() because it gets added back further down the chain
|
||||
// and that makes pets too far away. Subtracting it allows pets to properly
|
||||
// be (GetCombatReach() + i_offset) away.
|
||||
// Only applies when i_target is pet's owner otherwise pets and mobs end up
|
||||
// doing a "dance" while fighting
|
||||
if (owner->IsPet() && i_target->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
dist = 1.0f; //i_target->GetCombatReach();
|
||||
size = 1.0f; //i_target->GetCombatReach() - i_target->GetCombatReach();
|
||||
}
|
||||
else
|
||||
{
|
||||
dist = i_offset + 1.0f;
|
||||
size = owner->GetCombatReach();
|
||||
}
|
||||
|
||||
if (i_target->IsWithinDistInMap(owner, dist))
|
||||
return;
|
||||
|
||||
// to at i_offset distance from target and i_angle from target facing
|
||||
i_target->GetClosePoint(x, y, z, size, i_offset, i_angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the destination has not changed, we just need to refresh the path (usually speed change)
|
||||
G3D::Vector3 end = i_path->GetEndPosition();
|
||||
x = end.x;
|
||||
y = end.y;
|
||||
z = end.z;
|
||||
}
|
||||
|
||||
if (!i_path)
|
||||
i_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 = i_path->CalculatePath(x, y, z, forceDest);
|
||||
if (!result || (i_path->GetPathType() & PATHFIND_NOPATH))
|
||||
{
|
||||
// can't reach target
|
||||
i_recalculateTravel = true;
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
owner->ToCreature()->SetCannotReachTarget(true);
|
||||
return;
|
||||
}
|
||||
|
||||
D::_addUnitStateMove(owner);
|
||||
i_targetReached = false;
|
||||
i_recalculateTravel = false;
|
||||
owner->AddUnitState(UNIT_STATE_CHASE);
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
owner->ToCreature()->SetCannotReachTarget(false);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(i_path->GetPath());
|
||||
init.SetWalk(((D*)this)->EnableWalking());
|
||||
// Using the same condition for facing target as the one that is used for SetInFront on movement end
|
||||
// - applies to ChaseMovementGenerator mostly
|
||||
if (i_angle == 0.f)
|
||||
init.SetFacing(i_target.getTarget());
|
||||
|
||||
init.Launch();
|
||||
delete _path;
|
||||
}
|
||||
|
||||
template<class T, typename D>
|
||||
bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff)
|
||||
bool TargetedMovementGenerator<T, D>::DoUpdate(T* owner, uint32 diff)
|
||||
{
|
||||
if (!i_target.isValid() || !i_target->IsInWorld())
|
||||
if (!IsTargetValid() || !GetTarget()->IsInWorld())
|
||||
return false;
|
||||
|
||||
if (!owner || !owner->IsAlive())
|
||||
return false;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || HasLostTarget(owner)
|
||||
|| (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true)))
|
||||
{
|
||||
D::_clearUnitStateMove(owner);
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
|
||||
// prevent movement while casting spells with cast time or channel time
|
||||
if (owner->IsMovementPreventedByCasting())
|
||||
if (_interrupt || _recalculateTravel)
|
||||
{
|
||||
if (!owner->IsStopped())
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
|
||||
// prevent crash after creature killed pet
|
||||
if (static_cast<D*>(this)->_lostTarget(owner))
|
||||
{
|
||||
D::_clearUnitStateMove(owner);
|
||||
_interrupt = false;
|
||||
SetTargetLocation(owner, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool targetMoved = false;
|
||||
i_recheckDistance.Update(time_diff);
|
||||
if (i_recheckDistance.Passed())
|
||||
_timer.Update(diff);
|
||||
if (!_interrupt && _timer.Passed())
|
||||
{
|
||||
i_recheckDistance.Reset(100);
|
||||
_timer.Reset(100);
|
||||
|
||||
//More distance let have better performance, less distance let have more sensitive reaction at target move.
|
||||
float allowed_dist = 0.0f;
|
||||
float distance = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
|
||||
if (owner->IsPet() && (owner->GetCharmerOrOwnerGUID() == GetTarget()->GetGUID()))
|
||||
distance = 1.f; // pet following owner
|
||||
|
||||
if (owner->IsPet() && (owner->GetCharmerOrOwnerGUID() == i_target->GetGUID()))
|
||||
allowed_dist = 1.0f; // pet following owner
|
||||
else
|
||||
allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE);
|
||||
|
||||
G3D::Vector3 dest = owner->movespline->FinalDestination();
|
||||
G3D::Vector3 destination = owner->movespline->FinalDestination();
|
||||
if (owner->movespline->onTransport)
|
||||
if (TransportBase* transport = owner->GetDirectTransport())
|
||||
transport->CalculatePassengerPosition(dest.x, dest.y, dest.z);
|
||||
transport->CalculatePassengerPosition(destination.x, destination.y, destination.z);
|
||||
|
||||
// First check distance
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && (owner->ToCreature()->CanFly() || owner->ToCreature()->CanSwim()))
|
||||
targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist);
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly())
|
||||
targetMoved = !GetTarget()->IsWithinDist3d(destination.x, destination.y, destination.z, distance);
|
||||
else
|
||||
targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist);
|
||||
targetMoved = !GetTarget()->IsWithinDist2d(destination.x, destination.y, distance);
|
||||
|
||||
// then, if the target is in range, check also Line of Sight.
|
||||
if (!targetMoved)
|
||||
targetMoved = !i_target->IsWithinLOSInMap(owner);
|
||||
targetMoved = !GetTarget()->IsWithinLOSInMap(owner);
|
||||
}
|
||||
|
||||
if (i_recalculateTravel || targetMoved)
|
||||
_setTargetLocation(owner, targetMoved);
|
||||
if (targetMoved)
|
||||
SetTargetLocation(owner, targetMoved);
|
||||
|
||||
if (owner->movespline->Finalized())
|
||||
if (!_targetReached && owner->movespline->Finalized())
|
||||
{
|
||||
static_cast<D*>(this)->MovementInform(owner);
|
||||
if (i_angle == 0.f && !owner->HasInArc(0.01f, i_target.getTarget()))
|
||||
owner->SetInFront(i_target.getTarget());
|
||||
MovementInform(owner);
|
||||
if (_angle == 0.f && !owner->HasInArc(0.01f, GetTarget()))
|
||||
owner->SetInFront(GetTarget());
|
||||
|
||||
if (!i_targetReached)
|
||||
if (!_targetReached)
|
||||
{
|
||||
i_targetReached = true;
|
||||
static_cast<D*>(this)->_reachTarget(owner);
|
||||
_targetReached = true;
|
||||
ReachTarget(owner);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------//
|
||||
template<class T>
|
||||
void ChaseMovementGenerator<T>::_reachTarget(T* owner)
|
||||
template<class T, typename D>
|
||||
void TargetedMovementGenerator<T, D>::SetTargetLocation(T* owner, bool updateDestination)
|
||||
{
|
||||
_clearUnitStateMove(owner);
|
||||
if (owner->IsWithinMeleeRange(this->i_target.getTarget()))
|
||||
owner->Attack(this->i_target.getTarget(), true);
|
||||
if (!IsTargetValid() || !GetTarget()->IsInWorld())
|
||||
return;
|
||||
|
||||
if (!owner || !owner->IsAlive())
|
||||
return;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || HasLostTarget(owner)
|
||||
|| (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true)))
|
||||
{
|
||||
_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()->GetContactPoint(owner, x, y, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
float distance = _offset + 1.0f;
|
||||
float size = owner->GetCombatReach();
|
||||
|
||||
if (owner->IsPet() && GetTarget()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
distance = 1.0f;
|
||||
size = 1.0f;
|
||||
}
|
||||
|
||||
if (GetTarget()->IsWithinDistInMap(owner, distance))
|
||||
return;
|
||||
|
||||
GetTarget()->GetClosePoint(x, y, z, size, _offset, _angle);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
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 | UNIT_STATE_CHASE_MOVE);
|
||||
_setTargetLocation(owner, true);
|
||||
owner->AddUnitState(UNIT_STATE_CHASE);
|
||||
SetTargetLocation(owner, true);
|
||||
}
|
||||
|
||||
template<>
|
||||
void ChaseMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
{
|
||||
owner->SetWalk(false);
|
||||
owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE);
|
||||
_setTargetLocation(owner, true);
|
||||
owner->AddUnitState(UNIT_STATE_CHASE);
|
||||
SetTargetLocation(owner, true);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -250,41 +233,60 @@ void ChaseMovementGenerator<T>::DoReset(T* owner)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ChaseMovementGenerator<T>::MovementInform(T* /*unit*/) { }
|
||||
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<>
|
||||
void ChaseMovementGenerator<Creature>::MovementInform(Creature* unit)
|
||||
void ChaseMovementGenerator<Creature>::MovementInform(Creature* owner)
|
||||
{
|
||||
// Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle
|
||||
if (unit->AI())
|
||||
unit->AI()->MovementInform(CHASE_MOTION_TYPE, i_target.getTarget()->GetGUID().GetCounter());
|
||||
if (owner->AI())
|
||||
owner->AI()->MovementInform(CHASE_MOTION_TYPE, GetTarget()->GetGUID().GetCounter());
|
||||
}
|
||||
|
||||
//-----------------------------------------------//
|
||||
template<>
|
||||
bool FollowMovementGenerator<Creature>::EnableWalking() const
|
||||
{
|
||||
return i_target.isValid() && i_target->IsWalking();
|
||||
}
|
||||
//---- FollowMovementGenerator
|
||||
|
||||
template<class T>
|
||||
void FollowMovementGenerator<T>::UpdateSpeed(T*) { }
|
||||
|
||||
template<>
|
||||
bool FollowMovementGenerator<Player>::EnableWalking() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void FollowMovementGenerator<Player>::UpdateSpeed(Player* /*owner*/) { }
|
||||
|
||||
template<>
|
||||
void FollowMovementGenerator<Player>::_updateSpeed(Player* /*owner*/)
|
||||
void FollowMovementGenerator<Creature>::UpdateSpeed(Creature* owner)
|
||||
{
|
||||
// nothing to do for Player
|
||||
}
|
||||
|
||||
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() || !i_target.isValid() || i_target->GetGUID() != owner->GetOwnerGUID())
|
||||
// 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);
|
||||
@@ -292,27 +294,19 @@ void FollowMovementGenerator<Creature>::_updateSpeed(Creature* owner)
|
||||
owner->UpdateSpeed(MOVE_SWIM);
|
||||
}
|
||||
|
||||
template<>
|
||||
void FollowMovementGenerator<Player>::DoInitialize(Player* owner)
|
||||
template<class T>
|
||||
void FollowMovementGenerator<T>::DoInitialize(T* owner)
|
||||
{
|
||||
owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE);
|
||||
_updateSpeed(owner);
|
||||
_setTargetLocation(owner, true);
|
||||
}
|
||||
|
||||
template<>
|
||||
void FollowMovementGenerator<Creature>::DoInitialize(Creature* owner)
|
||||
{
|
||||
owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE);
|
||||
_updateSpeed(owner);
|
||||
_setTargetLocation(owner, true);
|
||||
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);
|
||||
UpdateSpeed(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -322,36 +316,85 @@ void FollowMovementGenerator<T>::DoReset(T* owner)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void FollowMovementGenerator<T>::MovementInform(T* /*unit*/) { }
|
||||
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<>
|
||||
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, i_target.getTarget()->GetGUID().GetCounter());
|
||||
unit->AI()->MovementInform(FOLLOW_MOTION_TYPE, GetTarget()->GetGUID().GetCounter());
|
||||
}
|
||||
|
||||
//-----------------------------------------------//
|
||||
template void TargetedMovementGeneratorMedium<Player, ChaseMovementGenerator<Player> >::_setTargetLocation(Player*, bool);
|
||||
template void TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::_setTargetLocation(Player*, bool);
|
||||
template void TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool);
|
||||
template void TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool);
|
||||
template bool TargetedMovementGeneratorMedium<Player, ChaseMovementGenerator<Player> >::DoUpdate(Player*, uint32);
|
||||
template bool TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::DoUpdate(Player*, uint32);
|
||||
template bool TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::DoUpdate(Creature*, uint32);
|
||||
template bool TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::DoUpdate(Creature*, uint32);
|
||||
|
||||
template void ChaseMovementGenerator<Player>::_reachTarget(Player*);
|
||||
template void ChaseMovementGenerator<Creature>::_reachTarget(Creature*);
|
||||
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 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*);
|
||||
|
||||
@@ -21,95 +21,93 @@
|
||||
#include "MovementGenerator.h"
|
||||
#include "FollowerReference.h"
|
||||
#include "Timer.h"
|
||||
#include "Unit.h"
|
||||
#include "PathGenerator.h"
|
||||
|
||||
class TargetedMovementGeneratorBase
|
||||
{
|
||||
public:
|
||||
TargetedMovementGeneratorBase(Unit* target) { i_target.link(target, this); }
|
||||
TargetedMovementGeneratorBase(Unit* target)
|
||||
{
|
||||
_target.link(target, this);
|
||||
}
|
||||
|
||||
bool IsTargetValid() const { return _target.isValid(); }
|
||||
Unit* GetTarget() const { return _target.getTarget(); }
|
||||
void stopFollowing() { }
|
||||
protected:
|
||||
FollowerReference i_target;
|
||||
|
||||
private:
|
||||
FollowerReference _target;
|
||||
};
|
||||
|
||||
template<class T, typename D>
|
||||
class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
|
||||
class TargetedMovementGenerator : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
|
||||
{
|
||||
protected:
|
||||
TargetedMovementGeneratorMedium(Unit* target, float offset, float angle) :
|
||||
TargetedMovementGeneratorBase(target), i_path(NULL),
|
||||
i_recheckDistance(0), i_offset(offset), i_angle(angle),
|
||||
i_recalculateTravel(false), i_targetReached(false)
|
||||
{
|
||||
}
|
||||
~TargetedMovementGeneratorMedium() { delete i_path; }
|
||||
|
||||
public:
|
||||
explicit TargetedMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGeneratorBase(target), _path(nullptr), _timer(0), _offset(offset), _angle(angle), _recalculateTravel(false), _targetReached(false), _interrupt(false) { }
|
||||
~TargetedMovementGenerator();
|
||||
|
||||
bool DoUpdate(T*, uint32);
|
||||
Unit* GetTarget() const { return i_target.getTarget(); }
|
||||
|
||||
void unitSpeedChanged() override { i_recalculateTravel = true; }
|
||||
bool IsReachable() const { return (i_path) ? (i_path->GetPathType() & PATHFIND_NORMAL) : true; }
|
||||
protected:
|
||||
void _setTargetLocation(T* owner, bool updateDestination);
|
||||
void UnitSpeedChanged() override { _recalculateTravel = true; }
|
||||
|
||||
PathGenerator* i_path;
|
||||
TimeTrackerSmall i_recheckDistance;
|
||||
float i_offset;
|
||||
float i_angle;
|
||||
bool i_recalculateTravel : 1;
|
||||
bool i_targetReached : 1;
|
||||
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*) { }
|
||||
|
||||
bool IsReachable() const;
|
||||
void SetTargetLocation(T* owner, bool updateDestination);
|
||||
|
||||
private:
|
||||
PathGenerator* _path;
|
||||
TimeTrackerSmall _timer;
|
||||
float _offset;
|
||||
float _angle;
|
||||
bool _recalculateTravel;
|
||||
bool _targetReached;
|
||||
bool _interrupt;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ChaseMovementGenerator : public TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >
|
||||
class ChaseMovementGenerator : public TargetedMovementGenerator<T, ChaseMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
ChaseMovementGenerator(Unit* target)
|
||||
: TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target) { }
|
||||
ChaseMovementGenerator(Unit* target, float offset, float angle)
|
||||
: TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target, offset, angle) { }
|
||||
~ChaseMovementGenerator() { }
|
||||
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 MovementInform(T*);
|
||||
|
||||
static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_CHASE_MOVE); }
|
||||
static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_CHASE_MOVE); }
|
||||
bool EnableWalking() const { return false;}
|
||||
bool _lostTarget(T* u) const { return u->GetVictim() != this->GetTarget(); }
|
||||
void _reachTarget(T*);
|
||||
void ClearUnitStateMove(T*) override;
|
||||
void AddUnitStateMove(T*) override;
|
||||
bool HasLostTarget(T*) const override;
|
||||
void ReachTarget(T*) override;
|
||||
void MovementInform(T*) override;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class FollowMovementGenerator : public TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >
|
||||
class FollowMovementGenerator : public TargetedMovementGenerator<T, FollowMovementGenerator<T> >
|
||||
{
|
||||
public:
|
||||
FollowMovementGenerator(Unit* target)
|
||||
: TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target){ }
|
||||
FollowMovementGenerator(Unit* target, float offset, float angle)
|
||||
: TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target, offset, angle) { }
|
||||
~FollowMovementGenerator() { }
|
||||
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 MovementInform(T*);
|
||||
|
||||
static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); }
|
||||
static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_FOLLOW_MOVE); }
|
||||
bool EnableWalking() const;
|
||||
bool _lostTarget(T*) const { return false; }
|
||||
void _reachTarget(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;
|
||||
private:
|
||||
void _updateSpeed(T* owner);
|
||||
void UpdateSpeed(T* owner);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user