public Missile(Game game, StaticObject target, StaticObject parent) : base(game, parent) { this.target = target; Vector3 velocity = this.shipData.speed * Matrix.CreateFromQuaternion(this.rotation).Forward; BBN_Game.Controller.GameController.particleController.MissileFiredExplosions(parent.Position, velocity, parent); }
public int getEliminationPriority(StaticObject target) { if (target is playerObject) return PRIORITY_FOR_ELIMINATING_PLAYER; else if (target is Turret) return PRIORITY_FOR_ELIMINATING_TURRET; else if (target is Destroyer) return PRIORITY_FOR_ELIMINATING_DESTROYER; else if (target is Fighter) return PRIORITY_FOR_ELIMINATING_FIGHTER; else if (target is Base) return PRIORITY_FOR_ELIMINATING_BASE; else return 0; }
protected float lifeSpan; // how long the bullet lasts #endregion Fields #region Constructors /// <summary> /// Constructor /// </summary> /// <param name="game">Game class</param> /// <param name="parent">The parent of the bullet</param> public Projectile(Game game, StaticObject parent) : base(game, Objects.Team.neutral, parent.Position + Vector3.Transform(new Vector3(0, -parent.getGreatestLength / 2, parent.getGreatestLength / 2), Matrix.CreateFromQuaternion(parent.rotation))) { this.Health = 10; numHudLines = 3; typeOfLine = PrimitiveType.LineStrip; Vector3 foreward = parent.Position + Vector3.Transform(new Vector3(0, 0, 10), Matrix.CreateFromQuaternion(parent.rotation)); Vector3 PYR = MathEuler.AngleTo(foreward, parent.Position); rotation = Quaternion.CreateFromYawPitchRoll(PYR.Y, PYR.X, PYR.Z); this.shipData.speed = parent.ShipMovementInfo.speed; this.parent = parent; }
/// <summary> /// Constructor /// </summary> /// <param name="game">Game class</param> /// <param name="parent">The parent of the bullet</param> /// <param name="target">The target for the object</param> public Bullet(Game game, StaticObject target, StaticObject parent) : base(game, parent) { this.target = target; }
/// <summary> /// Checks if a particular dodge is valid /// </summary> private bool isDodgeValid(DynamicObject callingAI,float dodgeAngle,int dodgeAngleMultiplierYaw,int dodgeAngleMultiplierPitch,PathInformation pathInfo, StaticObject closestObstruction,float dodgeDistance, ref Vector3 dodgeWp) { bool bFlag = false; //Define a conal area around the current path to choose another path from Quaternion qRot = Quaternion.CreateFromYawPitchRoll(dodgeAngle * dodgeAngleMultiplierYaw, dodgeAngle * dodgeAngleMultiplierPitch, 0); Vector3 choiceVector = Vector3.Normalize( Vector3.Transform(pathInfo.currentWaypoint.Position - callingAI.Position, Matrix.CreateFromQuaternion(qRot))); dodgeWp = callingAI.Position + choiceVector * dodgeDistance; if ((dodgeWp - closestObstruction.Position).Length() > dodgeDistance) { foreach (GridObjectInterface o in spatialGrid.checkNeighbouringBlocks(dodgeWp)) { if (o != callingAI) { if (o is StaticObject) { if ((o.Position - dodgeWp).Length() > (o.getBoundingSphere().Radius + callingAI.getBoundingSphere().Radius * (DODGE_DISTANCE_MULTIPLIER))) bFlag = true; } if (o is DynamicObject) { if (isObjectRegistered(o as DynamicObject)) { Node otherObjectsWaypoint = objectPaths[o as DynamicObject].currentWaypoint; if (otherObjectsWaypoint != null) { if ((otherObjectsWaypoint.Position - dodgeWp).Length() < (o.getBoundingSphere().Radius + callingAI.getBoundingSphere().Radius * (DODGE_DISTANCE_MULTIPLIER))) bFlag = false; } } } if (!spatialGrid.isInGrid(new Node(dodgeWp,-1))) bFlag = false; } } } return bFlag; }
/// <summary> /// Method to set the path of an ai unit in order to dodge an object /// </summary> /// <param name="callingAI">ai to perform dodge</param> /// <param name="closestObstruction">closest obstruction</param> private void dodgeObject(DynamicObject callingAI, StaticObject closestObstruction) { if (!this.isObjectRegistered(callingAI)) return; PathInformation pathInfo = objectPaths[callingAI]; if (pathInfo.currentWaypoint == null) return; if (!dodgeInactiveCountDown.Keys.Contains(callingAI)) dodgeInactiveCountDown.Add(callingAI, RETAIN_DODGE_PATH_TICKS); else return; Vector3 dodgeWp = new Vector3(); bool bFlag = false; // Set the new path: float dodgeDistance = (callingAI.getBoundingSphere().Radius + closestObstruction.getBoundingSphere().Radius) * DODGE_DISTANCE_MULTIPLIER; float distanceToObject = (callingAI.Position - closestObstruction.Position).Length(); float distanceToCurrentWp = (callingAI.Position - pathInfo.currentWaypoint.Position).Length(); float dodgeAngle = (float)Math.Abs(Math.Atan2(distanceToObject, dodgeDistance)); for (int i = (int)Math.Ceiling(dodgeAngle); i * dodgeAngle < Math.PI; ++i) { for (int j = (int)Math.Ceiling(dodgeAngle); j * dodgeAngle < Math.PI; ++j) { if (isDodgeValid(callingAI, dodgeAngle, i, j, pathInfo, closestObstruction, dodgeDistance, ref dodgeWp)) { bFlag = true; break; } if (isDodgeValid(callingAI, -dodgeAngle, i, j, pathInfo, closestObstruction, dodgeDistance, ref dodgeWp)) { bFlag = true; break; } } if (bFlag) break; } List<Node> path = pathInfo.remainingPath; if (path.Count > 0) path.Remove(path.Last()); path.Add(new Node(dodgeWp, -1)); pathInfo.remainingPath = path; }
/// <summary> /// Performs a dogfight move against the opponent /// </summary> /// <param name="ti">Team on which the ai is registered</param> /// <param name="ai">Character to perform move</param> /// <param name="target">Opponent of the ai</param> public void doDogfightMove(TeamInformation ti, DynamicObject ai, StaticObject target) { if (!this.isObjectRegistered(ai)) return; float radiusToGoBehindTarget = (target.getBoundingSphere().Radius + ai.getBoundingSphere().Radius) * RADIUS_MULTIPLIER_TO_GO_BEHIND_TARGET; Vector3 wpPosition = target.Position + Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Forward) * radiusToGoBehindTarget; Vector3 wpDPosition = target.Position + Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Up) * radiusToGoBehindTarget / RADIUS_FACTOR_TO_GO_ABOVE_TARGET; if (Vector3.Dot(Vector3.Normalize(wpPosition - target.Position), Vector3.Normalize(ai.Position - target.Position)) < DOT_ANGLE_TO_STOP_DOGFIGHT_MOVE || (ai.Position - target.Position).Length() > CHASE_WHEN_FURTHER) { PathInformation fighterPath = objectPaths[ai]; List<Node> waypointList = fighterPath.remainingPath; //we clear the waypoint list and add new waypoints: if (waypointList.Count > 0) { bool shouldAddTopWaypt = (Vector3.Dot(Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Forward), Vector3.Normalize(target.Position - ai.Position)) > 0); if ((wpPosition - waypointList.ElementAt(0).Position).Length() > TARGET_WP_BUFFER || shouldAddTopWaypt) { waypointList.Clear(); if (shouldAddTopWaypt) waypointList.Insert(0, new Node(wpDPosition, -1)); waypointList.Insert(0, new Node(wpPosition, -1)); } } else { if (Vector3.Dot(Vector3.Normalize(Matrix.CreateFromQuaternion(target.rotation).Forward), Vector3.Normalize(target.Position - ai.Position)) > 0) waypointList.Insert(0, new Node(wpDPosition, -1)); waypointList.Insert(0, new Node(wpPosition, -1)); } fighterPath.remainingPath = waypointList; } else //stop navigation (we are behind the target so we can start shooting it) getPath(ai).Clear(); }
/// <summary> /// override for the update method to call on the camera update methods. /// </summary> /// <param name="gt">Game time variable</param> public override void Update(GameTime gt) { // todo add the if statement on the enum for cockpit View if (cameraType.Equals(CurrentCam.Chase)) chaseCamera.update(gt, Position, Matrix.CreateFromQuaternion(rotation)); else fpCamera.update(gt, Position, Matrix.CreateFromQuaternion(rotation), this.getGreatestLength); if (target != null) { if (target is Turret) { if (((Turret)target).Repairing) target = null; } else { if (target.getHealth <= 0) target = null; } } if (target == null) { getNewTarget(); } base.Update(gt); }
/// <summary> /// This tries to get /// </summary> public void getNewTarget() { List<Grid.GridObjectInterface> list = Controller.GameController.getTargets(this); if (list.Count > 0) { for (int i = 0; i < list.Count; ++i) { if (list.ElementAt(i) is StaticObject) { StaticObject obj = (StaticObject)list.ElementAt(i); if (obj.Team != Team.neutral) { if (obj.Team != this.Team) { if (!previousList.Contains(obj)) { previousList.Add(obj); target = obj; return; } } } } } previousList.Clear(); } }
public void registerHitOnBaseOrTurretOrFighters(StaticObject victim, StaticObject shooter) { TeamInformation tiV = getTeam(victim); TeamInformation tiS = getTeam(shooter); if (tiV == null || tiS == null) return; if (tiV != tiS) if (!isTargetMarkedForElimination(shooter, tiV)) if (!isTargetAlreadyBattledByFighters(tiV, shooter)) { if (shooter is playerObject) { if (victim is Fighter || victim is Base) tiV.scrambleQueue.Add(new KeyValuePair<int, StaticObject>(PRIORITY_FOR_ELIMINATING_PLAYER, shooter)); else if (victim is Turret) { float distanceFromTurretToHomeBase = (victim.Position - tiV.teamBase.Position).Length(); if (distanceFromTurretToHomeBase <= DISTANCE_WHEN_TURRET_IS_CLOSE_TO_BASE) tiV.scrambleQueue.Add(new KeyValuePair<int, StaticObject>(PRIORITY_FOR_ELIMINATING_PLAYER, shooter)); } } else if (shooter is Destroyer) { if (victim is Fighter || victim is Base) tiV.scrambleQueue.Add(new KeyValuePair<int, StaticObject>(PRIORITY_FOR_ELIMINATING_DESTROYER, shooter)); else if (victim is Turret) { float distanceFromTurretToHomeBase = (victim.Position - tiV.teamBase.Position).Length(); if (distanceFromTurretToHomeBase <= DISTANCE_WHEN_TURRET_IS_CLOSE_TO_BASE) tiV.scrambleQueue.Add(new KeyValuePair<int, StaticObject>(PRIORITY_FOR_ELIMINATING_DESTROYER, shooter)); } } } }
private int topupAssignedFightersToBattle(TeamInformation ti, StaticObject enemy) { Dictionary<StaticObject, int> numEngagedFightersPerEnemy = countFightersEngagedOnEnemy(ti); int numToScramble = 0; if (enemy is playerObject) numToScramble = FIGHTERS_TO_SCRAMBLE_FOR_PLAYER; else if (enemy is Destroyer) numToScramble = FIGHTERS_TO_SCRAMBLE_FOR_DESTROYER; //if the enemy is already being faught then just top up the fighters when they die off if (numEngagedFightersPerEnemy.Keys.Contains(enemy)) numToScramble -= numEngagedFightersPerEnemy[enemy]; //now get the healthiest fighters and scramble them: if (numToScramble > 0) { PowerDataStructures.PriorityQueue<float, Fighter> healthiestInactiveFighters = getHealthiestFighters(ti, FighterState.FS_IDLE); int numIdleAvailable = healthiestInactiveFighters.Count; //when we have enough fighters available just scramble them if (numIdleAvailable >= numToScramble) { for (int i = 0; i < numToScramble; ++i) ti.fighterBattleList.Add(healthiestInactiveFighters.DequeueValue(), enemy); return numIdleAvailable; } //when we have too few fighters reassign them to more important targets else { //add what we do have: for (int i = 0; i < numIdleAvailable; ++i) ti.fighterBattleList.Add(healthiestInactiveFighters.DequeueValue(), enemy); //now find more fighters and reassign: PowerDataStructures.PriorityQueue<float, Fighter> healthiestActiveFighters = getHealthiestFighters(ti, FighterState.FS_ENGAGED); int numReassigned = 0; foreach (KeyValuePair<float,Fighter> fighter in healthiestActiveFighters) if (getEliminationPriority(ti.fighterBattleList[fighter.Value]) < getEliminationPriority(enemy)) { ti.fighterBattleList.Remove(fighter.Value); ti.fighterBattleList.Add(fighter.Value, enemy); if (numIdleAvailable+(++numReassigned) == numToScramble) break; } return numReassigned+numIdleAvailable; } } else return 0; }
private bool isTargetMarkedForElimination(StaticObject target, TeamInformation ti) { foreach (System.Collections.Generic.KeyValuePair<int, BBN_Game.Objects.StaticObject> pair in ti.scrambleQueue) if (pair.Value == target) return true; return false; }
private bool isTargetAlreadyBattledByFighters(TeamInformation ti, StaticObject target) { return ti.fighterBattleList.Values.Contains(target); }
private TeamInformation getTeam(StaticObject ai) { foreach (TeamInformation ti in infoOnTeams) if (ai.Team == ti.teamId) return ti; return null; }