// Create force field dynamically. public ForceField(GameEnvironment env, Vector2 pos, float angle, GameEntity o) : base(env) { Position = pos; m_angle = angle; Initialize(); owner = o; }
private float waitTimer; //countdown timer for ships to stay inert while neutral #endregion Fields #region Constructors /// <summary> /// Creates a new AI with given spawnpoint and given environment /// Initial state is Neutral /// </summary> public AIController(SpawnPoint sp, GameEnvironment e) { timeSinceLastStateChange = 0; spawn = sp; env = e; nextState = State.Neutral; currentState = State.Neutral; target = null; answeringDistressCall = false; lookingFor = null; currentShip = null; timeSinceHitWall = 0; ; timeSinceChangedTargets = 0; waitTimer = 0; patrolPoints = new List<Vector2>(); patrolPoints.Add(randomPatrolPoint()); oldTarget = null; timeSinceMoved = 0; oldPosition = new Vector2(-1000, 1000);//I hope this is improbable timeSinceSawTarget = 0; timeSinceAnsweredDistressCall = 0; targetList = new List<GameEntity>(); }
public void GotShotBy(Ship s, GameEntity f) { if (controlled is TriangulusShip) { foreach (TriangulusShip t in m_env.triangles) { t.ai.DistressCall(controlled, f); } } else if (controlled is SquaretopiaShip) { foreach (SquaretopiaShip sq in m_env.squares) { sq.ai.DistressCall(controlled, f); } } else if (controlled is CircloidShip) { foreach (CircloidShip c in m_env.circles) { c.ai.DistressCall(controlled, f); } } }
public override void OnSeparate(Entity entB, FarseerPhysics.Dynamics.Contacts.Contact contact) { if (entB == shootTarget) { isShooting = false; shootTarget = null; } base.OnSeparate(entB, contact); }
public override void OnCollide(Entity entB, FarseerPhysics.Dynamics.Contacts.Contact contact) { if (contact.FixtureA == sensor || contact.FixtureB == sensor) contact.Enabled = false; if (entB is Ship && ((Ship) entB).IsFriendly()) { isShooting = true; shooterRotation = (float)Math.Atan2(entB.Position.Y - this.Position.Y, entB.Position.X - this.Position.X); shootTarget = (Ship) entB; } base.OnCollide(entB, contact); }
/// <summary> /// Call when sputnik's controlled ship (s) gets shot by f /// </summary> public void DistressCall(Ship s, GameEntity f) { if(currentState == State.Allied) { targetList.Insert(0, f); } //Don't answer distress calls too often or if you are a circloid ship and the shooter is a boss else if (timeSinceAnsweredDistressCall > 5 && !(currentShip is CircloidShip && f is SaphereBoss)) { timeSinceAnsweredDistressCall = 0; if (currentState == State.Neutral && !s.IsAllied((TakesDamage)f)) //Only non busy ships (neutral) answer {//Don't answer of some weird civil war is going on if (CanSee(currentShip, s))//If i can see sputniks ship, go help him { changeToAllied(s); targetList.Insert(0, f); } else //If I can't see Sputnik's ship, go look for it. { changeToConfused(s, true); targetList.Insert(0, f); } } } }
/// <summary> /// Method to call to change to neutral state /// </summary> private void changeToNeutral() { timeSinceSawTarget = 0; oldTarget = target; target = null; lookingFor = null; currentState = State.Neutral; nextState = State.Neutral; answeringDistressCall = false; timeSinceLastStateChange = 0; timeSinceChangedTargets = 0; targetList.Clear(); }
public virtual void Shoot(float elapsedTime, GameEntity target) { shooter.Shoot(elapsedTime); isShooting = true; if (target == Environment.sputnik.controlled) Environment.sputnik.controlled.ai.GotShotBy(Environment.sputnik.controlled, this); }
/// <summary> /// Method to call to change to allied state with target t /// </summary> private void changeToAllied(GameEntity t) { timeSinceSawTarget = 0; oldTarget = target; target = t; lookingFor = null; currentState = State.Allied; nextState = State.Allied; answeringDistressCall = false; timeSinceLastStateChange = 0; timeSinceChangedTargets = 0; }
/// <summary> /// Preliminary Vision, given starting GameEntity s and GameEntity Ship f, can s shoot to f /// </summary> private bool CanShoot(GameEntity s, GameEntity f) { //TODO For some reason this case happens, evidently something is going wrong somewhere if (s == null || f == null) { return false; } //TODO Im not quite sure why, but sometimes ships try to see null collisionbodys if (s.CollisionBody == null || f.CollisionBody == null) { return false; } if (s.CollisionBody.Position.Equals(f.CollisionBody.Position)) { // If we are touching, we can shoot each other return true; } rayCastTarget = f; env.CollisionWorld.RayCast(RayCastHit, s.CollisionBody.Position, f.CollisionBody.Position); return (hitBodyPosition.Equals(f.CollisionBody.Position)); }
/// <summary> /// Method to call to change to alert state with target t /// </summary> private void changeToAlert(GameEntity t) { if (currentState != State.Alert) { env.AlertEffect.Trigger(currentShip.Position); } timeSinceSawTarget = 0; oldTarget = target; target = t; lookingFor = null; currentState = State.Alert; nextState = State.Alert; answeringDistressCall = false; timeSinceLastStateChange = 0; timeSinceChangedTargets = 0; targetList.Clear(); }
/// <summary> /// Preliminary Vision, given starting GameEntity s and GameEntity Ship f, can s see f /// </summary> private bool CanSee(GameEntity s, GameEntity f) { //TODO For some reason this case happens, evidently something is going wrong somewhere if (s == null || f == null) { return false; } //TODO Im not quite sure why, but sometimes ships try to see null collisionbodys if (s.CollisionBody == null || f.CollisionBody == null) { return false; } if (s.CollisionBody.Position.Equals(f.CollisionBody.Position)) { // If we are touching, we can see each other return true; } float theta = Angle.Direction(s.Position, f.Position); //Angle that I want to see if (Angle.DistanceMag(theta, s.Rotation) < (MathHelper.ToRadians(20))) // If within cone of vision (20 degrees), raycast { rayCastTarget = f; env.CollisionWorld.RayCast(RayCastHit, s.CollisionBody.Position, f.CollisionBody.Position); return (hitBodyPosition.Equals(f.CollisionBody.Position)); } else //Not within cone of vision { return false; } }
/// <summary> /// Call when controlled ship gets tractored by s /// </summary> public void GotTractored(GameEntity s) { currentShip.DesiredVelocity = Vector2.Zero; changeToDisabled(s); }
/// <summary> /// Call when s gets shot by f, due to bosses not being ships, default to GameEntity /// </summary> public void GotShotBy(Ship s, GameEntity f) { if (currentState != State.Disabled && currentState != State.Allied) //Allied and Disabled ships don't react { if (CanSee(currentShip, f)) //If I can see the shooter { switch (currentState) { case State.Neutral: //Currently I only become un-neutral when shot changeToAlert(f); break; case State.Alert: //Someone shot me, time to do something if (f == target) //My target shot me, now Im mad { changeToHostile(f); } else //Someone else shot me, time to get suspicious of them { //I actually might want to make this behavior more faction like //If whoever shot me is the same faction as my previous target, I might just go hostile //Take this up to the game creator gods. changeToAlert(f); } break; case State.Hostile: if (timeSinceChangedTargets > 20) // If i haven't killed my target in 20 seconds, I should change to an easier target { changeToHostile(f); } break; default: //current do nothing if in Disabled or Hostile when shot break; } } else { if (currentState == State.Hostile) { if (timeSinceChangedTargets > 20) // If i haven't killed my target in 20 seconds, I should change to an easier target { changeToConfused(f, false); } } else { if (timeSinceChangedTargets > 10 || (s == currentShip && timeSinceChangedTargets > 5)) //Dont get confused too often, unless its me shot { changeToConfused(f, false); } } } } }
public void DistressCall(Ship s, GameEntity f) { //Player doesn't care about distress calls }
/// <summary> /// Method to call to change to confused state while looking for l and if adc(AnsweringDistressCall) /// </summary> private void changeToConfused(GameEntity l, bool adc) { timeSinceSawTarget = 0; oldTarget = target; target = null; lookingFor = l; currentState = State.Confused; nextState = State.Confused; answeringDistressCall = adc; timeSinceLastStateChange = 0; timeSinceChangedTargets = 0; }
public void GotFrozen(GameEntity s) { //Chaos }
/// <summary> /// Method to call to change to hostile state with target t /// </summary> private void changeToHostile(GameEntity t) { timeSinceSawTarget = 0; oldTarget = target; target = t; lookingFor = null; currentState = State.Hostile; nextState = State.Hostile; answeringDistressCall = false; timeSinceLastStateChange = 0; timeSinceChangedTargets = 0; targetList.Clear(); }
public void GotTractored(GameEntity s) { //Chaos }
public void Freeze(GameEntity s) { ++m_frozenCount; if (m_frozenCount == 1) ai.GotFrozen(s); CollisionBody.AngularVelocity = 0.0f; }