diff options
author | ccrs <ccrs@users.noreply.github.com> | 2017-04-09 14:13:29 +0200 |
---|---|---|
committer | funjoker <funjoker109@gmail.com> | 2020-04-27 12:25:52 +0200 |
commit | 84df2c57a385df4503fc1f8ff5dfdf445ea2e31f (patch) | |
tree | 9184d1703865b5fde64cbdbe3f185a67dda2bc9f | |
parent | c31f875cc8e7870659a1c9bd565d37b334e5dba8 (diff) |
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 46221b6dc1272989e0de85a4563fc49dba8e7851)
9 files changed, 210 insertions, 17 deletions
diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 1643a712f8e..07547ae9139 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -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); } } diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h index 38e86ea4c12..85eb7454432 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.h +++ b/src/server/game/Entities/Creature/CreatureGroups.h @@ -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); }; diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index b124edb22d1..3b446733bbb 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -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() diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 8a3f8e5d0b2..7cb72c353f7 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -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; diff --git a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp new file mode 100644 index 00000000000..a1382ec673e --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp @@ -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); +} diff --git a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h new file mode 100644 index 00000000000..27ab7d50da5 --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h @@ -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 diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index 9c2567ad6a3..ff3a2699128 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -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(); diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 4c4f8945bfd..7b0025d644f 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -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> diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 9f07641d74d..0a01d7f3a96 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -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; } |