/// <summary> /// Fire Weapons spawns new missiles groups or adds missiles to existing ones. /// </summary> /// <param name="TG">Taskgroup this MFC is in.</param> /// <param name="FiredFrom">Ship these missiles were fired from.</param> /// <returns>If missiles were fired at all from this MFC. true = atleast 1 missile(and therefore missile group, false = no missiles.</returns> public bool FireWeapons(TaskGroupTN TG, ShipTN FiredFrom) { bool retv = false; if (m_oTarget != null) { /// <summary> /// Just a temporary variable for this function. /// </summary> BindingList <OrdnanceGroupTN> LocalMissileGroups = new BindingList <OrdnanceGroupTN>(); foreach (MissileLauncherTN LaunchTube in m_lLinkedWeapons) { if (LaunchTube.isDestroyed == false && LaunchTube.loadTime == 0 && LaunchTube.loadedOrdnance != null) { if (FiredFrom.ShipOrdnance.ContainsKey(LaunchTube.loadedOrdnance) == true) { OrdnanceTN newMissile = new OrdnanceTN(this, LaunchTube.loadedOrdnance, FiredFrom); /// <summary> /// Create a new missile group /// </summary> if (LocalMissileGroups.Count == 0) { OrdnanceGroupTN newMissileGroup = new OrdnanceGroupTN(TG, newMissile); LocalMissileGroups.Add(newMissileGroup); TG.TaskGroupFaction.MissileGroups.Add(newMissileGroup); } /// <summary> /// An existing missile group may be useable. /// </summary> else { bool foundGroup = false; foreach (OrdnanceGroupTN OrdGroup in LocalMissileGroups) { /// <summary> /// All Missile groups should be composed of just 1 type of missile for convienence. if (OrdGroup.missiles[0].missileDef.Id == LaunchTube.loadedOrdnance.Id) { OrdGroup.AddMissile(newMissile); foundGroup = true; break; } } /// <summary> /// Have to create a new missile group after all. /// </summary> if (foundGroup == false) { OrdnanceGroupTN newMissileGroup = new OrdnanceGroupTN(TG, newMissile); LocalMissileGroups.Add(newMissileGroup); TG.TaskGroupFaction.MissileGroups.Add(newMissileGroup); } } /// <summary> /// Decrement the loaded ordnance count, and remove the type entirely if this was the last one. /// </summary> FiredFrom.ShipOrdnance[LaunchTube.loadedOrdnance] = FiredFrom.ShipOrdnance[LaunchTube.loadedOrdnance] - 1; if (FiredFrom.ShipOrdnance[LaunchTube.loadedOrdnance] == 0) { FiredFrom.ShipOrdnance.Remove(LaunchTube.loadedOrdnance); } /// <summary> /// Set the launch tube cooldown time as a missile was just fired from it. /// </summary> LaunchTube.loadTime = LaunchTube.missileLauncherDef.rateOfFire; /// <summary> /// return that a missile was launched. /// </summary> retv = true; } else { String Msg = String.Format("No ordnance {0} on ship {1} is available for Launch Tube {2}", LaunchTube.Name, FiredFrom.Name, LaunchTube.Name); MessageEntry newMessage = new MessageEntry(MessageEntry.MessageType.FiringNoAvailableOrdnance, TG.Contact.Position.System, TG.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Msg); TG.TaskGroupFaction.MessageLog.Add(newMessage); } } else if (LaunchTube.isDestroyed == true) { String Msg = String.Format("Destroyed launch tube {0} is still attached to {1}'s MFC", LaunchTube.Name, FiredFrom.Name); MessageEntry newMessage = new MessageEntry(MessageEntry.MessageType.Error, TG.Contact.Position.System, TG.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Msg); TG.TaskGroupFaction.MessageLog.Add(newMessage); } else if (LaunchTube.loadedOrdnance == null) { String Msg = String.Format("No loaded ordnance for launch tube {0} on ship {1}", LaunchTube.Name, FiredFrom.Name); MessageEntry newMessage = new MessageEntry(MessageEntry.MessageType.FiringNoLoadedOrdnance, TG.Contact.Position.System, TG.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Msg); TG.TaskGroupFaction.MessageLog.Add(newMessage); } } return(retv); } else { return(false); } }
/// <summary> /// Fire this MFC in point defense mode. /// </summary> /// <param name="TG">Taskgroup the MFC is in</param> /// <param name="FiredFrom">Ship the MFC is on</param> /// <param name="Target">Target of point defense fire.</param> /// <param name="MissilesToFire">Number of missiles to fire at it</param> /// <returns></returns> public int FireWeaponsPD(TaskGroupTN TG, ShipTN FiredFrom, OrdnanceGroupTN Target, int MissilesToFire) { /// <summary> /// simple stupid sanity check. /// </summary> if (MissilesToFire == 0) { return(0); } int LaunchCount = 0; /// <summary> /// Just a temporary variable for this function. /// </summary> BindingList <OrdnanceGroupTN> LocalMissileGroups = new BindingList <OrdnanceGroupTN>(); foreach (MissileLauncherTN LaunchTube in m_lLinkedWeapons) //int loop = 0; loop < LinkedWeapons.Count; loop++) { if (LaunchTube.isDestroyed == false && LaunchTube.loadTime == 0 && LaunchTube.loadedOrdnance != null) { if (FiredFrom.ShipOrdnance.ContainsKey(LaunchTube.loadedOrdnance) == true) { OrdnanceTN newMissile = new OrdnanceTN(this, LaunchTube.loadedOrdnance, FiredFrom); /// <summary> /// Point defense does not go by MFC targetting. have to add target here. /// </summary> newMissile.target = new TargetTN(Target); LaunchCount++; /// <summary> /// Create a new missile group /// </summary> if (LocalMissileGroups.Count == 0) { OrdnanceGroupTN newMissileGroup = new OrdnanceGroupTN(TG, newMissile); LocalMissileGroups.Add(newMissileGroup); TG.TaskGroupFaction.MissileGroups.Add(newMissileGroup); /// <summary> /// Add this ordnance group to the ord groups targetting list for the intended target missile group. /// This is only necessary here as Manually fired MFC missiles are connected to their MFC. /// </summary> Target.ordGroupsTargetting.Add(newMissileGroup); } /// <summary> /// An existing missile group may be useable. /// </summary> else { bool foundGroup = false; foreach (OrdnanceGroupTN OrdGroup in LocalMissileGroups) { /// <summary> /// All Missile groups should be composed of just 1 type of missile for convienence. if (OrdGroup.missiles[0].missileDef.Id == LaunchTube.loadedOrdnance.Id) { OrdGroup.AddMissile(newMissile); foundGroup = true; break; } } /// <summary> /// Have to create a new missile group after all. /// </summary> if (foundGroup == false) { OrdnanceGroupTN newMissileGroup = new OrdnanceGroupTN(TG, newMissile); LocalMissileGroups.Add(newMissileGroup); TG.TaskGroupFaction.MissileGroups.Add(newMissileGroup); /// <summary> /// Add this ordnance group to the ord groups targetting list for the intended target missile group. /// This is only necessary here as Manually fired MFC missiles are connected to their MFC. /// </summary> Target.ordGroupsTargetting.Add(newMissileGroup); } } /// <summary> /// Decrement the loaded ordnance count, and remove the type entirely if this was the last one. /// </summary> FiredFrom.ShipOrdnance[LaunchTube.loadedOrdnance] = FiredFrom.ShipOrdnance[LaunchTube.loadedOrdnance] - 1; if (FiredFrom.ShipOrdnance[LaunchTube.loadedOrdnance] == 0) { FiredFrom.ShipOrdnance.Remove(LaunchTube.loadedOrdnance); } /// <summary> /// Set the launch tube cooldown time as a missile was just fired from it. /// </summary> LaunchTube.loadTime = LaunchTube.missileLauncherDef.rateOfFire; if (LaunchCount == MissilesToFire) { break; } } else { String Msg = String.Format("No ordnance {0} on ship {1} is available for Launch Tube {2} in PD Mode", LaunchTube.Name, FiredFrom.Name, LaunchTube.Name); MessageEntry newMessage = new MessageEntry(MessageEntry.MessageType.FiringNoAvailableOrdnance, TG.Contact.Position.System, TG.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Msg); TG.TaskGroupFaction.MessageLog.Add(newMessage); } } else if (LaunchTube.isDestroyed == true) { String Msg = String.Format("Destroyed launch tube {0} is still attached to {1}'s MFC in PD Mode", LaunchTube.Name, FiredFrom.Name); MessageEntry newMessage = new MessageEntry(MessageEntry.MessageType.Error, TG.Contact.Position.System, TG.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Msg); TG.TaskGroupFaction.MessageLog.Add(newMessage); } else if (LaunchTube.loadedOrdnance == null) { String Msg = String.Format("No loaded ordnance for launch tube {0} on ship {1} in PD Mode", LaunchTube.Name, FiredFrom.Name); MessageEntry newMessage = new MessageEntry(MessageEntry.MessageType.FiringNoLoadedOrdnance, TG.Contact.Position.System, TG.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Msg); TG.TaskGroupFaction.MessageLog.Add(newMessage); } } return(LaunchCount); }
/// <summary> /// Final defensive fire scans through all potential FCs that could fire defensively on the incoming missile to see if it is intercepeted. /// All PD enabled FCs will attempt to shoot down this missile except ones from the same faction, as this missile is practically right on top of said FC. /// In other words allied/neutral status isn't taken into account. /// </summary> /// <param name="P">Faction list</param> /// <param name="Missile">Missile to try to intercept</param> /// <param name="RNG">Random Number Generator</param> /// <returns>Whether the missile has been intercepted</returns> public static bool FinalDefensiveFire(BindingList <Faction> P, OrdnanceTN Missile, Random RNG) { bool Intercept = false; StarSystem CurrentSystem = Missile.missileGroup.contact.Position.System; float PointBlank = 10000.0f / (float)Constants.Units.KM_PER_AU; /// <summary> /// loop through every faction. /// </summary> foreach (Faction faction in P) { /// <summary> /// Is the current faction different from the missile group faction, and does the faction have a detected contacts list for the current system? /// </summary> if (faction != Missile.missileGroup.ordnanceGroupFaction && faction.DetectedContactLists.ContainsKey(CurrentSystem) == true) { /// <summary> /// Is the Missile group in this detected contact list? /// </summary> if (faction.DetectedContactLists[CurrentSystem].DetectedMissileContacts.ContainsKey(Missile.missileGroup) == true) { /// <summary> /// Is the detection an active detection? /// </summary> if (faction.DetectedContactLists[CurrentSystem].DetectedMissileContacts[Missile.missileGroup].active == true) { /// <summary> /// Does this faction have any point defense enabled FCs in this system? /// </summary> if (faction.PointDefense.ContainsKey(CurrentSystem) == true) { /// <summary> /// loop through all the possible PD enabled FC. /// </summary> foreach (KeyValuePair <ComponentTN, ShipTN> pair in faction.PointDefense[CurrentSystem].PointDefenseFC) { ShipTN Ship = pair.Value; /// <summary> /// Ship jump sickness will prevent point defense from operating. /// </summary> if (Ship.IsJumpSick()) { continue; } /// <summary> /// Only want BFCs in FDF mode for now. /// </summary> if (faction.PointDefense[CurrentSystem].PointDefenseType[pair.Key] == false && pair.Value.ShipBFC[pair.Key.componentIndex].pDState == PointDefenseState.FinalDefensiveFire) { BeamFireControlTN ShipBeamFC = pair.Value.ShipBFC[pair.Key.componentIndex]; /// <summary> /// Do a distance check on pair.Value vs the missile itself. if that checks out to be less than 10k km(or equal to zero), then /// check to see if the FC can shoot down said missile. This should never be run before a sensor sweep /// </summary> float dist = -1; /// <summary> /// dist is in AU. /// </summary> Missile.missileGroup.contact.DistTable.GetDistance(Ship.ShipsTaskGroup.Contact, out dist); /// <summary> /// if distance is less than the 10k km threshold attempt to intercept at Point blank range. /// </summary> if (dist < PointBlank) { /// <summary> /// Finally intercept the target. /// </summary> bool WF = false; Intercept = ShipBeamFC.InterceptTarget(RNG, 0, Missile, Ship.ShipsFaction, Ship.ShipsTaskGroup.Contact, Ship, out WF); /// <summary> /// Add this ship to the weapon recharge list since it has fired. This is done here in Sim, or for FDF_Self in Ship.cs /// </summary> if (WF == true) { if (faction.RechargeList.ContainsKey(Ship) == true) { /// <summary> /// If our recharge value does not have Recharge beams in it(bitflag 2 for now), then add it. /// </summary> if ((faction.RechargeList[pair.Value] & (int)Faction.RechargeStatus.Weapons) != (int)Faction.RechargeStatus.Weapons) { faction.RechargeList[pair.Value] = (faction.RechargeList[pair.Value] + (int)Faction.RechargeStatus.Weapons); } } else { faction.RechargeList.Add(pair.Value, (int)Faction.RechargeStatus.Weapons); } } /// <summary> /// break out of the first foreach loop. /// </summary> if (Intercept == true) { break; } } } } } } } } /// <summary> /// now break out of the faction loop as this missile has been shot down. /// </summary> if (Intercept == true) { break; } } return(Intercept); }