diff --git a/Source/Framework/Constants/Movement/MovementConst.cs b/Source/Framework/Constants/Movement/MovementConst.cs index 146d95812..c03d06349 100644 --- a/Source/Framework/Constants/Movement/MovementConst.cs +++ b/Source/Framework/Constants/Movement/MovementConst.cs @@ -27,25 +27,26 @@ namespace Framework.Constants public enum MovementGeneratorType { - Idle = 0, // IdleMovement - Random = 1, // RandomMovement - Waypoint = 2, // WaypointMovement + Idle = 0, // IdleMovement + Random = 1, // RandomMovement + Waypoint = 2, // WaypointMovement - MaxDB = 3, // *** this and below motion types can't be set in DB. - Confused = 4, // ConfusedMovementGenerator - Chase = 5, // TargetedMovementGenerator - Home = 6, // HomeMovementGenerator - Flight = 7, // WaypointMovementGenerator - Point = 8, // PointMovementGenerator - Fleeing = 9, // FleeingMovementGenerator - Distract = 10, // IdleMovementGenerator - Assistance = 11, // PointMovementGenerator - AssistanceDistract = 12, // IdleMovementGenerator - TimedFleeing = 13, // FleeingMovementGenerator + MaxDB = 3, // *** this and below motion types can't be set in DB. + Confused = 4, // ConfusedMovementGenerator + Chase = 5, // TargetedMovementGenerator + Home = 6, // HomeMovementGenerator + Flight = 7, // WaypointMovementGenerator + Point = 8, // PointMovementGenerator + Fleeing = 9, // FleeingMovementGenerator + Distract = 10, // IdleMovementGenerator + Assistance = 11, // PointMovementGenerator + AssistanceDistract = 12, // IdleMovementGenerator + TimedFleeing = 13, // FleeingMovementGenerator Follow = 14, Rotate = 15, Effect = 16, - SplineChain = 17, + SplineChain = 17, // SplineChainMovementGenerator + Formation = 18, // FormationMovementGenerator Max } diff --git a/Source/Game/Entities/Creature/CreatureGroups.cs b/Source/Game/Entities/Creature/CreatureGroups.cs index 96b2faae1..5758c8252 100644 --- a/Source/Game/Entities/Creature/CreatureGroups.cs +++ b/Source/Game/Entities/Creature/CreatureGroups.cs @@ -222,13 +222,16 @@ namespace Game.Entities m_Formed = !dismiss; } - public void LeaderMoveTo(float x, float y, float z) + public void LeaderMoveTo(Position destination, uint id = 0, uint 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(); + float y = destination.GetPositionY(); + float z = destination.GetPositionZ(); float pathangle = (float)Math.Atan2(m_leader.GetPositionY() - y, m_leader.GetPositionX() - x); foreach (var pair in m_members) @@ -254,12 +257,9 @@ namespace Game.Entities if (!member.IsFlying()) member.UpdateGroundPositionZ(dx, dy, ref dz); - if (member.IsWithinDist(m_leader, dist + 5.0f)) - member.SetUnitMovementFlags(m_leader.GetUnitMovementFlags()); - else - member.SetWalk(false); + Position point = new Position(dx, dy, dz, destination.GetOrientation()); - member.GetMotionMaster().MovePoint(0, dx, dy, dz); + member.GetMotionMaster().MoveFormation(id, point, moveType, !member.IsWithinDist(m_leader, dist + 5.0f), orientation); member.SetHomePosition(dx, dy, dz, pathangle); } } diff --git a/Source/Game/Movement/Generators/FormationMovement.cs b/Source/Game/Movement/Generators/FormationMovement.cs new file mode 100644 index 000000000..1fc6add10 --- /dev/null +++ b/Source/Game/Movement/Generators/FormationMovement.cs @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2012-2020 CypherCore + * + * 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 3 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 . + */ + +using Framework.Constants; +using Game.Entities; + +namespace Game.Movement +{ + public class FormationMovementGenerator : MovementGeneratorMedium + { + public FormationMovementGenerator(uint id, Position destination, uint moveType, bool run, bool orientation) + { + _movementId = id; + _destination = destination; + _moveType = moveType; + _run = run; + _orientation = orientation; + } + + public override void DoInitialize(Creature owner) + { + owner.AddUnitState(UnitState.Roaming); + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + { + _interrupt = true; + owner.StopMoving(); + return; + } + + owner.AddUnitState(UnitState.RoamingMove); + + MoveSplineInit init = new MoveSplineInit(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(AnimType.ToGround); + break; + case 3: // WAYPOINT_MOVE_TYPE_TAKEOFF + init.SetAnimation(AnimType.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(); + } + + public override void DoReset(Creature owner) + { + owner.StopMoving(); + DoInitialize(owner); + } + + public override bool DoUpdate(Creature owner, uint diff) + { + if (!owner) + return false; + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + { + _interrupt = true; + owner.StopMoving(); + return true; + } + + if ((_interrupt && owner.MoveSpline.Finalized()) || (_recalculateSpeed && !owner.MoveSpline.Finalized())) + { + _recalculateSpeed = false; + _interrupt = false; + + owner.AddUnitState(UnitState.RoamingMove); + + MoveSplineInit init = new MoveSplineInit(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(AnimType.ToGround); + break; + case 3: // WAYPOINT_MOVE_TYPE_TAKEOFF + init.SetAnimation(AnimType.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(); + } + + public override void DoFinalize(Creature owner) + { + owner.ClearUnitState(UnitState.Roaming | UnitState.RoamingMove); + + if (owner.MoveSpline.Finalized()) + MovementInform(owner); + } + + public override void UnitSpeedChanged() + { + _recalculateSpeed = true; + } + + public override MovementGeneratorType GetMovementGeneratorType() + { + return MovementGeneratorType.Formation; + } + + void MovementInform(Creature owner) + { + if (owner.GetAI() != null) + owner.GetAI().MovementInform(MovementGeneratorType.Formation, _movementId); + } + + uint _movementId; + Position _destination; + uint _moveType; + bool _run; + bool _orientation; + bool _recalculateSpeed; + bool _interrupt; + } +} diff --git a/Source/Game/Movement/Generators/PointMovement.cs b/Source/Game/Movement/Generators/PointMovement.cs index 1d0412137..19f74e8b6 100644 --- a/Source/Game/Movement/Generators/PointMovement.cs +++ b/Source/Game/Movement/Generators/PointMovement.cs @@ -69,7 +69,7 @@ namespace Game.Movement Creature creature = owner.ToCreature(); if (creature != null) if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) - creature.GetFormation().LeaderMoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ()); + creature.GetFormation().LeaderMoveTo(_destination, _movementId); } public override void DoReset(T owner) @@ -110,7 +110,7 @@ namespace Game.Movement Creature creature = owner.ToCreature(); if (creature != null) if (creature.GetFormation() != null && 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/Source/Game/Movement/Generators/RandomMovement.cs b/Source/Game/Movement/Generators/RandomMovement.cs index bfc89261c..7f4e88a99 100644 --- a/Source/Game/Movement/Generators/RandomMovement.cs +++ b/Source/Game/Movement/Generators/RandomMovement.cs @@ -118,7 +118,7 @@ namespace Game.Movement // Call for creature group update if (owner.GetFormation() != null && owner.GetFormation().GetLeader() == owner) - owner.GetFormation().LeaderMoveTo(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); + owner.GetFormation().LeaderMoveTo(position); } public override MovementGeneratorType GetMovementGeneratorType() diff --git a/Source/Game/Movement/Generators/WaypointMovement.cs b/Source/Game/Movement/Generators/WaypointMovement.cs index 4ad657fd0..7816d6cfa 100644 --- a/Source/Game/Movement/Generators/WaypointMovement.cs +++ b/Source/Game/Movement/Generators/WaypointMovement.cs @@ -187,7 +187,7 @@ namespace Game.Movement creature.AddUnitState(UnitState.RoamingMove); - Position formationDest = new Position(node.x, node.y, node.z, 0.0f); + Position formationDest = new Position(node.x, node.y, node.z, (node.orientation != 0 && node.delay != 0) ? node.orientation : 0.0f); MoveSplineInit init = new MoveSplineInit(creature); //! If creature is on transport, we assume waypoints set in DB are already transport offsets @@ -196,7 +196,11 @@ namespace Game.Movement init.DisableTransportPathTransformations(); ITransport trans = creature.GetDirectTransport(); if (trans != null) - trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref formationDest.Orientation); + { + float orientation = formationDest.GetOrientation(); + trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref orientation); + formationDest.SetOrientation(orientation); + } } //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call @@ -227,10 +231,7 @@ namespace Game.Movement //Call for creature group update if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) - { - creature.SetWalk(node.moveType != WaypointMoveType.Run); - creature.GetFormation().LeaderMoveTo(formationDest.posX, formationDest.posY, formationDest.posZ); - } + creature.GetFormation().LeaderMoveTo(formationDest, node.id, (uint)node.moveType, (node.orientation != 0 && node.delay != 0) ? true : false); return true; } diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index d91c98a77..2cb479c63 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -607,6 +607,12 @@ namespace Game.Movement StartMovement(new RotateMovementGenerator(time, direction), MovementSlot.Active); } + public void MoveFormation(uint id, Position destination, uint moveType, bool forceRun = false, bool forceOrientation = false) + { + if (_owner.GetTypeId() == TypeId.Unit) + StartMovement(new FormationMovementGenerator(id, destination, moveType, forceRun, forceOrientation), MovementSlot.Active); + } + void Pop() { if (Empty())