mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 15:40:45 +01:00
Core/Movement: Formation Rewrite (#24379)
* Core/Movement: Formation Rewrite * Add a missing include * fixed another warning * meh Co-authored-by: Ovahlord <Ovahlord@users.noreply.github.com> Co-authored-by: Ovah <dreadkiller@gmx.de>
This commit is contained in:
@@ -338,7 +338,7 @@ bool Creature::IsFormationLeader() const
|
||||
return m_formation->IsLeader(this);
|
||||
}
|
||||
|
||||
void Creature::SignalFormationMovement(Position const& destination, uint32 id/* = 0*/, uint32 moveType/* = 0*/, bool orientation/* = false*/)
|
||||
void Creature::SignalFormationMovement()
|
||||
{
|
||||
if (!m_formation)
|
||||
return;
|
||||
@@ -346,7 +346,7 @@ void Creature::SignalFormationMovement(Position const& destination, uint32 id/*
|
||||
if (!m_formation->IsLeader(this))
|
||||
return;
|
||||
|
||||
m_formation->LeaderMoveTo(destination, id, moveType, orientation);
|
||||
m_formation->LeaderStartedMoving();
|
||||
}
|
||||
|
||||
bool Creature::IsFormationLeaderMoveAllowed() const
|
||||
|
||||
@@ -315,7 +315,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
|
||||
CreatureGroup* GetFormation() { return m_formation; }
|
||||
void SetFormation(CreatureGroup* formation) { m_formation = formation; }
|
||||
bool IsFormationLeader() const;
|
||||
void SignalFormationMovement(Position const& destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false);
|
||||
void SignalFormationMovement();
|
||||
bool IsFormationLeaderMoveAllowed() const;
|
||||
|
||||
void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; }
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Log.h"
|
||||
#include "Map.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "MovementGenerator.h"
|
||||
#include "ObjectMgr.h"
|
||||
|
||||
#define MAX_DESYNC 5.0f
|
||||
@@ -275,51 +276,23 @@ void CreatureGroup::FormationReset(bool dismiss)
|
||||
_formed = !dismiss;
|
||||
}
|
||||
|
||||
void CreatureGroup::LeaderMoveTo(Position const& destination, uint32 id /*= 0*/, uint32 moveType /*= 0*/, bool orientation /*= false*/)
|
||||
void CreatureGroup::LeaderStartedMoving()
|
||||
{
|
||||
//! To do: This should probably get its own movement generator or use WaypointMovementGenerator.
|
||||
//! If the leader's path is known, member's path can be plotted as well using formation offsets.
|
||||
if (!_leader)
|
||||
return;
|
||||
|
||||
Position pos(destination);
|
||||
float pathangle = std::atan2(_leader->GetPositionY() - pos.GetPositionY(), _leader->GetPositionX() - pos.GetPositionX());
|
||||
|
||||
for (auto const& pair : _members)
|
||||
{
|
||||
Creature* member = pair.first;
|
||||
if (member == _leader || !member->IsAlive() || member->IsEngaged() || !(pair.second->GroupAI & FLAG_IDLE_IN_FORMATION))
|
||||
continue;
|
||||
|
||||
if (pair.second->LeaderWaypointIDs[0])
|
||||
{
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
{
|
||||
if (_leader->GetCurrentWaypointInfo().first == pair.second->LeaderWaypointIDs[i])
|
||||
{
|
||||
pair.second->FollowAngle = float(M_PI) * 2.f - pair.second->FollowAngle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float angle = pair.second->FollowAngle;
|
||||
float angle = pair.second->FollowAngle + float(M_PI); // for some reason, someone thought it was a great idea to invert relativ angles...
|
||||
float dist = pair.second->FollowDist;
|
||||
|
||||
float dx = pos.GetPositionX() + std::cos(angle + pathangle) * dist;
|
||||
float dy = pos.GetPositionY() + std::sin(angle + pathangle) * dist;
|
||||
float dz = pos.GetPositionZ();
|
||||
|
||||
Trinity::NormalizeMapCoord(dx);
|
||||
Trinity::NormalizeMapCoord(dy);
|
||||
|
||||
if (!member->IsFlying())
|
||||
member->UpdateGroundPositionZ(dx, dy, dz);
|
||||
|
||||
member->SetHomePosition(dx, dy, dz, pathangle);
|
||||
|
||||
Position point(dx, dy, dz, destination.GetOrientation());
|
||||
member->GetMotionMaster()->MoveFormation(id, point, moveType, !member->IsWithinDist(_leader, dist + MAX_DESYNC), orientation);
|
||||
MovementGenerator const* moveGen = member->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* movement)->bool { return movement->GetMovementGeneratorType() == FORMATION_MOTION_TYPE; }, MOTION_SLOT_DEFAULT);
|
||||
if (!moveGen)
|
||||
member->GetMotionMaster()->MoveFormation(_leader, dist, angle, pair.second->LeaderWaypointIDs[0], pair.second->LeaderWaypointIDs[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ class TC_GAME_API CreatureGroup
|
||||
void RemoveMember(Creature* member);
|
||||
void FormationReset(bool dismiss);
|
||||
|
||||
void LeaderMoveTo(Position const& destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false);
|
||||
void LeaderStartedMoving();
|
||||
void MemberEngagingTarget(Creature* member, Unit* target);
|
||||
bool CanLeaderStartMoving() const;
|
||||
};
|
||||
|
||||
@@ -1012,12 +1012,12 @@ void MotionMaster::MoveRotate(uint32 id, uint32 time, RotateDirection direction)
|
||||
Add(new RotateMovementGenerator(id, time, direction));
|
||||
}
|
||||
|
||||
void MotionMaster::MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun /*= false*/, bool forceOrientation /*= false*/)
|
||||
void MotionMaster::MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2)
|
||||
{
|
||||
if (_owner->GetTypeId() == TYPEID_UNIT)
|
||||
if (_owner->GetTypeId() == TYPEID_UNIT && leader)
|
||||
{
|
||||
TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFormation: '%s', targeted point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
|
||||
Add(new FormationMovementGenerator(id, destination, moveType, forceRun, forceOrientation));
|
||||
TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFormation: '%s', started to move in a formation with leader %s", _owner->GetGUID().ToString().c_str(), leader->GetGUID().ToString().c_str());
|
||||
Add(new FormationMovementGenerator(leader, range, angle, point1, point2), MOTION_SLOT_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ class TC_GAME_API MotionMaster
|
||||
void MovePath(uint32 pathId, bool repeatable);
|
||||
void MovePath(WaypointPath& path, bool repeatable);
|
||||
void MoveRotate(uint32 id, uint32 time, RotateDirection direction);
|
||||
void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false);
|
||||
void MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2);
|
||||
|
||||
void LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id = 0, MovementGeneratorPriority priority = MOTION_PRIORITY_NORMAL, MovementGeneratorType type = EFFECT_MOTION_TYPE);
|
||||
private:
|
||||
|
||||
@@ -18,11 +18,14 @@
|
||||
#include "FormationMovementGenerator.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "G3DPosition.hpp"
|
||||
#include "MovementDefines.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "MoveSplineInit.h"
|
||||
|
||||
FormationMovementGenerator::FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation) : _movementId(id), _destination(destination), _moveType(moveType), _run(run), _orientation(orientation)
|
||||
FormationMovementGenerator::FormationMovementGenerator(Unit* leader, float range, float angle, uint32 point1, uint32 point2) : AbstractFollower(ASSERT_NOTNULL(leader)),
|
||||
_range(range), _angle(angle), _point1(point1), _point2(point2), _lastLeaderSplineID(0), _hasPredictedDestination(false)
|
||||
{
|
||||
Mode = MOTION_MODE_DEFAULT;
|
||||
Priority = MOTION_PRIORITY_NORMAL;
|
||||
@@ -47,33 +50,7 @@ void FormationMovementGenerator::DoInitialize(Creature* owner)
|
||||
return;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ());
|
||||
if (_orientation)
|
||||
init.SetFacing(_destination.GetOrientation());
|
||||
|
||||
switch (_moveType)
|
||||
{
|
||||
case 2: // WAYPOINT_MOVE_TYPE_LAND
|
||||
init.SetAnimation(Movement::ToGround);
|
||||
break;
|
||||
case 3: // WAYPOINT_MOVE_TYPE_TAKEOFF
|
||||
init.SetAnimation(Movement::ToFly);
|
||||
break;
|
||||
case 1: // WAYPOINT_MOVE_TYPE_RUN
|
||||
init.SetWalk(false);
|
||||
break;
|
||||
case 0: // WAYPOINT_MOVE_TYPE_WALK
|
||||
init.SetWalk(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_run)
|
||||
init.SetWalk(false);
|
||||
|
||||
init.Launch();
|
||||
_nextMoveTimer.Reset(0);
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::DoReset(Creature* owner)
|
||||
@@ -83,59 +60,154 @@ void FormationMovementGenerator::DoReset(Creature* owner)
|
||||
DoInitialize(owner);
|
||||
}
|
||||
|
||||
bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 /*diff*/)
|
||||
bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 diff)
|
||||
{
|
||||
if (!owner)
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (!owner || !target)
|
||||
return false;
|
||||
|
||||
// Owner cannot move. Reset all fields and wait for next action
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED);
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED) && owner->movespline->Finalized()) || (HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized()))
|
||||
// Leader has stopped moving, so do we as well
|
||||
if (target->movespline->Finalized() && target->movespline->GetId() == _lastLeaderSplineID && _hasPredictedDestination)
|
||||
{
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED | MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING);
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
owner->StopMoving();
|
||||
_nextMoveTimer.Reset(0);
|
||||
_hasPredictedDestination = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
// Update home position
|
||||
owner->SetHomePosition(owner->GetPosition());
|
||||
if (HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED))
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ());
|
||||
if (_orientation)
|
||||
init.SetFacing(_destination.GetOrientation());
|
||||
// Leader has stopped moving, so do we as well
|
||||
if (owner->HasUnitState(UNIT_STATE_ROAMING_MOVE) && _hasPredictedDestination && target->movespline->Finalized() && target->movespline->GetId() == _lastLeaderSplineID)
|
||||
{
|
||||
owner->StopMoving();
|
||||
_nextMoveTimer.Reset(0);
|
||||
_hasPredictedDestination = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (_moveType)
|
||||
// Formation leader has launched a new spline, launch a new one for our member as well
|
||||
// This action does not reset the regular movement launch cycle interval
|
||||
if (!target->movespline->Finalized() && target->movespline->GetId() != _lastLeaderSplineID)
|
||||
{
|
||||
// Update formation angle
|
||||
if (_point1 && target->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
case 2: // WAYPOINT_MOVE_TYPE_LAND
|
||||
init.SetAnimation(Movement::ToGround);
|
||||
break;
|
||||
case 3: // WAYPOINT_MOVE_TYPE_TAKEOFF
|
||||
init.SetAnimation(Movement::ToFly);
|
||||
break;
|
||||
case 1: // WAYPOINT_MOVE_TYPE_RUN
|
||||
init.SetWalk(false);
|
||||
break;
|
||||
case 0: // WAYPOINT_MOVE_TYPE_WALK
|
||||
init.SetWalk(true);
|
||||
break;
|
||||
if (CreatureGroup* formation = target->ToCreature()->GetFormation())
|
||||
{
|
||||
if (Creature* leader = formation->GetLeader())
|
||||
{
|
||||
uint8 currentWaypoint = leader->GetCurrentWaypointInfo().first;
|
||||
if (currentWaypoint == _point1 || currentWaypoint == _point2)
|
||||
_angle = float(M_PI) * 2 - _angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_run)
|
||||
init.SetWalk(false);
|
||||
init.Launch();
|
||||
LaunchMovement(owner, target);
|
||||
_lastLeaderSplineID = target->movespline->GetId();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (owner->movespline->Finalized())
|
||||
_nextMoveTimer.Update(diff);
|
||||
if (_nextMoveTimer.Passed())
|
||||
{
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY);
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED);
|
||||
return false;
|
||||
_nextMoveTimer.Reset(FORMATION_MOVEMENT_INTERVAL);
|
||||
|
||||
// Our leader has a different position than on our last check, launch movement.
|
||||
if (_lastLeaderPosition != target->GetPosition())
|
||||
{
|
||||
LaunchMovement(owner, target);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We have reached our destination before launching a new movement. Alling facing with leader
|
||||
if (owner->HasUnitState(UNIT_STATE_ROAMING_MOVE) && owner->movespline->Finalized())
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
owner->SetFacingTo(target->GetOrientation());
|
||||
MovementInform(owner);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::LaunchMovement(Creature* owner, Unit* target)
|
||||
{
|
||||
float relativeAngle = 0.f;
|
||||
|
||||
// Determine our relative angle to our current spline destination point
|
||||
if (!target->movespline->Finalized())
|
||||
relativeAngle = target->GetRelativeAngle(Vector3ToPosition(target->movespline->CurrentDestination()));
|
||||
|
||||
// Destination calculation
|
||||
/*
|
||||
According to sniff data, formation members have a periodic move interal of 1,2s.
|
||||
Each of these splines has a exact duration of 1650ms +- 1ms when no pathfinding is involved.
|
||||
To get a representative result like that we have to predict our formation leader's path
|
||||
and apply our formation shape based on that destination.
|
||||
*/
|
||||
Position dest = target->GetPosition();
|
||||
float velocity = 0.f;
|
||||
|
||||
// Formation leader is moving. Predict our destination
|
||||
if (!target->movespline->Finalized())
|
||||
{
|
||||
// Pick up leader's spline velocity
|
||||
velocity = target->movespline->Velocity();
|
||||
|
||||
// Calculate travel distance to get a 1650ms result
|
||||
float travelDist = velocity * 1.65f;
|
||||
|
||||
// Move destination ahead...
|
||||
target->MovePositionToFirstCollision(dest, travelDist, relativeAngle);
|
||||
// ... and apply formation shape
|
||||
target->MovePositionToFirstCollision(dest, _range, _angle + relativeAngle);
|
||||
|
||||
float distance = owner->GetExactDist(dest);
|
||||
|
||||
// Calculate catchup speed mod (Limit to a maximum of 50% of our original velocity
|
||||
float velocityMod = std::min<float>(distance / travelDist, 1.5f);
|
||||
|
||||
// Now we will always stay synch with our leader
|
||||
velocity *= velocityMod;
|
||||
_hasPredictedDestination = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Formation leader is not moving. Just apply the base formation shape on his position.
|
||||
target->MovePositionToFirstCollision(dest, _range, _angle + relativeAngle);
|
||||
_hasPredictedDestination = false;
|
||||
}
|
||||
|
||||
// Leader is not moving, so just pick up his default walk speed
|
||||
if (velocity == 0.f)
|
||||
velocity = target->GetSpeed(MOVE_WALK);
|
||||
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MoveTo(PositionToVector3(dest));
|
||||
init.SetVelocity(velocity);
|
||||
init.Launch();
|
||||
|
||||
_lastLeaderPosition = target->GetPosition();
|
||||
owner->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::DoDeactivate(Creature* owner)
|
||||
{
|
||||
AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED);
|
||||
@@ -155,5 +227,5 @@ void FormationMovementGenerator::DoFinalize(Creature* owner, bool active, bool m
|
||||
void FormationMovementGenerator::MovementInform(Creature* owner)
|
||||
{
|
||||
if (owner->AI())
|
||||
owner->AI()->MovementInform(FORMATION_MOTION_TYPE, _movementId);
|
||||
owner->AI()->MovementInform(FORMATION_MOTION_TYPE, 0);
|
||||
}
|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
#ifndef TRINITY_FORMATIONMOVEMENTGENERATOR_H
|
||||
#define TRINITY_FORMATIONMOVEMENTGENERATOR_H
|
||||
|
||||
#include "AbstractFollower.h"
|
||||
#include "MovementGenerator.h"
|
||||
#include "Position.h"
|
||||
#include "Timer.h"
|
||||
|
||||
class Creature;
|
||||
|
||||
class FormationMovementGenerator : public MovementGeneratorMedium<Creature, FormationMovementGenerator>
|
||||
class FormationMovementGenerator : public MovementGeneratorMedium<Creature, FormationMovementGenerator>, public AbstractFollower
|
||||
{
|
||||
public:
|
||||
explicit FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation);
|
||||
explicit FormationMovementGenerator(Unit* leader, float range, float angle, uint32 point1, uint32 point2);
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override;
|
||||
|
||||
@@ -36,16 +38,21 @@ class FormationMovementGenerator : public MovementGeneratorMedium<Creature, Form
|
||||
void DoDeactivate(Creature*);
|
||||
void DoFinalize(Creature*, bool, bool);
|
||||
|
||||
void UnitSpeedChanged() override { AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); }
|
||||
|
||||
private:
|
||||
void MovementInform(Creature*);
|
||||
|
||||
uint32 _movementId;
|
||||
Position _destination;
|
||||
uint32 _moveType;
|
||||
bool _run;
|
||||
bool _orientation;
|
||||
void LaunchMovement(Creature* owner, Unit* target);
|
||||
|
||||
static constexpr uint32 FORMATION_MOVEMENT_INTERVAL = 1200; // sniffed (3 batch update cycles)
|
||||
float const _range;
|
||||
float _angle;
|
||||
uint32 const _point1;
|
||||
uint32 const _point2;
|
||||
uint32 _lastLeaderSplineID;
|
||||
bool _hasPredictedDestination;
|
||||
|
||||
Position _lastLeaderPosition;
|
||||
TimeTrackerSmall _nextMoveTimer;
|
||||
};
|
||||
|
||||
#endif // TRINITY_FORMATIONMOVEMENTGENERATOR_H
|
||||
|
||||
@@ -75,7 +75,7 @@ void PointMovementGenerator<T>::DoInitialize(T* owner)
|
||||
|
||||
// Call for creature group update
|
||||
if (Creature* creature = owner->ToCreature())
|
||||
creature->SignalFormationMovement(Position(_x, _y, _z), _movementId);
|
||||
creature->SignalFormationMovement();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -123,7 +123,7 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/)
|
||||
|
||||
// Call for creature group update
|
||||
if (Creature* creature = owner->ToCreature())
|
||||
creature->SignalFormationMovement(Position(_x, _y, _z), _movementId);
|
||||
creature->SignalFormationMovement();
|
||||
}
|
||||
|
||||
if (owner->movespline->Finalized())
|
||||
|
||||
@@ -182,7 +182,7 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner)
|
||||
}
|
||||
|
||||
// Call for creature group update
|
||||
owner->SignalFormationMovement(position);
|
||||
owner->SignalFormationMovement();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -333,7 +333,6 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
|
||||
|
||||
ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id);
|
||||
WaypointNode const &waypoint = _path->nodes[_currentNode];
|
||||
Position formationDest(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation && waypoint.delay) ? waypoint.orientation : 0.0f);
|
||||
|
||||
RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_INFORM_ENABLED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED);
|
||||
|
||||
@@ -343,15 +342,7 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
|
||||
|
||||
//! If creature is on transport, we assume waypoints set in DB are already transport offsets
|
||||
if (transportPath)
|
||||
{
|
||||
init.DisableTransportPathTransformations();
|
||||
if (TransportBase* trans = owner->GetDirectTransport())
|
||||
{
|
||||
float orientation = formationDest.GetOrientation();
|
||||
trans->CalculatePassengerPosition(formationDest.m_positionX, formationDest.m_positionY, formationDest.m_positionZ, &orientation);
|
||||
formationDest.SetOrientation(orientation);
|
||||
}
|
||||
}
|
||||
|
||||
//! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call
|
||||
//! but formationDest contains global coordinates
|
||||
@@ -382,7 +373,7 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
|
||||
init.Launch();
|
||||
|
||||
// inform formation
|
||||
owner->SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation && waypoint.delay) ? true : false);
|
||||
owner->SignalFormationMovement();
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::ComputeNextNode()
|
||||
|
||||
@@ -162,6 +162,8 @@ void MoveSpline::Initialize(MoveSplineInitArgs const& args)
|
||||
vertical_acceleration = 0.f;
|
||||
effect_start_time = 0;
|
||||
|
||||
velocity = args.velocity;
|
||||
|
||||
// Check if its a stop spline
|
||||
if (args.flags.done)
|
||||
{
|
||||
@@ -185,7 +187,7 @@ void MoveSpline::Initialize(MoveSplineInitArgs const& args)
|
||||
}
|
||||
|
||||
MoveSpline::MoveSpline() : m_Id(0), time_passed(0),
|
||||
vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0),
|
||||
vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), velocity(0.f),
|
||||
onTransport(false)
|
||||
{
|
||||
splineflags.done = true;
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace Movement
|
||||
int32 effect_start_time;
|
||||
int32 point_Idx;
|
||||
int32 point_Idx_offset;
|
||||
float velocity;
|
||||
|
||||
void init_spline(MoveSplineInitArgs const& args);
|
||||
|
||||
@@ -86,6 +87,7 @@ namespace Movement
|
||||
int32 Duration() const { return spline.length(); }
|
||||
MySpline const& _Spline() const { return spline; }
|
||||
int32 _currentSplineIdx() const { return point_Idx; }
|
||||
float Velocity() const { return velocity; }
|
||||
void _Finalize();
|
||||
void _Interrupt() { splineflags.done = true; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user