mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Movement: FormationMovementGenerator
Use own movement generator for creatures following on a formation.
First step of implementation, huge room for improvement.
Closes #19422
(cherry picked from commit 46221b6dc1)
This commit is contained in:
@@ -224,13 +224,15 @@ void CreatureGroup::FormationReset(bool dismiss)
|
||||
m_Formed = !dismiss;
|
||||
}
|
||||
|
||||
void CreatureGroup::LeaderMoveTo(float x, float y, float z)
|
||||
void CreatureGroup::LeaderMoveTo(Position destination, uint32 id /*= 0*/, uint32 moveType /*= 0*/, bool orientation /*= false*/)
|
||||
{
|
||||
//! 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 (!m_leader)
|
||||
return;
|
||||
|
||||
float x = destination.GetPositionX(), y = destination.GetPositionY(), z = destination.GetPositionZ();
|
||||
|
||||
float pathangle = std::atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
|
||||
|
||||
for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
@@ -256,12 +258,9 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z)
|
||||
if (!member->IsFlying())
|
||||
member->UpdateGroundPositionZ(dx, dy, dz);
|
||||
|
||||
if (member->IsWithinDist(m_leader, dist + MAX_DESYNC))
|
||||
member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags());
|
||||
else
|
||||
member->SetWalk(false);
|
||||
Position point(dx, dy, dz, destination.GetOrientation());
|
||||
|
||||
member->GetMotionMaster()->MovePoint(0, dx, dy, dz);
|
||||
member->GetMotionMaster()->MoveFormation(id, point, moveType, !member->IsWithinDist(m_leader, dist + MAX_DESYNC), orientation);
|
||||
member->SetHomePosition(dx, dy, dz, pathangle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define _FORMATIONS_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "Position.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
@@ -87,7 +88,7 @@ class TC_GAME_API CreatureGroup
|
||||
void RemoveMember(Creature* member);
|
||||
void FormationReset(bool dismiss);
|
||||
|
||||
void LeaderMoveTo(float x, float y, float z);
|
||||
void LeaderMoveTo(Position destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false);
|
||||
void MemberAttackStart(Creature* member, Unit* target);
|
||||
};
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include "RandomMovementGenerator.h"
|
||||
#include "SplineChainMovementGenerator.h"
|
||||
#include "FormationMovementGenerator.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "PathGenerator.h"
|
||||
@@ -711,6 +712,15 @@ void MotionMaster::MoveRotate(uint32 time, RotateDirection direction)
|
||||
Mutate(new RotateMovementGenerator(time, direction), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
|
||||
void MotionMaster::MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun /*= false*/, bool forceOrientation /*= false*/)
|
||||
{
|
||||
if (_owner->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
TC_LOG_DEBUG("misc", "MotionMaster::MoveFormation: Creature (Entry: %u %s) targeted point (Id: %u X: %f Y: %f Z: %f).", _owner->GetEntry(), _owner->GetGUID().ToString().c_str(), id, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
|
||||
Mutate(new FormationMovementGenerator(id, destination, moveType, forceRun, forceOrientation), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/******************** Private methods ********************/
|
||||
|
||||
void MotionMaster::pop()
|
||||
|
||||
@@ -66,6 +66,7 @@ enum MovementGeneratorType : uint8
|
||||
ROTATE_MOTION_TYPE = 15,
|
||||
EFFECT_MOTION_TYPE = 16,
|
||||
SPLINE_CHAIN_MOTION_TYPE = 17, // SplineChainMovementGenerator.h
|
||||
FORMATION_MOTION_TYPE = 18, // FormationMovementGenerator.h
|
||||
MAX_MOTION_TYPE // limit
|
||||
};
|
||||
|
||||
@@ -176,6 +177,8 @@ class TC_GAME_API MotionMaster
|
||||
void MovePath(uint32 path_id, bool repeatable);
|
||||
void MoveRotate(uint32 time, RotateDirection direction);
|
||||
|
||||
void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false);
|
||||
|
||||
private:
|
||||
typedef std::vector<MovementGenerator*> MovementList;
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "FormationMovementGenerator.h"
|
||||
|
||||
void FormationMovementGenerator::DoInitialize(Creature* owner)
|
||||
{
|
||||
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());
|
||||
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();
|
||||
}
|
||||
|
||||
bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 /*diff*/)
|
||||
{
|
||||
if (!owner)
|
||||
return false;
|
||||
|
||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||
{
|
||||
_interrupt = true;
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((_interrupt && owner->movespline->Finalized()) || (_recalculateSpeed && !owner->movespline->Finalized()))
|
||||
{
|
||||
_recalculateSpeed = false;
|
||||
_interrupt = false;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
return !owner->movespline->Finalized();
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::DoFinalize(Creature* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (owner->movespline->Finalized())
|
||||
MovementInform(owner);
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::DoReset(Creature* owner)
|
||||
{
|
||||
owner->StopMoving();
|
||||
DoInitialize(owner);
|
||||
}
|
||||
|
||||
void FormationMovementGenerator::MovementInform(Creature* owner)
|
||||
{
|
||||
if (owner->AI())
|
||||
owner->AI()->MovementInform(FORMATION_MOTION_TYPE, _movementId);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_FORMATIONMOVEMENTGENERATOR_H
|
||||
#define TRINITY_FORMATIONMOVEMENTGENERATOR_H
|
||||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
class FormationMovementGenerator : public MovementGeneratorMedium< Creature, FormationMovementGenerator >
|
||||
{
|
||||
public:
|
||||
explicit FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation) : _movementId(id), _destination(destination), _moveType(moveType), _run(run), _orientation(orientation), _recalculateSpeed(false), _interrupt(false) { }
|
||||
|
||||
MovementGeneratorType GetMovementGeneratorType() const override { return FORMATION_MOTION_TYPE; }
|
||||
|
||||
void DoInitialize(Creature*);
|
||||
void DoFinalize(Creature*);
|
||||
void DoReset(Creature*);
|
||||
bool DoUpdate(Creature*, uint32);
|
||||
|
||||
void UnitSpeedChanged() override { _recalculateSpeed = true; }
|
||||
|
||||
private:
|
||||
void MovementInform(Creature*);
|
||||
|
||||
uint32 _movementId;
|
||||
Position _destination;
|
||||
uint32 _moveType;
|
||||
bool _run;
|
||||
bool _orientation;
|
||||
bool _recalculateSpeed;
|
||||
bool _interrupt;
|
||||
};
|
||||
|
||||
#endif // TRINITY_FORMATIONMOVEMENTGENERATOR_H
|
||||
@@ -60,7 +60,7 @@ void PointMovementGenerator<T>::DoInitialize(T* owner)
|
||||
// Call for creature group update
|
||||
if (Creature* creature = owner->ToCreature())
|
||||
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
|
||||
creature->GetFormation()->LeaderMoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ());
|
||||
creature->GetFormation()->LeaderMoveTo(_destination, _movementId);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -95,7 +95,7 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/)
|
||||
// Call for creature group update
|
||||
if (Creature* creature = owner->ToCreature())
|
||||
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
|
||||
creature->GetFormation()->LeaderMoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ());
|
||||
creature->GetFormation()->LeaderMoveTo(_destination, _movementId);
|
||||
}
|
||||
|
||||
return !owner->movespline->Finalized();
|
||||
|
||||
@@ -116,7 +116,7 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner)
|
||||
|
||||
// Call for creature group update
|
||||
if (owner->GetFormation() && owner->GetFormation()->getLeader() == owner)
|
||||
owner->GetFormation()->LeaderMoveTo(position.m_positionX, position.m_positionY, position.m_positionZ);
|
||||
owner->GetFormation()->LeaderMoveTo(position);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -139,7 +139,7 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
|
||||
|
||||
creature->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
Movement::Location formationDest(node->x, node->y, node->z, 0.0f);
|
||||
Position formationDest(node->x, node->y, node->z, (node->orientation && node->delay) ? node->orientation : 0.0f);
|
||||
Movement::MoveSplineInit init(creature);
|
||||
|
||||
//! If creature is on transport, we assume waypoints set in DB are already transport offsets
|
||||
@@ -147,7 +147,11 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
|
||||
{
|
||||
init.DisableTransportPathTransformations();
|
||||
if (TransportBase* trans = creature->GetDirectTransport())
|
||||
trans->CalculatePassengerPosition(formationDest.x, formationDest.y, formationDest.z, &formationDest.orientation);
|
||||
{
|
||||
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
|
||||
@@ -176,12 +180,9 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
|
||||
|
||||
init.Launch();
|
||||
|
||||
//Call for creature group update
|
||||
// Call for creature group update
|
||||
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
|
||||
{
|
||||
creature->SetWalk(node->move_type != WAYPOINT_MOVE_TYPE_RUN);
|
||||
creature->GetFormation()->LeaderMoveTo(formationDest.x, formationDest.y, formationDest.z);
|
||||
}
|
||||
creature->GetFormation()->LeaderMoveTo(formationDest, node->id, node->move_type, (node->orientation && node->delay) ? true : false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user