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 bool DoUpdate(T owner, uint diff) { if (owner == null) { return(false); } if (_movementId == EventId.ChargePrepath) { return(!owner.MoveSpline.Finalized()); } 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(), _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 Creature creature = owner.ToCreature(); if (creature != null) { if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) { creature.GetFormation().LeaderMoveTo(_destination, _movementId); } } } return(!owner.MoveSpline.Finalized()); }
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 WaypointMoveType.Land: init.SetAnimation(AnimType.ToGround); break; case WaypointMoveType.Takeoff: init.SetAnimation(AnimType.ToFly); break; case WaypointMoveType.Run: init.SetWalk(false); break; case WaypointMoveType.Walk: init.SetWalk(true); break; } if (_run) { init.SetWalk(false); } init.Launch(); }
public override void DoInitialize(T owner) { if (_movementId == EventId.ChargePrepath) { owner.AddUnitState(UnitState.Roaming | UnitState.RoamingMove); return; } 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(), _generatePath); if (_speed > 0.0f) { init.SetVelocity(_speed); } if (_faceTarget) { init.SetFacing(_faceTarget); } if (_spellEffectExtra != null) { init.SetSpellEffectExtraData(_spellEffectExtra); } init.Launch(); // Call for creature group update Creature creature = owner.ToCreature(); if (creature != null) { creature.SignalFormationMovement(_destination, _movementId); } }
public override void DoInitialize(T owner) { if (!owner.IsStopped()) { owner.StopMoving(); } owner.AddUnitState(UnitState.Roaming | UnitState.RoamingMove); if (id == EventId.ChargePrepath) { return; } MoveSplineInit init = new MoveSplineInit(owner); init.MoveTo(i_x, i_y, i_z, m_generatePath); if (speed > 0.0f) { init.SetVelocity(speed); } if (i_faceTarget) { init.SetFacing(i_faceTarget); } if (i_spellEffectExtra != null) { init.SetSpellEffectExtraData(i_spellEffectExtra); } init.Launch(); // Call for creature group update Creature creature = owner.ToCreature(); if (creature != null) { if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) { creature.GetFormation().LeaderMoveTo(i_x, i_y, i_z); } } }
uint SendPathSpline(Unit me, Span <Vector3> wp) { int numWp = wp.Length; Cypher.Assert(numWp > 1, "Every path must have source & destination"); MoveSplineInit init = new MoveSplineInit(me); if (numWp > 2) { init.MovebyPath(wp.ToArray()); } else { init.MoveTo(wp[1], false, true); } init.SetWalk(_walk); return((uint)init.Launch()); }
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, byte stepCount) { float step = 2 * MathFunctions.PI / stepCount * (clockwise ? -1.0f : 1.0f); Position pos = new Position(x, y, z, 0.0f); float angle = pos.GetAngle(_owner.GetPositionX(), _owner.GetPositionY()); MoveSplineInit init = new MoveSplineInit(_owner); init.args.path = new Vector3[stepCount]; for (byte i = 0; i < stepCount; angle += step, ++i) { Vector3 point = new Vector3(); point.X = (float)(x + radius * Math.Cos(angle)); point.Y = (float)(y + radius * Math.Sin(angle)); if (_owner.IsFlying()) { point.Z = z; } else { point.Z = _owner.GetMap().GetHeight(_owner.GetPhaseShift(), point.X, point.Y, z); } init.args.path[i] = point; } if (_owner.IsFlying()) { init.SetFly(); init.SetCyclic(); init.SetAnimation(AnimType.ToFly); } else { init.SetWalk(true); init.SetCyclic(); } init.Launch(); }
public void MoveCharge(PathGenerator path, float speed = SPEED_CHARGE, Unit target = null, SpellEffectExtraData spellEffectExtraData = null) { Vector3 dest = path.GetActualEndPosition(); MoveCharge(dest.X, dest.Y, dest.Z, SPEED_CHARGE, EventId.ChargePrepath); // Charge movement is not started when using EVENT_CHARGE_PREPATH MoveSplineInit init = new MoveSplineInit(_owner); init.MovebyPath(path.GetPath()); init.SetVelocity(speed); if (target != null) { init.SetFacing(target); } if (spellEffectExtraData != null) { init.SetSpellEffectExtraData(spellEffectExtraData); } init.Launch(); }
void MoveCloserAndStop(uint id, Unit target, float distance) { float distanceToTravel = _owner.GetExactDist2d(target) - distance; if (distanceToTravel > 0.0f) { float angle = _owner.GetAngle(target); float destx = _owner.GetPositionX() + distanceToTravel * (float)Math.Cos(angle); float desty = _owner.GetPositionY() + distanceToTravel * (float)Math.Sin(angle); MovePoint(id, destx, desty, target.GetPositionZ()); } else { // we are already close enough. We just need to turn toward the target without changing position. MoveSplineInit init = new MoveSplineInit(_owner); init.MoveTo(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZMinusOffset()); init.SetFacing(target); init.Launch(); StartMovement(new EffectMovementGenerator(id), MovementSlot.Active); } }
void MoveSmoothPath(uint pointId, Vector3[] pathPoints, int pathSize, bool walk = false, bool fly = false) { MoveSplineInit init = new MoveSplineInit(_owner); if (fly) { init.SetFly(); init.SetUncompressed(); init.SetSmooth(); } init.MovebyPath(pathPoints); init.SetWalk(walk); init.Launch(); // This code is not correct // EffectMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE // need to call PointMovementGenerator with various pointIds StartMovement(new EffectMovementGenerator(pointId), MovementSlot.Active); //Position pos(pathPoints[pathSize - 1].x, pathPoints[pathSize - 1].y, pathPoints[pathSize - 1].z); //MovePoint(EVENT_CHARGE_PREPATH, pos, false); }
public override bool DoUpdate(T owner, uint time_diff) { if (owner == null) { return(false); } if (owner.HasUnitState(UnitState.Root | UnitState.Stunned)) { owner.ClearUnitState(UnitState.RoamingMove); return(true); } owner.AddUnitState(UnitState.RoamingMove); if (id != EventId.ChargePrepath && i_recalculateSpeed && !owner.MoveSpline.Finalized()) { i_recalculateSpeed = false; MoveSplineInit init = new MoveSplineInit(owner); 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); } init.Launch(); // Call for creature group update Creature creature = owner.ToCreature(); if (creature != null) { if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) { creature.GetFormation().LeaderMoveTo(i_x, i_y, i_z); } } } return(!owner.MoveSpline.Finalized()); }
public override void DoReset(Player owner) { owner.getHostileRefManager().setOnlineOfflineState(false); owner.AddUnitState(UnitState.InFlight); owner.AddUnitFlag(UnitFlags.RemoveClientControl | UnitFlags.TaxiFlight); MoveSplineInit init = new MoveSplineInit(owner); uint end = GetPathAtMapEnd(); init.args.path = new Vector3[end]; for (int i = (int)GetCurrentNode(); i != end; ++i) { Vector3 vertice = new Vector3(i_path[i].Loc.X, i_path[i].Loc.Y, i_path[i].Loc.Z); init.args.path[i] = vertice; } init.SetFirstPointId((int)GetCurrentNode()); init.SetFly(); init.SetSmooth(); init.SetUncompressed(); init.SetWalk(true); init.SetVelocity(30.0f); init.Launch(); }
public void MoveJump(float x, float y, float z, float o, float speedXY, float speedZ, uint id = EventId.Jump, bool hasOrientation = false, JumpArrivalCastArgs arrivalCast = null, SpellEffectExtraData spellEffectExtraData = null) { Log.outDebug(LogFilter.Server, "Unit ({0}) jump to point (X: {1} Y: {2} Z: {3})", _owner.GetGUID().ToString(), x, y, z); if (speedXY < 0.01f) { return; } float moveTimeHalf = (float)(speedZ / gravity); float max_height = -MoveSpline.ComputeFallElevation(moveTimeHalf, false, -speedZ); MoveSplineInit init = new MoveSplineInit(_owner); init.MoveTo(x, y, z, false); init.SetParabolic(max_height, 0); init.SetVelocity(speedXY); if (hasOrientation) { init.SetFacing(o); } if (spellEffectExtraData != null) { init.SetSpellEffectExtraData(spellEffectExtraData); } init.Launch(); uint arrivalSpellId = 0; ObjectGuid arrivalSpellTargetGuid = ObjectGuid.Empty; if (arrivalCast != null) { arrivalSpellId = arrivalCast.SpellId; arrivalSpellTargetGuid = arrivalCast.Target; } StartMovement(new EffectMovementGenerator(id, arrivalSpellId, arrivalSpellTargetGuid), MovementSlot.Controlled); }
public void SetTargetLocation(T owner, bool updateDestination) { if (!IsTargetValid() || !GetTarget().IsInWorld) { return; } if (!owner || !owner.IsAlive()) { return; } if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting() || HasLostTarget(owner)) { _interrupt = true; owner.StopMoving(); return; } if (owner.IsTypeId(TypeId.Unit) && !GetTarget().IsInAccessiblePlaceFor(owner.ToCreature())) { owner.ToCreature().SetCannotReachTarget(true); return; } float x, y, z; if (updateDestination || _path == null) { if (_offset == 0) { if (GetTarget().IsWithinDistInMap(owner, SharedConst.ContactDistance)) { return; } // to nearest contact position GetTarget().GetContactPoint(owner, out x, out y, out 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(out x, out y, out z, size, _offset, _angle); } } else { // the destination has not changed, we just need to refresh the path (usually speed change) var end = _path.GetEndPosition(); x = end.X; y = end.Y; z = end.Z; } if (_path == null) { _path = new PathGenerator(owner); } // allow pets to use shortcut if no path found when following their master bool forceDest = owner.IsTypeId(TypeId.Unit) && owner.IsPet() && owner.HasUnitState(UnitState.Follow); bool result = _path.CalculatePath(x, y, z, forceDest); if (!result && Convert.ToBoolean(_path.GetPathType() & PathType.NoPath)) { // Can't reach target _recalculateTravel = true; if (owner.IsTypeId(TypeId.Unit)) { owner.ToCreature().SetCannotReachTarget(true); } return; } _targetReached = false; _recalculateTravel = false; _speedChanged = false; AddUnitStateMove(owner); if (owner.IsTypeId(TypeId.Unit)) { owner.ToCreature().SetCannotReachTarget(false); } MoveSplineInit init = new MoveSplineInit(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.0f) { init.SetFacing(GetTarget()); } init.Launch(); }
public void _setRandomLocation(Creature creature) { if (creature.IsMovementPreventedByCasting()) { creature.CastStop(); return; } float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ; creature.GetHomePosition(out respX, out respY, out respZ, out respO); Map map = creature.GetMap(); bool is_air_ok = creature.CanFly(); float angle = (float)(RandomHelper.NextDouble() * MathFunctions.TwoPi); float range = (float)(RandomHelper.NextDouble() * wander_distance); float distanceX = (float)(range * Math.Cos(angle)); float distanceY = (float)(range * Math.Sin(angle)); destX = respX + distanceX; destY = respY + distanceY; // prevent invalid coordinates generation GridDefines.NormalizeMapCoord(ref destX); GridDefines.NormalizeMapCoord(ref 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) { // Limit height change float distanceZ = (float)(RandomHelper.NextDouble() * travelDistZ / 2.0f); destZ = respZ + distanceZ; float levelZ = map.GetWaterOrGroundLevel(creature.GetPhases(), 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 // 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.GetPhases(), destX, destY, respZ + travelDistZ - 2.0f, false); if (Math.Abs(destZ - respZ) > travelDistZ) // Map check { // Vmap Horizontal or above destZ = map.GetHeight(creature.GetPhases(), destX, destY, respZ - 2.0f, true); if (Math.Abs(destZ - respZ) > travelDistZ) { // Vmap Higher destZ = map.GetHeight(creature.GetPhases(), 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 (Math.Abs(destZ - respZ) > travelDistZ) { return; } } } } if (is_air_ok) { i_nextMoveTime.Reset(0); } else { if (RandomHelper.randChance(50)) { i_nextMoveTime.Reset(RandomHelper.IRand(5000, 10000)); } else { i_nextMoveTime.Reset(RandomHelper.IRand(50, 400)); } } creature.AddUnitState(UnitState.RoamingMove); MoveSplineInit init = new MoveSplineInit(creature); init.MoveTo(destX, destY, destZ); init.SetWalk(true); init.Launch(); //Call for creature group update if (creature.GetFormation() != null && creature.GetFormation().getLeader() == creature) { creature.GetFormation().LeaderMoveTo(destX, destY, destZ); } }
public void _setTargetLocation(T owner, bool updateDestination) { if (!Reftarget.IsValid() || !Target.IsInWorld) { return; } if (owner.HasUnitState(UnitState.NotMove)) { return; } if (owner.IsMovementPreventedByCasting()) { return; } if (owner.IsTypeId(TypeId.Unit) && !Target.IsInAccessiblePlaceFor(owner.ToCreature())) { owner.ToCreature().SetCannotReachTarget(true); return; } if (owner.IsTypeId(TypeId.Unit) && owner.ToCreature().IsFocusing(null, true)) { return; } float x, y, z; if (updateDestination || i_path == null) { if (offset == 0) { if (Target.IsWithinDistInMap(owner, SharedConst.ContactDistance)) { return; } // to nearest contact position Target.GetContactPoint(owner, out x, out y, out z); } else { float dist = 0; float size = 0; // Pets need special handling. // We need to subtract GetObjectSize() 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() && Target.IsTypeId(TypeId.Player)) { dist = 1.0f; // target.GetCombatReach(); size = 1.0f; // target.GetCombatReach() - target.GetObjectSize(); } else { dist = offset + 1.0f; size = owner.GetObjectSize(); } if (Target.IsWithinDistInMap(owner, dist)) { return; } // to at i_offset distance from target and i_angle from target facing Target.GetClosePoint(out x, out y, out z, size, offset, angle); } } else { // the destination has not changed, we just need to refresh the path (usually speed change) var end = i_path.GetEndPosition(); x = end.X; y = end.Y; z = end.Z; } if (i_path == null) { i_path = new PathGenerator(owner); } // allow pets to use shortcut if no path found when following their master bool forceDest = (owner.IsTypeId(TypeId.Unit) && owner.IsPet() && owner.HasUnitState(UnitState.Follow)); bool result = i_path.CalculatePath(x, y, z, forceDest); if (!result && Convert.ToBoolean(i_path.GetPathType() & PathType.NoPath)) { // Can't reach target recalculateTravel = true; if (owner.IsTypeId(TypeId.Unit)) { owner.ToCreature().SetCannotReachTarget(true); } return; } _addUnitStateMove(owner); targetReached = false; recalculateTravel = false; owner.AddUnitState(UnitState.Chase); if (owner.IsTypeId(TypeId.Unit)) { owner.ToCreature().SetCannotReachTarget(false); } MoveSplineInit init = new MoveSplineInit(owner); init.MovebyPath(i_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.0f) { init.SetFacing(Target); } init.Launch(); }
bool StartMove(Creature creature) { if (path == null || path.Empty()) { return(false); } if (Stopped()) { return(true); } bool transportPath = creature.GetTransport() != null; if (isArrivalDone) { if ((currentNode == path.Count - 1) && !repeating) // If that's our last waypoint { WaypointData waypoint = path.LookupByIndex((int)currentNode); float x = waypoint.x; float y = waypoint.y; float z = waypoint.z; float o = creature.GetOrientation(); if (!transportPath) { creature.SetHomePosition(x, y, z, o); } else { Transport trans = creature.GetTransport(); if (trans) { o -= trans.GetOrientation(); creature.SetTransportHomePosition(x, y, z, o); trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o); creature.SetHomePosition(x, y, z, o); } else { transportPath = false; } // else if (vehicle) - this should never happen, vehicle offsets are const } creature.GetMotionMaster().Initialize(); return(false); } currentNode = (uint)((currentNode + 1) % path.Count); } var node = path.LookupByIndex((int)currentNode); isArrivalDone = false; creature.AddUnitState(UnitState.RoamingMove); 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 if (transportPath) { init.DisableTransportPathTransformations(); ITransport trans = creature.GetDirectTransport(); if (trans != null) { 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 //! but formationDest contains global coordinates init.MoveTo(node.x, node.y, node.z); //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table if (node.orientation != 0 && node.delay != 0) { init.SetFacing(node.orientation); } switch (node.moveType) { case WaypointMoveType.Land: init.SetAnimation(AnimType.ToGround); break; case WaypointMoveType.Takeoff: init.SetAnimation(AnimType.ToFly); break; case WaypointMoveType.Run: init.SetWalk(false); break; case WaypointMoveType.Walk: init.SetWalk(true); break; } init.Launch(); //Call for creature group update if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) { creature.GetFormation().LeaderMoveTo(formationDest, node.id, (uint)node.moveType, (node.orientation != 0 && node.delay != 0) ? true : false); } return(true); }
bool StartMove(Creature creature) { if (!creature || !creature.IsAlive()) { return(false); } if (path == null || path.nodes.Empty()) { return(false); } if (Stopped()) { return(true); } bool transportPath = creature.GetTransport() != null; if (isArrivalDone) { if ((currentNode == path.nodes.Count - 1) && !repeating) // If that's our last waypoint { WaypointNode waypoint = path.nodes.LookupByIndex((int)currentNode); float x = waypoint.x; float y = waypoint.y; float z = waypoint.z; float o = creature.GetOrientation(); if (!transportPath) { creature.SetHomePosition(x, y, z, o); } else { Transport trans = creature.GetTransport(); if (trans) { o -= trans.GetOrientation(); creature.SetTransportHomePosition(x, y, z, o); trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o); creature.SetHomePosition(x, y, z, o); } else { transportPath = false; } // else if (vehicle) - this should never happen, vehicle offsets are const } return(false); } currentNode = (uint)((currentNode + 1) % path.nodes.Count); } float finalOrient = 0.0f; WaypointMoveType finalMove = WaypointMoveType.Walk; List <Vector3> pathing = new List <Vector3>(); pathing.Add(new Vector3(creature.GetPositionX(), creature.GetPositionY(), creature.GetPositionZ())); for (int i = (int)currentNode; i < path.nodes.Count; ++i) { WaypointNode waypoint = path.nodes.LookupByIndex(i); pathing.Add(new Vector3(waypoint.x, waypoint.y, waypoint.z)); finalOrient = waypoint.orientation; finalMove = waypoint.moveType; if (waypoint.delay != 0) { break; } } // if we have only 1 point, only current position, we shall return if (pathing.Count < 2) { return(false); } isArrivalDone = false; recalculateSpeed = false; creature.AddUnitState(UnitState.RoamingMove); MoveSplineInit init = new MoveSplineInit(creature); var node = path.nodes.LookupByIndex((int)currentNode); Position formationDest = new Position(node.x, node.y, node.z, 0.0f); //! If creature is on transport, we assume waypoints set in DB are already transport offsets if (transportPath) { init.DisableTransportPathTransformations(); ITransport trans = creature.GetDirectTransport(); if (trans != null) { trans.CalculatePassengerPosition(ref formationDest.posX, ref formationDest.posY, ref formationDest.posZ, ref formationDest.Orientation); } } init.MovebyPath(pathing.ToArray(), (int)currentNode); switch (finalMove) { case WaypointMoveType.Land: init.SetAnimation(AnimType.ToGround); break; case WaypointMoveType.Takeoff: init.SetAnimation(AnimType.ToFly); break; case WaypointMoveType.Run: init.SetWalk(false); break; case WaypointMoveType.Walk: init.SetWalk(true); break; } if (finalOrient != 0.0f) { init.SetFacing(finalOrient); } init.Launch(); //Call for creature group update if (creature.GetFormation() != null && creature.GetFormation().getLeader() == creature) { creature.GetFormation().LeaderMoveTo(formationDest.posX, formationDest.posY, formationDest.posZ); } return(true); }
bool StartMove(Creature creature) { if (!creature || !creature.IsAlive()) { return(true); } if (_done || _path == null || _path.nodes.Empty()) { return(true); } // if the owner is the leader of its formation, check members status if (creature.IsFormationLeader() && !creature.IsFormationLeaderMoveAllowed()) { _nextMoveTime.Reset(1000); return(true); } bool transportPath = creature.GetTransport() != null; if (_isArrivalDone) { if ((_currentNode == _path.nodes.Count - 1) && !_repeating) // If that's our last waypoint { WaypointNode lastWaypoint = _path.nodes.ElementAt(_currentNode); float x = lastWaypoint.x; float y = lastWaypoint.y; float z = lastWaypoint.z; float o = creature.GetOrientation(); if (!transportPath) { creature.SetHomePosition(x, y, z, o); } else { Transport trans = creature.GetTransport(); if (trans) { o -= trans.GetOrientation(); creature.SetTransportHomePosition(x, y, z, o); trans.CalculatePassengerPosition(ref x, ref y, ref z, ref o); creature.SetHomePosition(x, y, z, o); } else { transportPath = false; } // else if (vehicle) - this should never happen, vehicle offsets are const } _done = true; return(true); } _currentNode = (_currentNode + 1) % _path.nodes.Count; // inform AI if (creature.IsAIEnabled) { Cypher.Assert(_currentNode < _path.nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.id})"); creature.GetAI().WaypointStarted(_path.nodes[(int)_currentNode].id, _path.id); } } WaypointNode waypoint = _path.nodes.ElementAt(_currentNode); Position formationDest = new Position(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation != 0 && waypoint.delay != 0) ? waypoint.orientation : 0.0f); _isArrivalDone = false; _recalculateSpeed = false; creature.AddUnitState(UnitState.RoamingMove); MoveSplineInit init = new MoveSplineInit(creature); //! If creature is on transport, we assume waypoints set in DB are already transport offsets if (transportPath) { init.DisableTransportPathTransformations(); ITransport trans = creature.GetDirectTransport(); if (trans != null) { 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 //! but formationDest contains global coordinates init.MoveTo(waypoint.x, waypoint.y, waypoint.z); //! Accepts angles such as 0.00001 and -0.00001, 0 must be ignored, default value in waypoint table if (waypoint.orientation != 0 && waypoint.delay != 0) { init.SetFacing(waypoint.orientation); } switch (waypoint.moveType) { case WaypointMoveType.Land: init.SetAnimation(AnimType.ToGround); break; case WaypointMoveType.Takeoff: init.SetAnimation(AnimType.ToFly); break; case WaypointMoveType.Run: init.SetWalk(false); break; case WaypointMoveType.Walk: init.SetWalk(true); break; } init.Launch(); // inform formation creature.SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation != 0 && waypoint.delay != 0) ? true : false); return(true); }