/// <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(); } }
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; }
/// <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(); }
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 void routePlayerToTurret(TeamInformation ti, Turret turret) { ti.playerObjective = turret; List<GridObjectInterface> neighbouringObjects = this.spatialGrid.checkNeighbouringBlocks(turret); Node closeWaypointToTurret = null; foreach (GridObjectInterface obj in neighbouringObjects) if (obj is Node && (obj.Position - ti.playerObjective.Position).Length() <= GridDataCollection.MAX_CAPTURE_DISTANCE) { closeWaypointToTurret = obj as Node; break; } neighbouringObjects = this.spatialGrid.checkNeighbouringBlocks(ti.teamPlayer); Node closeWaypointToPlayer = null; float minDist = 0; foreach (GridObjectInterface obj in neighbouringObjects) if (obj is Node) { float dist = (obj.Position - ti.teamPlayer.Position).Length(); if (closeWaypointToPlayer == null || minDist > dist) { closeWaypointToPlayer = obj as Node; minDist = dist; } } if (!(closeWaypointToTurret == null || closeWaypointToPlayer == null)) navComputer.setNewPathForRegisteredObject(ti.teamPlayer, closeWaypointToPlayer, closeWaypointToTurret); else { List<Node> path = new List<Node>(); path.Add(new Node(ti.playerObjective.Position + Vector3.Normalize(Matrix.CreateFromQuaternion(ti.playerObjective.rotation).Forward) * (ti.playerObjective.getGreatestLength + ti.teamPlayer.getGreatestLength) * LINE_OF_SIGHT_CLOSE_DIST_MULTIPLYER, -1)); navComputer.objectPaths[ti.teamPlayer].remainingPath = path; } }
private bool isFighterEngagedInBattle(TeamInformation ti, Fighter fi) { return ti.fighterBattleList.Keys.Contains(fi); }
private bool isTargetAlreadyBattledByFighters(TeamInformation ti, StaticObject target) { return ti.fighterBattleList.Values.Contains(target); }
private bool isDestroyerEngaged(TeamInformation ti, Destroyer ds) { if (ti.destroyerBattleList.Keys.Contains(ds)) return true; else return false; }
private Node getRandomPatrolNode(TeamInformation ti) { if (ti.teamOwnedNodes.Count > 0) return ti.teamOwnedNodes.ElementAt(randomizer.Next(0, ti.teamOwnedNodes.Count - 1)); else return null; }
private PowerDataStructures.PriorityQueue<float, Fighter> getHealthiestFighters(TeamInformation ti, FighterState requiredFighterState) { PowerDataStructures.PriorityQueue<float, Fighter> healthiestFighters = new PowerDataStructures.PriorityQueue<float,Fighter>(true); foreach (Fighter fi in ti.teamFighters) if (requiredFighterState == FighterState.FS_IDLE) { if (!isFighterEngagedInBattle(ti,fi)) healthiestFighters.Add(new KeyValuePair<float,Fighter>(fi.getHealth,fi)); } else if (requiredFighterState == FighterState.FS_ENGAGED) { if (!isFighterEngagedInBattle(ti, fi)) healthiestFighters.Add(new KeyValuePair<float, Fighter>(fi.getHealth, fi)); } else if (requiredFighterState == FighterState.FS_DONTCARE) healthiestFighters.Add(new KeyValuePair<float, Fighter>(fi.getHealth, fi)); return healthiestFighters; }
private Dictionary<StaticObject, int> countFightersEngagedOnEnemy(TeamInformation ti) { Dictionary<StaticObject, int> result = new Dictionary<StaticObject, int>(); foreach (StaticObject enemy in ti.fighterBattleList.Values) if (!result.Keys.Contains(enemy)) result.Add(enemy, 1); else result[enemy]++; return result; }
public void registerTeam(TeamInformation ti) { if (!infoOnTeams.Contains(ti)) infoOnTeams.Add(ti); }