void SetTargetLocation(T owner) { if (owner == null || !owner.IsAlive()) { return; } if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { AddFlag(MovementGeneratorFlags.Interrupted); owner.StopMoving(); _path = null; return; } Position destination = new (owner.GetPosition()); GetPoint(owner, destination); // Add LOS check for target point if (!owner.IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ())) { _timer.Reset(200); return; } if (_path == null) { _path = new PathGenerator(owner); _path.SetPathLengthLimit(30.0f); } bool result = _path.CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); if (!result || _path.GetPathType().HasFlag(PathType.NoPath) || _path.GetPathType().HasFlag(PathType.Shortcut) || _path.GetPathType().HasFlag(PathType.FarFromPoly)) { _timer.Reset(100); return; } owner.AddUnitState(UnitState.FleeingMove); MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(false); int traveltime = init.Launch(); _timer.Reset(traveltime + RandomHelper.URand(800, 1500)); }
public override bool DoUpdate(T owner, uint time_diff) { if (owner.HasUnitState(UnitState.Root | UnitState.Stunned | UnitState.Distracted)) { return(true); } if (i_nextMoveTime.Passed()) { // currently moving, update location owner.AddUnitState(UnitState.ConfusedMove); if (owner.MoveSpline.Finalized()) { i_nextMoveTime.Reset(RandomHelper.IRand(800, 1500)); } } else { // waiting for next move i_nextMoveTime.Update(time_diff); if (i_nextMoveTime.Passed()) { // start moving owner.AddUnitState(UnitState.ConfusedMove); float dest = (float)(4.0f * RandomHelper.NextDouble() - 2.0f); Position pos = new Position(i_x, i_y, i_z); owner.MovePositionToFirstCollision(ref pos, dest, 0.0f); PathGenerator path = new PathGenerator(owner); path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); if (!result || path.GetPathType().HasAnyFlag(PathType.NoPath)) { i_nextMoveTime.Reset(100); return(true); } MoveSplineInit init = new MoveSplineInit(owner); init.MovebyPath(path.GetPath()); init.SetWalk(true); init.Launch(); } } return(true); }
void SetRandomLocation(Creature owner) { if (owner == null) { return; } if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { _interrupt = true; owner.StopMoving(); return; } owner.AddUnitState(UnitState.RoamingMove); Position position = new Position(_reference); float distance = RandomHelper.FRand(0.0f, 1.0f) * _wanderDistance; float angle = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f; owner.MovePositionToFirstCollision(ref position, distance, angle); uint resetTimer = RandomHelper.randChance(50) ? RandomHelper.URand(5000, 10000) : RandomHelper.URand(1000, 2000); if (_path == null) { _path = new PathGenerator(owner); } _path.SetPathLengthLimit(30.0f); bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath)) { _timer.Reset(100); return; } MoveSplineInit init = new MoveSplineInit(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(true); int traveltime = init.Launch(); _timer.Reset(traveltime + resetTimer); // Call for creature group update owner.SignalFormationMovement(position); }
public void MoveTo(Vector3 dest, bool generatePath = true, bool forceDestination = false) { if (generatePath) { PathGenerator path = new PathGenerator(unit); bool result = path.CalculatePath(dest.X, dest.Y, dest.Z, forceDestination); if (result && !Convert.ToBoolean(path.GetPathType() & PathType.NoPath)) { MovebyPath(path.GetPath()); return; } } args.path_Idx_offset = 0; args.path = new Vector3[2]; TransportPathTransform transform = new TransportPathTransform(unit, args.TransformForTransport); args.path[1] = transform.Calc(dest); }
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(); }
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 override bool Update(Unit owner, uint diff) { // owner might be dead or gone (can we even get nullptr here?) if (!owner || !owner.IsAlive()) { return(false); } // our target might have gone away Unit target = _abstractFollower.GetTarget(); if (target == null || !target.IsInWorld) { return(false); } // the owner might be unable to move (rooted or casting), pause movement if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { owner.StopMoving(); _lastTargetPosition = null; Creature cOwner = owner.ToCreature(); if (cOwner != null) { cOwner.SetCannotReachTarget(false); } return(true); } bool mutualChase = IsMutualChase(owner, target); float hitboxSum = owner.GetCombatReach() + target.GetCombatReach(); float minRange = _range.HasValue ? _range.Value.MinRange + hitboxSum : SharedConst.ContactDistance; float minTarget = (_range.HasValue ? _range.Value.MinTolerance : 0.0f) + hitboxSum; float maxRange = _range.HasValue ? _range.Value.MaxRange + hitboxSum : owner.GetMeleeRange(target); // melee range already includes hitboxes float maxTarget = _range.HasValue ? _range.Value.MaxTolerance + hitboxSum : SharedConst.ContactDistance + hitboxSum; ChaseAngle?angle = mutualChase ? null : _angle; // if we're already moving, periodically check if we're already in the expected range... if (owner.HasUnitState(UnitState.ChaseMove)) { if (_rangeCheckTimer > diff) { _rangeCheckTimer -= diff; } else { _rangeCheckTimer = RANGE_CHECK_INTERVAL; if (PositionOkay(owner, target, _movingTowards ? null : minTarget, _movingTowards ? maxTarget : null, angle)) { _path = null; owner.StopMoving(); owner.SetInFront(target); DoMovementInform(owner, target); return(true); } } } // if we're done moving, we want to clean up if (owner.HasUnitState(UnitState.ChaseMove) && owner.MoveSpline.Finalized()) { _path = null; Creature cOwner = owner.ToCreature(); if (cOwner != null) { cOwner.SetCannotReachTarget(false); } owner.ClearUnitState(UnitState.ChaseMove); owner.SetInFront(target); DoMovementInform(owner, target); } // if the target moved, we have to consider whether to adjust if (_lastTargetPosition == null || target.GetPosition() != _lastTargetPosition || mutualChase != _mutualChase) { _lastTargetPosition = new(target.GetPosition()); _mutualChase = mutualChase; if (owner.HasUnitState(UnitState.ChaseMove) || !PositionOkay(owner, target, minRange, maxRange, angle)) { Creature cOwner = owner.ToCreature(); // can we get to the target? if (cOwner != null && !target.IsInAccessiblePlaceFor(cOwner)) { cOwner.SetCannotReachTarget(true); cOwner.StopMoving(); _path = null; return(true); } // figure out which way we want to move bool moveToward = !owner.IsInDist(target, maxRange); // make a new path if we have to... if (_path == null || moveToward != _movingTowards) { _path = new PathGenerator(owner); } float x, y, z; bool shortenPath; // if we want to move toward the target and there's no fixed angle... if (moveToward && !angle.HasValue) { // ...we'll pathfind to the center, then shorten the path target.GetPosition(out x, out y, out z); shortenPath = true; } else { // otherwise, we fall back to nearpoint finding target.GetNearPoint(owner, out x, out y, out z, (moveToward ? maxTarget : minTarget) - hitboxSum, angle.HasValue ? target.ToAbsoluteAngle(angle.Value.RelativeAngle) : target.GetAbsoluteAngle(owner)); shortenPath = false; } if (owner.IsHovering()) { owner.UpdateAllowedPositionZ(x, y, ref z); } bool success = _path.CalculatePath(x, y, z, owner.CanFly()); if (!success || _path.GetPathType().HasAnyFlag(PathType.NoPath)) { if (cOwner) { cOwner.SetCannotReachTarget(true); } owner.StopMoving(); return(true); } if (shortenPath) { _path.ShortenPathUntilDist(target, maxTarget); } if (cOwner) { cOwner.SetCannotReachTarget(false); } owner.AddUnitState(UnitState.ChaseMove); bool walk = false; if (cOwner && !cOwner.IsPet()) { switch (cOwner.GetMovementTemplate().GetChase()) { case CreatureChaseMovementType.CanWalk: walk = owner.IsWalking(); break; case CreatureChaseMovementType.AlwaysWalk: walk = true; break; default: break; } } MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(walk); init.SetFacing(target); init.Launch(); } } // and then, finally, we're done for the tick return(true); }
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(); }
public override bool Update(Unit owner, uint diff) { // owner might be dead or gone if (owner == null || !owner.IsAlive()) { return(false); } // our target might have gone away Unit target = _abstractFollower.GetTarget(); if (target == null || !target.IsInWorld) { return(false); } if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { _path = null; owner.StopMoving(); _lastTargetPosition = null; return(true); } _checkTimer.Update((int)diff); if (_checkTimer.Passed()) { _checkTimer.Reset(CHECK_INTERVAL); if (HasFlag(MovementGeneratorFlags.InformEnabled) && PositionOkay(owner, target, _range, _angle)) { RemoveFlag(MovementGeneratorFlags.InformEnabled); _path = null; owner.StopMoving(); _lastTargetPosition = new(); DoMovementInform(owner, target); return(true); } } if (owner.HasUnitState(UnitState.FollowMove) && owner.MoveSpline.Finalized()) { RemoveFlag(MovementGeneratorFlags.InformEnabled); _path = null; owner.ClearUnitState(UnitState.FollowMove); DoMovementInform(owner, target); } if (_lastTargetPosition == null || _lastTargetPosition.GetExactDistSq(target.GetPosition()) > 0.0f) { _lastTargetPosition = new(target.GetPosition()); if (owner.HasUnitState(UnitState.FollowMove) || !PositionOkay(owner, target, _range + FOLLOW_RANGE_TOLERANCE)) { if (_path == null) { _path = new PathGenerator(owner); } float x, y, z; // select angle float tAngle; float curAngle = target.GetRelativeAngle(owner); if (_angle.IsAngleOkay(curAngle)) { tAngle = curAngle; } else { float diffUpper = Position.NormalizeOrientation(curAngle - _angle.UpperBound()); float diffLower = Position.NormalizeOrientation(_angle.LowerBound() - curAngle); if (diffUpper < diffLower) { tAngle = _angle.UpperBound(); } else { tAngle = _angle.LowerBound(); } } target.GetNearPoint(owner, out x, out y, out z, _range, target.ToAbsoluteAngle(tAngle)); if (owner.IsHovering()) { owner.UpdateAllowedPositionZ(x, y, ref z); } // pets are allowed to "cheat" on pathfinding when following their master bool allowShortcut = false; Pet oPet = owner.ToPet(); if (oPet != null) { if (target.GetGUID() == oPet.GetOwnerGUID()) { allowShortcut = true; } } bool success = _path.CalculatePath(x, y, z, allowShortcut); if (!success || _path.GetPathType().HasFlag(PathType.NoPath)) { owner.StopMoving(); return(true); } owner.AddUnitState(UnitState.FollowMove); AddFlag(MovementGeneratorFlags.InformEnabled); MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(target.IsWalking()); init.SetFacing(target.GetOrientation()); init.Launch(); } } return(true); }
public override bool DoUpdate(T owner, uint diff) { if (!owner || !owner.IsAlive()) { return(false); } if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { AddFlag(MovementGeneratorFlags.Interrupted); owner.StopMoving(); _path = null; return(true); } else { RemoveFlag(MovementGeneratorFlags.Interrupted); } // waiting for next move _timer.Update(diff); if ((HasFlag(MovementGeneratorFlags.SpeedUpdatePending) && !owner.MoveSpline.Finalized()) || (_timer.Passed() && owner.MoveSpline.Finalized())) { RemoveFlag(MovementGeneratorFlags.Transitory); Position destination = new(_reference); float distance = (float)(4.0f * RandomHelper.FRand(0.0f, 1.0f) - 2.0f); float angle = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f; owner.MovePositionToFirstCollision(destination, distance, angle); // Check if the destination is in LOS if (!owner.IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ())) { // Retry later on _timer.Reset(200); return(true); } if (_path == null) { _path = new PathGenerator(owner); _path.SetPathLengthLimit(30.0f); } bool result = _path.CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); if (!result || _path.GetPathType().HasFlag(PathType.NoPath) || _path.GetPathType().HasFlag(PathType.Shortcut) || _path.GetPathType().HasFlag(PathType.FarFromPoly)) { _timer.Reset(100); return(true); } owner.AddUnitState(UnitState.ConfusedMove); MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(true); int traveltime = init.Launch(); _timer.Reset(traveltime + RandomHelper.URand(800, 1500)); } return(true); }
void SetRandomLocation(Creature owner) { if (owner == null) { return; } if (owner.HasUnitState(UnitState.NotMove | UnitState.LostControl) || owner.IsMovementPreventedByCasting()) { AddFlag(MovementGeneratorFlags.Interrupted); owner.StopMoving(); _path = null; return; } Position position = new(_reference); float distance = RandomHelper.FRand(0.0f, 1.0f) * _wanderDistance; float angle = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f; owner.MovePositionToFirstCollision(position, distance, angle); uint resetTimer = RandomHelper.randChance(50) ? RandomHelper.URand(5000, 10000) : RandomHelper.URand(1000, 2000); if (_path == null) { _path = new PathGenerator(owner); _path.SetPathLengthLimit(30.0f); } bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath) || _path.GetPathType().HasAnyFlag(PathType.Shortcut)) { _timer.Reset(100); return; } owner.AddUnitState(UnitState.RoamingMove); bool walk = true; switch (owner.GetMovementTemplate().GetRandom()) { case CreatureRandomMovementType.CanRun: walk = owner.IsWalking(); break; case CreatureRandomMovementType.AlwaysRun: walk = false; break; default: break; } MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(walk); int traveltime = init.Launch(); _timer.Reset(traveltime + resetTimer); // Call for creature group update owner.SignalFormationMovement(position); }
void SetRandomLocation(Creature owner) { if (owner == null) { return; } if (owner.HasUnitState(UnitState.NotMove | UnitState.LostControl) || owner.IsMovementPreventedByCasting()) { AddFlag(MovementGeneratorFlags.Interrupted); owner.StopMoving(); _path = null; return; } Position position = new(_reference); float distance = RandomHelper.FRand(0.0f, _wanderDistance); float angle = RandomHelper.FRand(0.0f, MathF.PI * 2.0f); owner.MovePositionToFirstCollision(position, distance, angle); // Check if the destination is in LOS if (!owner.IsWithinLOS(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ())) { // Retry later on _timer.Reset(200); return; } if (_path == null) { _path = new PathGenerator(owner); _path.SetPathLengthLimit(30.0f); } bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); if (!result || _path.GetPathType().HasFlag(PathType.NoPath) || _path.GetPathType().HasFlag(PathType.Shortcut) || _path.GetPathType().HasFlag(PathType.FarFromPoly)) { _timer.Reset(100); return; } RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.TimedPaused); owner.AddUnitState(UnitState.RoamingMove); bool walk = true; switch (owner.GetMovementTemplate().GetRandom()) { case CreatureRandomMovementType.CanRun: walk = owner.IsWalking(); break; case CreatureRandomMovementType.AlwaysRun: walk = false; break; default: break; } MoveSplineInit init = new(owner); init.MovebyPath(_path.GetPath()); init.SetWalk(walk); int splineDuration = init.Launch(); --_wanderSteps; if (_wanderSteps != 0) // Creature has yet to do steps before pausing { _timer.Reset(splineDuration); } else { // Creature has made all its steps, time for a little break _timer.Reset(splineDuration + RandomHelper.URand(4, 10) * Time.InMilliseconds); // Retails seems to use rounded numbers so we do as well _wanderSteps = RandomHelper.URand(2, 10); } // Call for creature group update owner.SignalFormationMovement(); }