public IEnumerable States() { List <Sprite> targets = (This.Game.CurrentLevel as FrostbyteLevel).allies; Vector2 guardPosition = master.GroundPos; while (true) { Sprite closestTarget = master.GetClosestTarget(targets, 550.0f); if (closestTarget != null && Vector2.DistanceSquared(closestTarget.GroundPos, master.GroundPos) > 100 * 100) { master.charge(closestTarget.GroundPos, 1.3f); } else if (closestTarget == null && Vector2.DistanceSquared(guardPosition, master.GroundPos) > 20 * 20) { master.charge(guardPosition, 3.0f); } else if (closestTarget == null && Vector2.DistanceSquared(guardPosition, master.GroundPos) <= 20 * 20) { Sprite closestTarget2 = master.GetClosestTarget(targets, 800.0f); master.State = SpriteState.Idle; if (closestTarget2 != null) { master.Direction = closestTarget2.GroundPos - master.GroundPos; } } yield return(null); } }
/// <summary> /// Wander around within a certain range from closest enemy ( For Owls) /// </summary> internal static bool wideRangeWander(this Enemy ths, List <Sprite> targets, TimeSpan duration, float arcAngle, float wanderRadius) { Sprite target = ths.GetClosestTarget(targets); if (target == null) { return(false); } if (Vector2.DistanceSquared(ths.GroundPos, target.GroundPos) >= wanderRadius * wanderRadius) { ths.Direction = target.GroundPos - ths.GroundPos; ths.Direction.Normalize(); ths.GroundPos += ths.Direction * ths.Speed; } if (RNG.NextDouble() < 0.2) { double angle = Math.Atan2(ths.Direction.Y, ths.Direction.X) + (2 * RNG.NextDouble() - 1) * arcAngle; ths.Direction = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); //ths.GroundPos += ths.Direction * ths.Speed / 4; // Wandering should be *slow* } ths.GroundPos += ths.Direction * ths.Speed; // Wandering should be *slow* return(false); }
/// <summary> /// Charge but do not update direction for length of charge - complete /// </summary> internal static bool ram(this Enemy ths, List <Sprite> targets, TimeSpan duration, float aggroDistance, float speedMultiplier) { if (ths.Personality.Status != EnemyStatus.Ram) { ths.movementStartTime = This.gameTime.TotalGameTime; Sprite target = ths.GetClosestTarget(targets, aggroDistance); if (target != null) { ths.Direction = target.GroundPos - ths.GroundPos; ths.Personality.Status = EnemyStatus.Ram; } } float ramSpeed = ths.Speed * speedMultiplier; if (ths.Personality.Status == EnemyStatus.Ram) { if (duration == TimeSpan.MaxValue || This.gameTime.TotalGameTime <= ths.movementStartTime + duration) { ths.GroundPos += ths.Direction * ramSpeed; } else { ths.Personality.Status = EnemyStatus.Wander; return(true); } } return(false); }
internal static bool dartingBat(this Enemy ths, List <Sprite> targets, float dartSpeedMultiplier, int flyRadius, TimeSpan dartTimeout) { Sprite target = ths.GetClosestTarget(targets); if (target == null) { return(false); } float dartSpeed = ths.Speed * dartSpeedMultiplier; if (ths.Personality.Status != EnemyStatus.Charge) { nextHoverPoint = new Vector2( RNG.Next((int)target.GroundPos.X - flyRadius, (int)target.GroundPos.X + flyRadius), //(int)(ths.Pos.X + Vector2.Distance(target.Pos, ths.Pos))), RNG.Next((int)target.GroundPos.Y - flyRadius, (int)target.GroundPos.Y + flyRadius) //(int)(ths.Pos.Y + Vector2.Distance(target.Pos, ths.Pos))) ); ths.Direction = -(ths.GroundPos - nextHoverPoint);// -ths.GroundPos; ths.Direction.Normalize(); ths.Personality.Status = EnemyStatus.Charge; dartTimeout = new TimeSpan(0, 0, 0, 0, 300); ths.movementStartTime = This.gameTime.TotalGameTime; } //if we choose a nextHoverPoint thats beyond a wall, we get stuck... else if (Vector2.Distance(ths.GroundPos, nextHoverPoint) > 3f && nextHoverPoint != Vector2.Zero && This.gameTime.TotalGameTime < ths.movementStartTime + dartTimeout) { ths.GroundPos += ths.Direction * dartSpeed; } else { ths.Personality.Status = EnemyStatus.Wander; nextHoverPoint = new Vector2( RNG.Next((int)target.GroundPos.X - flyRadius, (int)target.GroundPos.X + flyRadius), //(int)(ths.Pos.X + Vector2.Distance(target.Pos, ths.Pos))), RNG.Next((int)target.GroundPos.Y - flyRadius, (int)target.GroundPos.Y + flyRadius) ); ths.Direction = (ths.GroundPos - nextHoverPoint);// -ths.GroundPos; ths.Direction.Normalize(); //dartTimeout = new TimeSpan(0, 0, 0, 0, 300); ths.movementStartTime = This.gameTime.TotalGameTime; return(true); } if (RNG.NextDouble() < 0.9) { double angle = Math.Atan2(ths.Direction.Y, ths.Direction.X) + (2 * RNG.NextDouble() - 1) * Math.PI / 8; ths.Direction = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); ths.GroundPos += ths.Direction * ths.Speed / 4; // Wandering should be *slow* } return(false); }
/// <summary> /// Move away when x distance from target until z distance from player /// </summary> internal static bool teaseRetreat(this Enemy ths, List <Sprite> targets, float aggroDistance, float safeDistance, float speedMultiplier) { if (ths.GetClosestTarget(targets, aggroDistance) != null) { return(retreat(ths, targets, safeDistance, speedMultiplier)); } else { return(true); } }
/// <summary> /// Update enemy position directly toward target for given duration - complete /// </summary> internal static bool charge(this Enemy ths, List <Sprite> targets, float aggroDistance, float speedMultiplier) { Sprite min = ths.GetClosestTarget(targets, aggroDistance); if (min == null) // No targets, so just continue on { return(true); } charge(ths, min.GroundPos, speedMultiplier); return(false); }
/// <summary> /// Be still until a certain distance from a player (between aggroDistance and ignoreDistance) /// </summary> internal static bool camp(this Enemy ths, List <Sprite> targets, float aggroDistance, float ignoreDistance) { Sprite target = ths.GetClosestTarget(targets, aggroDistance); if (target != null) { ths.Personality.Status = EnemyStatus.Wander; return(true); } else { target = ths.GetClosestTarget(targets); if (target != null && (Vector2.DistanceSquared(target.GroundPos, ths.GroundPos) > (ignoreDistance * ignoreDistance))) { ths.Personality.Status = EnemyStatus.Wander; return(true); } ths.Personality.Status = EnemyStatus.Frozen; } return(false); }
/// <summary> /// Hide and follow player until certain distance from player - complete /// </summary> internal static bool stealthCharge(this Enemy ths, List <Sprite> targets, TimeSpan duration, float visibleDistance, float aggroDistance, float speedMultiplier) { if (ths.Personality.Status != EnemyStatus.Charge) { ths.movementStartTime = This.gameTime.TotalGameTime; } Sprite target = ths.GetClosestTarget(targets, aggroDistance); if (target != null) { ths.Personality.Status = EnemyStatus.Charge; if (Vector2.DistanceSquared(target.GroundPos, ths.GroundPos) <= visibleDistance * visibleDistance) { ths.Personality.Status = EnemyStatus.Wander; ths.Visible = true; return(true); } else { ths.Visible = false; } } else { return(false); } float chargeSpeed = ths.Speed * speedMultiplier; if (ths.Personality.Status == EnemyStatus.Charge) { if (duration == TimeSpan.MaxValue || This.gameTime.TotalGameTime <= ths.movementStartTime + duration) { ths.Direction = target.GroundPos - ths.GroundPos; ths.GroundPos += ths.Direction * chargeSpeed; } else { ths.Personality.Status = EnemyStatus.Wander; ths.Visible = true; return(true); } } return(false); }
/// <summary> /// Wander around for x seconds or until within a certain distance from a target /// </summary> internal static bool wander(this Enemy ths, List <Sprite> targets, TimeSpan duration, float safeDistance, float arcAngle) { Sprite min = ths.GetClosestTarget(targets, safeDistance); if (min != null) // Near a target, move on to something else { return(true); } if (RNG.NextDouble() < 0.9) { double angle = Math.Atan2(ths.Direction.Y, ths.Direction.X) + (2 * RNG.NextDouble() - 1) * arcAngle; ths.Direction = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); ths.GroundPos += ths.Direction * ths.Speed / 4; // Wandering should be *slow* } return(false); }
public IEnumerable States() { List <Sprite> targets = (This.Game.CurrentLevel as FrostbyteLevel).allies; float[] transitionDistances = new float[1] { 0f }; while (true) { Sprite closestTarget = master.GetClosestTarget(targets, 500.0f); if (closestTarget != null && Vector2.DistanceSquared(master.GroundPos, closestTarget.GroundPos) <= 500 * 500) { EnemyAI.wideRangeWander(master, targets, TimeSpan.MaxValue, (float)Math.PI / 4, 400f); } yield return(null); } }