//have to add new entry for GL Circle to draw sensor bubbles around taskgroups/populations/missile contacts //CircleElement has the circle in it already, but that might be inappropriate for what I want //SceenElement has the lable properly done. public SensorElement(GLEffect a_oDefaultEffect, Vector3 a_oPosition, float a_fRadius, System.Drawing.Color a_oColor, String LabelText, GameEntity Ent, ComponentTypeTN SType, Sceen ParentSceenArg) : base() { _ParentSceen = ParentSceenArg; _DisplayRadius = a_fRadius; m_oPrimaryPrimitive = new GLCircle(a_oDefaultEffect, a_oPosition, a_fRadius, a_oColor, UIConstants.Textures.DEFAULT_TEXTURE); m_lPrimitives.Add(m_oPrimaryPrimitive); int LabelMid = LabelText.Length / 4; float xAdjust = -LabelMid * (UIConstants.DEFAULT_TEXT_SIZE.X / _ParentSceen.ZoomSclaer); float yAdjust = 10.0f / ParentSceenArg.ZoomSclaer; Vector3 LPos = new Vector3(xAdjust, (a_fRadius + yAdjust), 0.0f); LPos = LPos + a_oPosition; Lable = new GLUtilities.GLFont(a_oDefaultEffect, LPos, UIConstants.DEFAULT_TEXT_SIZE, a_oColor, UIConstants.Textures.DEFAULT_GLFONT2, LabelText); Lable.Size = UIConstants.DEFAULT_TEXT_SIZE / ParentSceenArg.ZoomSclaer; SetActualPosition(a_oPosition); SceenEntity = Ent; _SensorType = SType; }
//have to add new entry for GL Circle to draw sensor bubbles around taskgroups/populations/missile contacts //CircleElement has the circle in it already, but that might be inappropriate for what I want //SceenElement has the lable properly done. public SensorElement(GLEffect a_oDefaultEffect, Vector3 a_oPosition, float a_fRadius, System.Drawing.Color a_oColor, String LabelText, GameEntity Ent, ComponentTypeTN SType, Sceen ParentSceenArg) : base() { _ParentSceen = ParentSceenArg; _DisplayRadius = a_fRadius; m_oPrimaryPrimitive = new GLCircle(a_oDefaultEffect, a_oPosition, a_fRadius, a_oColor, UIConstants.Textures.DEFAULT_TEXTURE); m_lPrimitives.Add(m_oPrimaryPrimitive); int LabelMid = LabelText.Length / 4; float xAdjust = -LabelMid * (UIConstants.DEFAULT_TEXT_SIZE.X / _ParentSceen.ZoomSclaer); float yAdjust = 10.0f / ParentSceenArg.ZoomSclaer; Vector3 LPos = new Vector3(xAdjust, (a_fRadius + yAdjust), 0.0f); LPos = LPos + a_oPosition; Lable = new GLUtilities.GLFont(a_oDefaultEffect, LPos, UIConstants.DEFAULT_TEXT_SIZE, a_oColor, UIConstants.Textures.DEFAULT_GLFONT2, LabelText); Lable.Size = UIConstants.DEFAULT_TEXT_SIZE / ParentSceenArg.ZoomSclaer; SetActualPosition(a_oPosition); SceenEntity = Ent; _SensorType = SType; }
/// <summary> /// ShieldDefTN is the constructor for both regular shield definitions, and absorption shield definitions. /// </summary> /// <param name="ShieldName">Name of the shield.</param> /// <param name="StrTech">Strength/Absorption strength tech level.</param> /// <param name="RegenTech">Regeneration/Radiation tech level.</param> /// <param name="FuelCon">Fuel consumption modifier: 1.0-0.1</param> /// <param name="HS">Size. Regular Shields are always 1 HS, absorption shields may be up to 1000 HS in size(only 1 per ship however.)</param> /// <param name="TypeOfShield">Shield or AbsorptionShield only please.</param> public ShieldDefTN(string ShieldName, int StrTech, int RegenTech, float FuelCon, float HS, ComponentTypeTN TypeOfShield) { Id = Guid.NewGuid(); componentType = TypeOfShield; ShieldStrength = StrTech; ShieldRegen = RegenTech; FuelConsumptionMod = FuelCon; Name = ShieldName; size = HS; if (TypeOfShield == ComponentTypeTN.Shield) { crew = 1; htk = 1; cost = 4 + Constants.ShieldTN.CostBase[ShieldStrength] + Constants.ShieldTN.CostBase[ShieldRegen]; ShieldPool = Constants.ShieldTN.ShieldBase[ShieldStrength]; ShieldGen = Constants.ShieldTN.ShieldBase[ShieldRegen]; ShieldGenPerTick = ShieldGen / 60.0f; } else if (TypeOfShield == ComponentTypeTN.AbsorptionShield) { crew = 3; htk = (byte)Math.Round(size / 4.0f); ShieldPool = Constants.ShieldTN.ShieldBase[ShieldStrength] * 3.0f * size; ShieldGen = Constants.ShieldTN.ShieldBase[ShieldRegen] * 0.5f * size; ShieldGenPerTick = ShieldGen / 12.0f; cost = (decimal)((2.0f * ShieldGen) + (2.0f * ShieldPool)); } minerialsCost = new decimal[Constants.Minerals.NO_OF_MINERIALS]; for (int mineralIterator = 0; mineralIterator < (int)Constants.Minerals.MinerialNames.MinerialCount; mineralIterator++) { minerialsCost[mineralIterator] = 0; } minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.25m; minerialsCost[(int)Constants.Minerals.MinerialNames.Corbomite] = cost * 0.375m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.375m; FuelCostPerHour = 10.0f * ShieldPool * FuelConsumptionMod; isMilitary = true; isObsolete = false; isSalvaged = false; isDivisible = false; isElectronic = false; }
/// <summary> /// ShieldDefTN is the constructor for both regular shield definitions, and absorption shield definitions. /// </summary> /// <param name="ShieldName">Name of the shield.</param> /// <param name="StrTech">Strength/Absorption strength tech level.</param> /// <param name="RegenTech">Regeneration/Radiation tech level.</param> /// <param name="FuelCon">Fuel consumption modifier: 1.0-0.1</param> /// <param name="HS">Size. Regular Shields are always 1 HS, absorption shields may be up to 1000 HS in size(only 1 per ship however.)</param> /// <param name="TypeOfShield">Shield or AbsorptionShield only please.</param> public ShieldDefTN(string ShieldName, int StrTech, int RegenTech, float FuelCon, float HS, ComponentTypeTN TypeOfShield) { Id = Guid.NewGuid(); componentType = TypeOfShield; ShieldStrength = StrTech; ShieldRegen = RegenTech; FuelConsumptionMod = FuelCon; Name = ShieldName; size = HS; if (TypeOfShield == ComponentTypeTN.Shield) { crew = 1; htk = 1; cost = 4 + Constants.ShieldTN.CostBase[ShieldStrength] + Constants.ShieldTN.CostBase[ShieldRegen]; ShieldPool = Constants.ShieldTN.ShieldBase[ShieldStrength]; ShieldGen = Constants.ShieldTN.ShieldBase[ShieldRegen]; ShieldGenPerTick = ShieldGen / 60.0f; } else if (TypeOfShield == ComponentTypeTN.AbsorptionShield) { crew = 3; htk = (byte)Math.Round(size / 4.0f); ShieldPool = Constants.ShieldTN.ShieldBase[ShieldStrength] * 3.0f * size; ShieldGen = Constants.ShieldTN.ShieldBase[ShieldRegen] * 0.5f * size; ShieldGenPerTick = ShieldGen / 12.0f; cost = (decimal)((2.0f * ShieldGen) + (2.0f * ShieldPool)); } minerialsCost = new decimal[Constants.Minerals.NO_OF_MINERIALS]; for (int mineralIterator = 0; mineralIterator < (int)Constants.Minerals.MinerialNames.MinerialCount; mineralIterator++) { minerialsCost[mineralIterator] = 0; } minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.25m; minerialsCost[(int)Constants.Minerals.MinerialNames.Corbomite] = cost * 0.375m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.375m; FuelCostPerHour = 10.0f * ShieldPool * FuelConsumptionMod; isMilitary = true; isObsolete = false; isSalvaged = false; isDivisible = false; isElectronic = false; }
/// <summary> /// Constructor for all beam weapon types. /// </summary> /// <param name="Title">Name of the beam weapon, user entered string, or default string.</param> /// <param name="Type">What type of beam weapon this is, note that componentTypeTN encompasses much more than beam weapon types, don't give those values to this function.</param> /// <param name="SizeTech">Every beam weapon either has a calibre size, except for particle beams, which use warhead strength, and gauss which give a rate of fire. All use this variable.</param> /// <param name="RangeTech">Every beam weapon has a range tech except for plasma carronades which do not have any way to increase range or decrease damage falloff.</param> /// <param name="CapacitorTech">Every beam weapon has a capacitor tech associated with it except gauss. Shotcount tech for gauss.</param> /// <param name="Reduction">Lasers and Gauss both have size reduction capabilities, though with drawbacks for both types: recharge rate and accuracy respectively.</param> public BeamDefTN(String Title, ComponentTypeTN Type, byte SizeTech, byte RangeTech, byte CapacitorTech, float Reduction, MountType MType = MountType.Standard) { #warning function has beam weapon range related magic numbers and others if (Type < ComponentTypeTN.Rail || Type > ComponentTypeTN.AdvParticle) { /// <summary> /// Error, bad ID passed to BeamDefTN. /// </summary> return; } Id = Guid.NewGuid(); componentType = Type; Name = Title; m_oWeaponSizeTech = SizeTech; m_oWeaponRangeTech = RangeTech; m_oWeaponCapacitorTech = CapacitorTech; m_oWeaponCapacitor = Constants.BeamWeaponTN.Capacitor[CapacitorTech]; m_oWMType = MType; m_oShotCount = 1; m_oBaseAccuracy = 1.0f; m_lDamage = new BindingList<ushort>(); int RangeIncrement; switch (componentType) { /// <summary> /// Laser is the the most basic jack of all trade beam weapon. /// </summary> case ComponentTypeTN.Laser: /// <summary> /// I Suspect that size is 3.2cm per HS but am just using a table for now. /// </summary> size = (float)Math.Round(Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech] * Reduction); /// <summary> /// The first entry in the damage table is max damage at point blank(0-10k range) damage. /// </summary> m_lDamage.Add((ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]); /// <summary> /// Have to modify capacitor by size reduction values. /// </summary> if (Reduction == 0.75f) m_oWeaponCapacitor = m_oWeaponCapacitor / 4.0f; else if (Reduction == 0.5f) m_oWeaponCapacitor = m_oWeaponCapacitor / 20.0f; /// <summary> /// Damage, Size, and Range are all modified by spinal mounting: /// </summary> switch (m_oWMType) { case MountType.Spinal: size = (float)Math.Round(size * 1.25f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 1.5f); break; case MountType.AdvancedSpinal: size = (float)Math.Round(size * 1.5f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 2.0f); break; } /// <summary> /// Lasers have the longest range of all beam weapons due to their high damage, normal 10,000km factor and weapon range tech. /// </summary> m_oRange = (float)m_lDamage[0] * 10000.0f * (float)(m_oWeaponRangeTech + 1); /// <summary> /// Lasers require 1 unit of power for every unit of damage that they do. /// </summary> m_oPowerRequirement = m_lDamage[0]; /// <summary> /// Subsequent entries up to Wavelength * 10k do full damage, after that the value is: /// FullDamage * ( Wavelength / RangeIncrement Tick) with a minimum of 1 over range. /// </summary> /// RangeIncrement = (m_oWeaponRangeTech + 1) * m_lDamage[0]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Beam; break; case ComponentTypeTN.AdvLaser: size = (float)Math.Round(Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech] * Reduction); m_lDamage.Add((ushort)Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech]); /// <summary> /// Advanced lasers do more damage per unit of power than regular lasers. /// </summary> m_oPowerRequirement = Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; /// <summary> /// Have to modify capacitor by size reduction values. /// </summary> if (Reduction == 0.75f) m_oWeaponCapacitor = m_oWeaponCapacitor / 4.0f; else if (Reduction == 0.5f) m_oWeaponCapacitor = m_oWeaponCapacitor / 20.0f; /// <summary> /// Damage, Size, and Range are all modified by spinal mounting: /// </summary> switch (MType) { case MountType.Spinal: size = (float)Math.Round(size * 1.25f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 1.5f); m_oPowerRequirement = (ushort)Math.Round((float)m_oPowerRequirement * 1.5f); break; case MountType.AdvancedSpinal: size = (float)Math.Round(size * 1.5f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 2.0f); m_oPowerRequirement = (ushort)Math.Round((float)m_oPowerRequirement * 2.0f); break; } m_oRange = (float)m_lDamage[0] * 10000.0f * (float)(m_oWeaponRangeTech + 1); RangeIncrement = (m_oWeaponRangeTech + 1) * m_lDamage[0]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Beam; break; /// <summary> /// Plasmas are essentially cheaper infared lasers. /// </summary> case ComponentTypeTN.Plasma: m_oWeaponRangeTech = 0; /// <summary> /// I Suspect that size is 3.2cm per HS but am just using a table for now. No reductions for plasma. /// </summary> size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; /// <summary> /// Plasma carronades have the same range as an infared laser of equal size. /// </summary> m_oRange = (float)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech] * 10000.0f * (float)(m_oWeaponRangeTech + 1); /// <summary> /// The first entry in the damage table is max damage at point blank(0-10k range) damage. /// </summary> m_lDamage.Add((ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]); /// <summary> /// Plasmas require 1 unit of power for every unit of damage that they do. /// </summary> m_oPowerRequirement = m_lDamage[0]; /// <summary> /// Subsequent entries up to Wavelength * 10k do full damage, after that the value is: /// FullDamage * ( Wavelength / RangeIncrement Tick) with a minimum of 1 over range. /// </summary> /// RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Plasma; break; case ComponentTypeTN.AdvPlasma: m_oWeaponRangeTech = 0; size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech] * 10000.0f * (float)(m_oWeaponRangeTech + 1); m_lDamage.Add((ushort)Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech]); m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Plasma; break; /// <summary> /// Railguns have a higher damage than lasers of equal size, though it is spread out over many hits. /// Likewise railguns are not suitable for turrets, lastly railguns don't have the full tech progression that lasers have. /// Railguns and especially advanced railguns are also power efficient as far as the damage that they do. /// </summary> case ComponentTypeTN.Rail: m_oShotCount = 4; size = (float)Constants.BeamWeaponTN.RailGunSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 10000.0f * (m_oWeaponRangeTech + 1); m_lDamage.Add((ushort)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]); m_oPowerRequirement = (ushort)(Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 3); RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// Only difference here is 1 more shot. /// </summary> case ComponentTypeTN.AdvRail: m_oShotCount = 5; size = (float)Constants.BeamWeaponTN.RailGunSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 10000.0f * (m_oWeaponRangeTech + 1); m_lDamage.Add((ushort)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]); m_oPowerRequirement = (ushort)(Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 3); RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// Mesons have half the range that lasers have, and only do 1 damage, but always pass through armor and shields. /// </summary> case ComponentTypeTN.Meson: size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech] * 5000.0f * (float)(m_oWeaponRangeTech + 1); m_lDamage.Add(1); m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; RangeIncrement = (((m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]) / 2); for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(1); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Meson; break; /// <summary> /// Microwaves do electronic only damage, though they do triple against shields. this isn't very useful though as they don't do triple normal laser damage vs shields, just 3. /// They share 1/2 range with mesons, but can't be turreted. /// </summary> case ComponentTypeTN.Microwave: size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech] * 5000.0f * (float)(m_oWeaponRangeTech + 1); m_lDamage.Add(1); m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; RangeIncrement = (((m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]) / 2); for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(1); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Microwave; break; /// <summary> /// Particle Beams suffer no range dissipation so will out damage lasers at their maximum range, but are shorter ranged than lasers. /// WeaponSizeTech for particle beams is their warhead strength, not any focal lense size as with lasers. /// </summary> case ComponentTypeTN.Particle: size = (float)Constants.BeamWeaponTN.ParticleSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech] * 10000.0f; m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.ParticlePower[m_oWeaponSizeTech]; m_lDamage.Add(Constants.BeamWeaponTN.ParticleDamage[m_oWeaponSizeTech]); RangeIncrement = Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech]; for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(Constants.BeamWeaponTN.ParticleDamage[m_oWeaponSizeTech]); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// More damage is the only change for advanced particle beams. /// </summary> case ComponentTypeTN.AdvParticle: size = (float)Constants.BeamWeaponTN.ParticleSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech] * 10000.0f; m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.ParticlePower[m_oWeaponSizeTech]; m_lDamage.Add(Constants.BeamWeaponTN.AdvancedParticleDamage[m_oWeaponSizeTech]); RangeIncrement = Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech]; for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(Constants.BeamWeaponTN.AdvancedParticleDamage[m_oWeaponSizeTech]); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// Gauss Cannons differ substantially from other beam weapons. Size is determined directly from a size vs accuracy choice. /// Likewise capacitor refers to shotcount rather than any capacitor technology. /// </summary> case ComponentTypeTN.Gauss: size = Constants.BeamWeaponTN.GaussSize[m_oWeaponSizeTech]; m_oRange = (m_oWeaponRangeTech + 1) * 10000.0f; m_oShotCount = Constants.BeamWeaponTN.GaussShots[CapacitorTech]; m_oBaseAccuracy = Constants.BeamWeaponTN.GaussAccuracy[m_oWeaponSizeTech]; m_oPowerRequirement = 0; m_lDamage.Add(1); RangeIncrement = (m_oWeaponRangeTech + 1); for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(1); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Kinetic; break; } /// <summary> /// Gauss cannons just have to be different. /// </summary> if (componentType != ComponentTypeTN.Gauss) { htk = (byte)(size / 2.0f); crew = (byte)(size * 2.0f); /// <summary> /// This isn't how aurora does cost, I couldn't quite figure that out. seems like it might be a table. /// well in any event cost is simply the hit to kill * weapon tech level + 1 * weapon capacitor tech level + 1. /// </summary> cost = (decimal)((int)htk * (int)(m_oWeaponRangeTech + 1) * (int)(m_oWeaponCapacitor + 1)); m_oROF = (ushort)((ushort)Math.Ceiling((float)((float)m_oPowerRequirement / (float)m_oWeaponCapacitor)) * 5); } else { /// <summary> /// Gauss data here. /// </summary> if (size == 6.0 || size == 5.0 || size == 4.0) htk = 2; else if (size >= 1.0) htk = 1; else htk = 0; crew = (byte)(size * 2.0f); cost = (decimal)((size * 2.0f) * (float)(m_oWeaponRangeTech + 1) * (float)(m_oWeaponCapacitor + 1)); m_oROF = 5; } minerialsCost = new decimal[Constants.Minerals.NO_OF_MINERIALS]; for (int mineralIterator = 0; mineralIterator < (int)Constants.Minerals.MinerialNames.MinerialCount; mineralIterator++) { minerialsCost[mineralIterator] = 0; } switch (componentType) { case ComponentTypeTN.Laser: case ComponentTypeTN.AdvLaser: case ComponentTypeTN.Plasma: case ComponentTypeTN.AdvPlasma: case ComponentTypeTN.Particle: case ComponentTypeTN.AdvParticle: case ComponentTypeTN.Meson: case ComponentTypeTN.Microwave: //20%D 20%B 60%C minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Corundium] = cost * 0.6m; break; case ComponentTypeTN.Rail: case ComponentTypeTN.AdvRail: //20%D 20%B 60%N minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Neutronium] = cost * 0.6m; break; case ComponentTypeTN.Gauss: //100%V minerialsCost[(int)Constants.Minerals.MinerialNames.Vendarite] = cost; break; } isMilitary = true; isObsolete = false; isDivisible = false; isSalvaged = false; isElectronic = false; }
/// <summary> /// Constructor for all beam weapon types. /// </summary> /// <param name="Title">Name of the beam weapon, user entered string, or default string.</param> /// <param name="Type">What type of beam weapon this is, note that componentTypeTN encompasses much more than beam weapon types, don't give those values to this function.</param> /// <param name="SizeTech">Every beam weapon either has a calibre size, except for particle beams, which use warhead strength, and gauss which give a rate of fire. All use this variable.</param> /// <param name="RangeTech">Every beam weapon has a range tech except for plasma carronades which do not have any way to increase range or decrease damage falloff.</param> /// <param name="CapacitorTech">Every beam weapon has a capacitor tech associated with it except gauss. Shotcount tech for gauss.</param> /// <param name="Reduction">Lasers and Gauss both have size reduction capabilities, though with drawbacks for both types: recharge rate and accuracy respectively.</param> public BeamDefTN(String Title, ComponentTypeTN Type, byte SizeTech, byte RangeTech, byte CapacitorTech, float Reduction, MountType MType = MountType.Standard) { #warning function has beam weapon range related magic numbers and others if (Type < ComponentTypeTN.Rail || Type > ComponentTypeTN.AdvParticle) { /// <summary> /// Error, bad ID passed to BeamDefTN. /// </summary> return; } Id = Guid.NewGuid(); componentType = Type; Name = Title; m_oWeaponSizeTech = SizeTech; m_oWeaponRangeTech = RangeTech; m_oWeaponCapacitorTech = CapacitorTech; m_oWeaponCapacitor = Constants.BeamWeaponTN.Capacitor[CapacitorTech]; m_oWMType = MType; m_oShotCount = 1; m_oBaseAccuracy = 1.0f; m_lDamage = new BindingList <ushort>(); int RangeIncrement; switch (componentType) { /// <summary> /// Laser is the the most basic jack of all trade beam weapon. /// </summary> case ComponentTypeTN.Laser: /// <summary> /// I Suspect that size is 3.2cm per HS but am just using a table for now. /// </summary> size = (float)Math.Round(Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech] * Reduction); /// <summary> /// The first entry in the damage table is max damage at point blank(0-10k range) damage. /// </summary> m_lDamage.Add((ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]); /// <summary> /// Have to modify capacitor by size reduction values. /// </summary> if (Reduction == 0.75f) { m_oWeaponCapacitor = m_oWeaponCapacitor / 4.0f; } else if (Reduction == 0.5f) { m_oWeaponCapacitor = m_oWeaponCapacitor / 20.0f; } /// <summary> /// Damage, Size, and Range are all modified by spinal mounting: /// </summary> switch (m_oWMType) { case MountType.Spinal: size = (float)Math.Round(size * 1.25f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 1.5f); break; case MountType.AdvancedSpinal: size = (float)Math.Round(size * 1.5f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 2.0f); break; } /// <summary> /// Lasers have the longest range of all beam weapons due to their high damage, normal 10,000km factor and weapon range tech. /// </summary> m_oRange = (float)m_lDamage[0] * 10000.0f * (float)(m_oWeaponRangeTech + 1); /// <summary> /// Lasers require 1 unit of power for every unit of damage that they do. /// </summary> m_oPowerRequirement = m_lDamage[0]; /// <summary> /// Subsequent entries up to Wavelength * 10k do full damage, after that the value is: /// FullDamage * ( Wavelength / RangeIncrement Tick) with a minimum of 1 over range. /// </summary> /// RangeIncrement = (m_oWeaponRangeTech + 1) * m_lDamage[0]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Beam; break; case ComponentTypeTN.AdvLaser: size = (float)Math.Round(Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech] * Reduction); m_lDamage.Add((ushort)Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech]); /// <summary> /// Advanced lasers do more damage per unit of power than regular lasers. /// </summary> m_oPowerRequirement = Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; /// <summary> /// Have to modify capacitor by size reduction values. /// </summary> if (Reduction == 0.75f) { m_oWeaponCapacitor = m_oWeaponCapacitor / 4.0f; } else if (Reduction == 0.5f) { m_oWeaponCapacitor = m_oWeaponCapacitor / 20.0f; } /// <summary> /// Damage, Size, and Range are all modified by spinal mounting: /// </summary> switch (MType) { case MountType.Spinal: size = (float)Math.Round(size * 1.25f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 1.5f); m_oPowerRequirement = (ushort)Math.Round((float)m_oPowerRequirement * 1.5f); break; case MountType.AdvancedSpinal: size = (float)Math.Round(size * 1.5f); m_lDamage[0] = (ushort)Math.Round((float)m_lDamage[0] * 2.0f); m_oPowerRequirement = (ushort)Math.Round((float)m_oPowerRequirement * 2.0f); break; } m_oRange = (float)m_lDamage[0] * 10000.0f * (float)(m_oWeaponRangeTech + 1); RangeIncrement = (m_oWeaponRangeTech + 1) * m_lDamage[0]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Beam; break; /// <summary> /// Plasmas are essentially cheaper infared lasers. /// </summary> case ComponentTypeTN.Plasma: m_oWeaponRangeTech = 0; /// <summary> /// I Suspect that size is 3.2cm per HS but am just using a table for now. No reductions for plasma. /// </summary> size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; /// <summary> /// Plasma carronades have the same range as an infared laser of equal size. /// </summary> m_oRange = (float)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech] * 10000.0f * (float)(m_oWeaponRangeTech + 1); /// <summary> /// The first entry in the damage table is max damage at point blank(0-10k range) damage. /// </summary> m_lDamage.Add((ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]); /// <summary> /// Plasmas require 1 unit of power for every unit of damage that they do. /// </summary> m_oPowerRequirement = m_lDamage[0]; /// <summary> /// Subsequent entries up to Wavelength * 10k do full damage, after that the value is: /// FullDamage * ( Wavelength / RangeIncrement Tick) with a minimum of 1 over range. /// </summary> /// RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Plasma; break; case ComponentTypeTN.AdvPlasma: m_oWeaponRangeTech = 0; size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech] * 10000.0f * (float)(m_oWeaponRangeTech + 1); m_lDamage.Add((ushort)Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech]); m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.AdvancedLaserDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Plasma; break; /// <summary> /// Railguns have a higher damage than lasers of equal size, though it is spread out over many hits. /// Likewise railguns are not suitable for turrets, lastly railguns don't have the full tech progression that lasers have. /// Railguns and especially advanced railguns are also power efficient as far as the damage that they do. /// </summary> case ComponentTypeTN.Rail: m_oShotCount = 4; size = (float)Constants.BeamWeaponTN.RailGunSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 10000.0f * (m_oWeaponRangeTech + 1); m_lDamage.Add((ushort)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]); m_oPowerRequirement = (ushort)(Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 3); RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// Only difference here is 1 more shot. /// </summary> case ComponentTypeTN.AdvRail: m_oShotCount = 5; size = (float)Constants.BeamWeaponTN.RailGunSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 10000.0f * (m_oWeaponRangeTech + 1); m_lDamage.Add((ushort)Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]); m_oPowerRequirement = (ushort)(Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech] * 3); RangeIncrement = (m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.RailGunDamage[m_oWeaponSizeTech]; CalcDamageTable(RangeIncrement); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// Mesons have half the range that lasers have, and only do 1 damage, but always pass through armor and shields. /// </summary> case ComponentTypeTN.Meson: size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech] * 5000.0f * (float)(m_oWeaponRangeTech + 1); m_lDamage.Add(1); m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; RangeIncrement = (((m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]) / 2); for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(1); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Meson; break; /// <summary> /// Microwaves do electronic only damage, though they do triple against shields. this isn't very useful though as they don't do triple normal laser damage vs shields, just 3. /// They share 1/2 range with mesons, but can't be turreted. /// </summary> case ComponentTypeTN.Microwave: size = (float)Constants.BeamWeaponTN.LaserSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech] * 5000.0f * (float)(m_oWeaponRangeTech + 1); m_lDamage.Add(1); m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]; RangeIncrement = (((m_oWeaponRangeTech + 1) * Constants.BeamWeaponTN.LaserDamage[m_oWeaponSizeTech]) / 2); for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(1); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Microwave; break; /// <summary> /// Particle Beams suffer no range dissipation so will out damage lasers at their maximum range, but are shorter ranged than lasers. /// WeaponSizeTech for particle beams is their warhead strength, not any focal lense size as with lasers. /// </summary> case ComponentTypeTN.Particle: size = (float)Constants.BeamWeaponTN.ParticleSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech] * 10000.0f; m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.ParticlePower[m_oWeaponSizeTech]; m_lDamage.Add(Constants.BeamWeaponTN.ParticleDamage[m_oWeaponSizeTech]); RangeIncrement = Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech]; for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(Constants.BeamWeaponTN.ParticleDamage[m_oWeaponSizeTech]); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// More damage is the only change for advanced particle beams. /// </summary> case ComponentTypeTN.AdvParticle: size = (float)Constants.BeamWeaponTN.ParticleSize[m_oWeaponSizeTech]; m_oRange = (float)Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech] * 10000.0f; m_oPowerRequirement = (ushort)Constants.BeamWeaponTN.ParticlePower[m_oWeaponSizeTech]; m_lDamage.Add(Constants.BeamWeaponTN.AdvancedParticleDamage[m_oWeaponSizeTech]); RangeIncrement = Constants.BeamWeaponTN.ParticleRange[m_oWeaponRangeTech]; for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(Constants.BeamWeaponTN.AdvancedParticleDamage[m_oWeaponSizeTech]); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Kinetic; break; /// <summary> /// Gauss Cannons differ substantially from other beam weapons. Size is determined directly from a size vs accuracy choice. /// Likewise capacitor refers to shotcount rather than any capacitor technology. /// </summary> case ComponentTypeTN.Gauss: size = Constants.BeamWeaponTN.GaussSize[m_oWeaponSizeTech]; m_oRange = (m_oWeaponRangeTech + 1) * 10000.0f; m_oShotCount = Constants.BeamWeaponTN.GaussShots[CapacitorTech]; m_oBaseAccuracy = Constants.BeamWeaponTN.GaussAccuracy[m_oWeaponSizeTech]; m_oPowerRequirement = 0; m_lDamage.Add(1); RangeIncrement = (m_oWeaponRangeTech + 1); for (int loop = 1; loop < RangeIncrement; loop++) { m_lDamage.Add(1); } m_lDamage.Add(0); m_oDamageType = DamageTypeTN.Kinetic; break; } /// <summary> /// Gauss cannons just have to be different. /// </summary> if (componentType != ComponentTypeTN.Gauss) { htk = (byte)(size / 2.0f); crew = (byte)(size * 2.0f); /// <summary> /// This isn't how aurora does cost, I couldn't quite figure that out. seems like it might be a table. /// well in any event cost is simply the hit to kill * weapon tech level + 1 * weapon capacitor tech level + 1. /// </summary> cost = (decimal)((int)htk * (int)(m_oWeaponRangeTech + 1) * (int)(m_oWeaponCapacitor + 1)); m_oROF = (ushort)((ushort)Math.Ceiling((float)((float)m_oPowerRequirement / (float)m_oWeaponCapacitor)) * 5); } else { /// <summary> /// Gauss data here. /// </summary> if (size == 6.0 || size == 5.0 || size == 4.0) { htk = 2; } else if (size >= 1.0) { htk = 1; } else { htk = 0; } crew = (byte)(size * 2.0f); cost = (decimal)((size * 2.0f) * (float)(m_oWeaponRangeTech + 1) * (float)(m_oWeaponCapacitor + 1)); m_oROF = 5; } minerialsCost = new decimal[Constants.Minerals.NO_OF_MINERIALS]; for (int mineralIterator = 0; mineralIterator < (int)Constants.Minerals.MinerialNames.MinerialCount; mineralIterator++) { minerialsCost[mineralIterator] = 0; } switch (componentType) { case ComponentTypeTN.Laser: case ComponentTypeTN.AdvLaser: case ComponentTypeTN.Plasma: case ComponentTypeTN.AdvPlasma: case ComponentTypeTN.Particle: case ComponentTypeTN.AdvParticle: case ComponentTypeTN.Meson: case ComponentTypeTN.Microwave: //20%D 20%B 60%C minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Corundium] = cost * 0.6m; break; case ComponentTypeTN.Rail: case ComponentTypeTN.AdvRail: //20%D 20%B 60%N minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.2m; minerialsCost[(int)Constants.Minerals.MinerialNames.Neutronium] = cost * 0.6m; break; case ComponentTypeTN.Gauss: //100%V minerialsCost[(int)Constants.Minerals.MinerialNames.Vendarite] = cost; break; } isMilitary = true; isObsolete = false; isDivisible = false; isSalvaged = false; isElectronic = false; }
/// <summary> /// Initializes this basic component. /// </summary> /// <param name="Title">Name which will be displayed to the user, they don't choose the names of these particular components however.</param> /// <param name="ComponentSize">Size of the component. this will determine crew capacity, fuel capacity, engineering percentage, and htk in addition to being merely size.</param> /// <param name="ComponentCrew">Crew requirement of the component, fuel tanks won't require any, orbital habitats will require a lot.</param> /// <param name="ComponentCost">Cost requirement of the component, mineral costs have yet to be done though those are just a percentage of total cost.</param> /// <param name="GeneralComponentType">What type of component is this? see the enum in ComponentTN.cs for a list.</param> public GeneralComponentDefTN(string Title, float ComponentSize, byte ComponentCrew, decimal ComponentCost, ComponentTypeTN GeneralComponentType) { Id = Guid.NewGuid(); Name = Title; size = ComponentSize; crew = ComponentCrew; cost = ComponentCost; componentType = GeneralComponentType; minerialsCost = new decimal[Constants.Minerals.NO_OF_MINERIALS]; for (int mineralIterator = 0; mineralIterator < (int)Constants.Minerals.MinerialNames.MinerialCount; mineralIterator++) { minerialsCost[mineralIterator] = 0; } switch (componentType) { case ComponentTypeTN.Crew: //25% Duranium 75% Mercassium minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.25m; minerialsCost[(int)Constants.Minerals.MinerialNames.Mercassium] = cost * 0.75m; break; case ComponentTypeTN.Fuel: //50% Duranium 50% Boronide minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.50m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.50m; break; case ComponentTypeTN.Engineering: //100% Duranium minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost; break; case ComponentTypeTN.Bridge: //50% Duranium, 50% corbomite minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.50m; minerialsCost[(int)Constants.Minerals.MinerialNames.Corbomite] = cost * 0.50m; break; //case ComponentTypeTN.FlagBridge: 50% corbomite, 50% Uridium //case ComponentTypeTN.MaintenanceBay: 50% Duranium, 50% Neutronium //case ComponentTypeTN.OrbitalHabitat: 25% Duranium, 25% Boronide, 50% Mercassium //case ComponentTypeTN.RecFacility: 20% Duranium, 20% Tritanium, 60% Boronide //case ComponentTypeTN.DamageControl: 50% Duranium, 25% Neutronium, 25% Uridium } isDivisible = false; if (componentType <= ComponentTypeTN.MaintenanceBay) { if (size < 1.0f) { htk = 0; } else { htk = 1; } } else if (componentType == ComponentTypeTN.FlagBridge || componentType == ComponentTypeTN.DamageControl) { htk = 2; } else if (componentType == ComponentTypeTN.OrbitalHabitat || componentType == ComponentTypeTN.RecFacility) { htk = 25; isDivisible = true; } isMilitary = false; isObsolete = false; isSalvaged = false; isElectronic = false; }
/// <summary> /// This function returns the cost of repairing the specified component based on the data given to the damage control queue. /// </summary> /// <param name="ID">Id of component in general ship component list.</param> /// <param name="CType">type of component.</param> /// <returns>cost of said component.</returns> public decimal GetDamagedComponentsRepairCost(int ID, ComponentTypeTN CType) { switch (CType) { case ComponentTypeTN.Crew: return CrewQuarters[ShipComponents[ID].componentIndex].genCompDef.cost; case ComponentTypeTN.Fuel: return FuelTanks[ShipComponents[ID].componentIndex].genCompDef.cost; case ComponentTypeTN.Engineering: return EngineeringBays[ShipComponents[ID].componentIndex].genCompDef.cost; case ComponentTypeTN.Bridge: case ComponentTypeTN.MaintenanceBay: case ComponentTypeTN.FlagBridge: case ComponentTypeTN.DamageControl: case ComponentTypeTN.OrbitalHabitat: case ComponentTypeTN.RecFacility: return OtherComponents[ShipComponents[ID].componentIndex].genCompDef.cost; case ComponentTypeTN.Engine: /// <summary> /// All engines have to be the same, so engine 0 is used for these for convienience. /// </summary> return ShipEngine[0].engineDef.cost; case ComponentTypeTN.PassiveSensor: return ShipPSensor[ShipComponents[ID].componentIndex].pSensorDef.cost; case ComponentTypeTN.ActiveSensor: return ShipASensor[ShipComponents[ID].componentIndex].aSensorDef.cost; case ComponentTypeTN.CargoHold: return ShipCargo[ShipComponents[ID].componentIndex].cargoDef.cost; case ComponentTypeTN.CargoHandlingSystem: return ShipCHS[ShipComponents[ID].componentIndex].cargoHandleDef.cost; case ComponentTypeTN.CryoStorage: return ShipColony[ShipComponents[ID].componentIndex].colonyDef.cost; case ComponentTypeTN.BeamFireControl: return ShipBFC[ShipComponents[ID].componentIndex].beamFireControlDef.cost; case ComponentTypeTN.Rail: case ComponentTypeTN.Gauss: case ComponentTypeTN.Plasma: case ComponentTypeTN.Laser: case ComponentTypeTN.Meson: case ComponentTypeTN.Microwave: case ComponentTypeTN.Particle: case ComponentTypeTN.AdvRail: case ComponentTypeTN.AdvLaser: case ComponentTypeTN.AdvPlasma: case ComponentTypeTN.AdvParticle: return ShipBeam[ShipComponents[ID].componentIndex].beamDef.cost; case ComponentTypeTN.Reactor: return ShipReactor[ShipComponents[ID].componentIndex].reactorDef.cost; case ComponentTypeTN.Shield: return ShipShield[ShipComponents[ID].componentIndex].shieldDef.cost; case ComponentTypeTN.AbsorptionShield: return ShipShield[ShipComponents[ID].componentIndex].shieldDef.cost; case ComponentTypeTN.MissileLauncher: return ShipMLaunchers[ShipComponents[ID].componentIndex].missileLauncherDef.cost; case ComponentTypeTN.Magazine: return ShipMagazines[ShipComponents[ID].componentIndex].magazineDef.cost; case ComponentTypeTN.MissileFireControl: return ShipMFC[ShipComponents[ID].componentIndex].mFCSensorDef.cost; case ComponentTypeTN.CIWS: return ShipCIWS[ShipComponents[ID].componentIndex].cIWSDef.cost; case ComponentTypeTN.Turret: return ShipTurret[ShipComponents[ID].componentIndex].turretDef.cost; case ComponentTypeTN.JumpEngine: return ShipJumpEngine[ShipComponents[ID].componentIndex].jumpEngineDef.cost; } return 0.0m; }
public void RepairComponent(ComponentTypeTN Type, int ComponentIndex) { /// <summary> /// Subtract MSPs in damage control function, not necessary here. /// </summary> ShipComponents[ComponentIndex].isDestroyed = false; DestroyedComponents.Remove((ushort)ComponentIndex); switch (Type) { case ComponentTypeTN.Crew: SpareBerths = SpareBerths + (int)(CrewQuarters[ShipComponents[ComponentIndex].componentIndex].genCompDef.size / ShipClass.TonsPerMan); break; case ComponentTypeTN.Fuel: CurrentFuelCapacity = CurrentFuelCapacity + (FuelTanks[ShipComponents[ComponentIndex].componentIndex].genCompDef.size * 50000.0f); break; case ComponentTypeTN.Engineering: float MSP = EngineeringBays[ShipComponents[ComponentIndex].componentIndex].genCompDef.size; CurrentMSPCapacity = CurrentMSPCapacity + (int)((float)ShipClass.BuildPointCost * ((MSP / ShipClass.SizeHS) / 0.08f)); CurrentDamageControlRating = CurrentDamageControlRating + 1; break; /// <summary> /// Nothing special is done for these yet. /// </summary> case ComponentTypeTN.Bridge: break; case ComponentTypeTN.MaintenanceBay: break; case ComponentTypeTN.FlagBridge: break; case ComponentTypeTN.DamageControl: break; case ComponentTypeTN.OrbitalHabitat: break; case ComponentTypeTN.RecFacility: break; case ComponentTypeTN.Engine: /// <summary> /// All engines have to be the same, so engine 0 is used for these for convienience. /// </summary> CurrentMaxEnginePower = CurrentMaxEnginePower + (int)Math.Round(ShipEngine[0].engineDef.enginePower); CurrentMaxThermalSignature = CurrentMaxThermalSignature + (int)Math.Round(ShipEngine[0].engineDef.thermalSignature); CurrentMaxFuelUsePerHour = CurrentMaxFuelUsePerHour + ShipEngine[0].engineDef.fuelUsePerHour; if (CurrentMaxEnginePower == 0) { /// <summary> /// This is a very bad error I think. /// hopefully it should never happen. /// </summary> CurrentMaxSpeed = 1; CurrentMaxThermalSignature = 1; #if LOG4NET_ENABLED #warning faction messagelog this? logger.Debug("CurrentMaxEnginePower was 0 AFTER engine repair. oops. see Ship.cs RepairComponent()"); #endif } else CurrentMaxSpeed = (int)((1000.0f / (float)ShipClass.TotalCrossSection) * (float)CurrentMaxEnginePower); int speedMin = 0; for (int loop = 0; loop < ShipsTaskGroup.Ships.Count; loop++) { if (ShipsTaskGroup.Ships[loop].CurrentMaxSpeed > speedMin) speedMin = CurrentMaxSpeed; } int oldThermal = CurrentThermalSignature; if (speedMin > ShipsTaskGroup.CurrentSpeed) { ShipsTaskGroup.CurrentSpeed = speedMin; for (int loop = 0; loop < ShipsTaskGroup.Ships.Count; loop++) { ShipsTaskGroup.Ships[loop].SetSpeed(ShipsTaskGroup.CurrentSpeed); } } if (oldThermal != CurrentThermalSignature) ShipsTaskGroup.SortShipBySignature(ThermalList, ShipsTaskGroup.ThermalSortList, 0); break; case ComponentTypeTN.PassiveSensor: if (ShipPSensor[ShipComponents[ComponentIndex].componentIndex].pSensorDef.thermalOrEM == PassiveSensorType.EM) { if (ShipPSensor[ShipComponents[ComponentIndex].componentIndex].pSensorDef.rating > ShipsTaskGroup.BestEM.pSensorDef.rating) { ShipsTaskGroup.BestEM = ShipPSensor[ShipComponents[ComponentIndex].componentIndex]; ShipsTaskGroup.BestEMCount = 1; } else if (ShipPSensor[ShipComponents[ComponentIndex].componentIndex].pSensorDef.rating == ShipsTaskGroup.BestEM.pSensorDef.rating) { ShipsTaskGroup.BestEMCount++; } } else { if (ShipPSensor[ShipComponents[ComponentIndex].componentIndex].pSensorDef.rating > ShipsTaskGroup.BestThermal.pSensorDef.rating) { ShipsTaskGroup.BestThermal = ShipPSensor[ShipComponents[ComponentIndex].componentIndex]; ShipsTaskGroup.BestThermalCount = 1; } else if (ShipPSensor[ShipComponents[ComponentIndex].componentIndex].pSensorDef.rating == ShipsTaskGroup.BestThermal.pSensorDef.rating) { ShipsTaskGroup.BestThermalCount++; } } break; /// <summary> /// Nothing special for these yet. /// </summary> case ComponentTypeTN.ActiveSensor: break; case ComponentTypeTN.CargoHold: break; case ComponentTypeTN.CargoHandlingSystem: CurrentTractorMultiplier = CurrentTractorMultiplier + ShipCHS[ShipComponents[ComponentIndex].componentIndex].cargoHandleDef.tractorMultiplier; break; /// <summary> /// Nothing special for these yet. Weapon links won't be restored. /// </summary> case ComponentTypeTN.CryoStorage: break; case ComponentTypeTN.BeamFireControl: break; case ComponentTypeTN.Rail: case ComponentTypeTN.Gauss: case ComponentTypeTN.Plasma: case ComponentTypeTN.Laser: case ComponentTypeTN.Meson: case ComponentTypeTN.Microwave: case ComponentTypeTN.Particle: case ComponentTypeTN.AdvRail: case ComponentTypeTN.AdvLaser: case ComponentTypeTN.AdvPlasma: case ComponentTypeTN.AdvParticle: break; case ComponentTypeTN.Reactor: CurrentPowerGen = CurrentPowerGen + (int)(Math.Round(ShipReactor[ShipComponents[ComponentIndex].componentIndex].reactorDef.powerGen)); break; /// <summary> /// For shields I will preserve ShieldIsActive as is, but set the other values up on component repair. /// </summary. case ComponentTypeTN.Shield: CurrentShieldPoolMax = CurrentShieldPoolMax + ShipShield[ShipComponents[ComponentIndex].componentIndex].shieldDef.shieldPool; CurrentShieldGen = CurrentShieldGen + ShipShield[ShipComponents[ComponentIndex].componentIndex].shieldDef.shieldGenPerTick; CurrentShieldFuelUse = CurrentShieldFuelUse + (ShipShield[ShipComponents[ComponentIndex].componentIndex].shieldDef.fuelCostPerHour / 720.0f); if (ShieldIsActive == true) { CurrentEMSignature = CurrentEMSignature + (int)(ShipShield[ShipComponents[ComponentIndex].componentIndex].shieldDef.shieldPool * 30.0f); ShipsTaskGroup.SortShipBySignature(EMList, ShipsTaskGroup.EMSortList, 1); } break; case ComponentTypeTN.AbsorptionShield: CurrentShieldPoolMax = ShipClass.TotalShieldPool; CurrentShieldGen = ShipClass.TotalShieldGenPerTick; CurrentShieldFuelUse = ShipClass.TotalShieldFuelCostPerTick; if (ShieldIsActive == true) { CurrentEMSignature = CurrentEMSignature + (int)(ShipShield[ShipComponents[ComponentIndex].componentIndex].shieldDef.shieldPool * 30.0f); ShipsTaskGroup.SortShipBySignature(EMList, ShipsTaskGroup.EMSortList, 1); } break; case ComponentTypeTN.MissileLauncher: CurrentLauncherMagCapacityMax = CurrentLauncherMagCapacityMax + ShipMLaunchers[ShipComponents[ComponentIndex].componentIndex].missileLauncherDef.launchMaxSize; CurrentMagazineCapacityMax = CurrentMagazineCapacityMax + ShipMLaunchers[ShipComponents[ComponentIndex].componentIndex].missileLauncherDef.launchMaxSize; break; case ComponentTypeTN.Magazine: CurrentMagazineMagCapacityMax = CurrentMagazineMagCapacityMax + ShipMagazines[ShipComponents[ComponentIndex].componentIndex].magazineDef.capacity; CurrentMagazineCapacityMax = CurrentMagazineCapacityMax + ShipMagazines[ShipComponents[ComponentIndex].componentIndex].magazineDef.capacity; break; case ComponentTypeTN.MissileFireControl: break; case ComponentTypeTN.CIWS: break; case ComponentTypeTN.Turret: break; case ComponentTypeTN.JumpEngine: break; } }
/// <summary> /// Destroy component handles destroying individual components of a ship, updating the ships data, and taskgroup data as needed. /// crew destruction and logging remain to be done. /// </summary> /// <param name="Type">Type of component destroyed</param> /// <param name="ComponentListDefIndex">Where in the shipClass.ListOfComponentDefs this component resides</param> /// <param name="Damage">How much damage is to be applied in the attempt to destroy the component</param> /// <param name="ComponentIndex">Which component specifically.</param> /// <param name="DacRNG">Current RNG kludge</param> /// <returns>Damage remaining after component destruction, or special message indicating no component to destroy(-1)/ship is totally destroyed(-2)</returns> public int DestroyComponent(ComponentTypeTN Type, int ComponentListDefIndex, int Damage, int ComponentIndex, Random DacRNG) { if (Damage >= ShipHTK) return -2; int ID = ComponentDefIndex[ComponentListDefIndex] + ComponentIndex; if (ShipComponents[ID].isDestroyed == true) { return -1; } int DamageReturn = -1; if (ShipClass.ListOfComponentDefs[ComponentListDefIndex].htk == 0) { ShipComponents[ID].isDestroyed = true; DamageReturn = Damage; } else if (ShipClass.ListOfComponentDefs[ComponentListDefIndex].htk != 0) { if (ShipClass.ListOfComponentDefs[ComponentListDefIndex].htk <= Damage) { ShipComponents[ID].isDestroyed = true; DamageReturn = ShipClass.ListOfComponentDefs[ComponentListDefIndex].htk; } else { int htkTest = DacRNG.Next(1, ShipClass.ListOfComponentDefs[ComponentListDefIndex].htk); if (htkTest == ShipClass.ListOfComponentDefs[ComponentListDefIndex].htk) { ShipComponents[ID].isDestroyed = true; DamageReturn = Damage; } else { /// <summary> /// All damage was absorbed by the component without it being destroyed. /// </summary> DamageReturn = Damage; return DamageReturn; } } } /// <summary> /// Copy the component over to the destroyed components list and decrement the ships remaining HTK value. DestroyedComponents.Add((ushort)ID); DestroyedComponentsType.Add(Type); ShipHTK = ShipHTK - ShipClass.ListOfComponentDefs[ComponentListDefIndex].htk; /// <summary> /// Do Crew destruction here at some point. /// </summary> switch (Type) { /// <summary> /// To Do: /// put everything in the log. /// </summary> case ComponentTypeTN.Crew: SpareBerths = SpareBerths - (int)(CrewQuarters[ShipComponents[ID].componentIndex].genCompDef.size / ShipClass.TonsPerMan); break; case ComponentTypeTN.Fuel: float Fuel = FuelTanks[ShipComponents[ID].componentIndex].genCompDef.size * 50000.0f; float FuelPercentage = Fuel / ShipClass.TotalFuelCapacity; float FuelLoss = FuelPercentage * CurrentFuel; CurrentFuel = CurrentFuel - FuelLoss; CurrentFuelCapacity = CurrentFuelCapacity - Fuel; break; case ComponentTypeTN.Engineering: float MSP = EngineeringBays[ShipComponents[ID].componentIndex].genCompDef.size; float MSPPercentage = MSP / ShipClass.TotalMSPCapacity; float MSPLoss = MSPPercentage * CurrentMSP; CurrentMSP = CurrentMSP - (int)MSPLoss; CurrentMSPCapacity = CurrentMSPCapacity - (int)((float)ShipClass.BuildPointCost * ((MSP / ShipClass.SizeHS) / 0.08f)); CurrentDamageControlRating = CurrentDamageControlRating - 1; break; /// <summary> /// Nothing special for these yet. /// </summary> case ComponentTypeTN.Bridge: break; case ComponentTypeTN.MaintenanceBay: break; case ComponentTypeTN.FlagBridge: break; case ComponentTypeTN.DamageControl: break; case ComponentTypeTN.OrbitalHabitat: break; case ComponentTypeTN.RecFacility: break; case ComponentTypeTN.Engine: /// <summary> /// All engines have to be the same, so engine 0 is used for these for convienience. /// </summary> CurrentMaxEnginePower = CurrentMaxEnginePower - (int)Math.Round(ShipEngine[0].engineDef.enginePower); CurrentMaxThermalSignature = CurrentMaxThermalSignature - (int)Math.Round(ShipEngine[0].engineDef.thermalSignature); CurrentMaxFuelUsePerHour = CurrentMaxFuelUsePerHour - ShipEngine[0].engineDef.fuelUsePerHour; if (CurrentMaxEnginePower != 0) CurrentMaxSpeed = (int)((1000.0f / ((float)ShipClass.TotalCrossSection) * (float)CurrentMaxEnginePower)); else { CurrentMaxSpeed = 1; CurrentMaxThermalSignature = 1; //it shouldn't be 0 either. } int oldThermal = CurrentThermalSignature; if (ShipsTaskGroup.CurrentSpeed > CurrentMaxSpeed) { ShipsTaskGroup.CurrentSpeed = CurrentMaxSpeed; for (int loop = 0; loop < ShipsTaskGroup.Ships.Count; loop++) { ShipsTaskGroup.Ships[loop].SetSpeed(ShipsTaskGroup.CurrentSpeed); } } if (oldThermal != CurrentThermalSignature) ShipsTaskGroup.SortShipBySignature(ThermalList, ShipsTaskGroup.ThermalSortList, 0); int ExpTest = DacRNG.Next(1, 100); if (ExpTest < ShipEngine[0].engineDef.expRisk) { /// <summary> /// *** Do secondary damage here. *** /// </summary> /// SecondaryExplosion(SecondaryType.Engine,ShipEngine[0].engineDef.enginePower); } break; case ComponentTypeTN.PassiveSensor: /// <summary> /// Performance could be improved here by storing a sorted linked list of all passive sensors if need be. /// I don't believe that sensor destruction events will be common enough to necessitate that however. /// </summary> if (ShipPSensor[ShipComponents[ID].componentIndex].pSensorDef.thermalOrEM == PassiveSensorType.EM) { if (ShipPSensor[ShipComponents[ID].componentIndex].pSensorDef.rating == ShipsTaskGroup.BestEM.pSensorDef.rating) { ShipsTaskGroup.BestEMCount--; if (ShipsTaskGroup.BestEMCount == 0) { for (int loop = 0; loop < ShipsTaskGroup.Ships.Count; loop++) { for (int loop2 = 0; loop2 < ShipsTaskGroup.Ships[loop].ShipPSensor.Count; loop2++) { if (ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].pSensorDef.thermalOrEM == PassiveSensorType.EM && ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].isDestroyed == false) { if (ShipsTaskGroup.BestEMCount == 0 || ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].pSensorDef.rating > ShipsTaskGroup.BestEM.pSensorDef.rating) { ShipsTaskGroup.BestEM = ShipsTaskGroup.Ships[loop].ShipPSensor[loop2]; ShipsTaskGroup.BestEMCount = 1; } else if (ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].pSensorDef.rating == ShipsTaskGroup.BestEM.pSensorDef.rating) { ShipsTaskGroup.BestEMCount++; } } } } } } } else { if (ShipPSensor[ShipComponents[ID].componentIndex].pSensorDef.rating == ShipsTaskGroup.BestThermal.pSensorDef.rating) { ShipsTaskGroup.BestThermalCount--; if (ShipsTaskGroup.BestThermalCount == 0) { for (int loop = 0; loop < ShipsTaskGroup.Ships.Count; loop++) { for (int loop2 = 0; loop2 < ShipsTaskGroup.Ships[loop].ShipPSensor.Count; loop2++) { if (ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].pSensorDef.thermalOrEM == PassiveSensorType.Thermal && ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].isDestroyed == false) { if (ShipsTaskGroup.BestThermalCount == 0 || ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].pSensorDef.rating > ShipsTaskGroup.BestThermal.pSensorDef.rating) { ShipsTaskGroup.BestThermal = ShipsTaskGroup.Ships[loop].ShipPSensor[loop2]; ShipsTaskGroup.BestThermalCount = 1; } else if (ShipsTaskGroup.Ships[loop].ShipPSensor[loop2].pSensorDef.rating == ShipsTaskGroup.BestThermal.pSensorDef.rating) { ShipsTaskGroup.BestThermalCount++; } } } } } } } break; case ComponentTypeTN.ActiveSensor: /// <summary> /// Luckily this function already takes care of active sensors being deactivated and removed from the sort lists. /// </summary> ShipsTaskGroup.SetActiveSensor(ShipsTaskGroup.Ships.IndexOf(this), ShipComponents[ID].componentIndex, false); break; case ComponentTypeTN.CargoHold: /// <summary> /// Cargo should be destroyed here. /// </summary> break; case ComponentTypeTN.CargoHandlingSystem: CurrentTractorMultiplier = CurrentTractorMultiplier - ShipCHS[ShipComponents[ID].componentIndex].cargoHandleDef.tractorMultiplier; break; case ComponentTypeTN.CryoStorage: /// <summary> /// Colonists in stasis or lifeboat rescuees should be destroyed here. /// </summary> break; /// <summary> /// The fire control open fire list has to be updated. /// </summary> case ComponentTypeTN.BeamFireControl: UnlinkAllWeapons(ShipBFC[ShipComponents[ID].componentIndex]); ShipBFC[ShipComponents[ID].componentIndex].openFire = false; if (ShipsFaction.OpenFireFC.ContainsKey(ShipComponents[ID]) == true) { ShipsFaction.OpenFireFC.Remove(ShipComponents[ID]); ShipsFaction.OpenFireFCType.Remove(ShipComponents[ID]); } break; case ComponentTypeTN.Rail: case ComponentTypeTN.Gauss: case ComponentTypeTN.Plasma: case ComponentTypeTN.Laser: case ComponentTypeTN.Meson: case ComponentTypeTN.Microwave: case ComponentTypeTN.Particle: case ComponentTypeTN.AdvRail: case ComponentTypeTN.AdvLaser: case ComponentTypeTN.AdvPlasma: case ComponentTypeTN.AdvParticle: UnlinkWeapon(ShipBeam[ShipComponents[ID].componentIndex]); ShipBeam[ShipComponents[ID].componentIndex].currentCapacitor = 0; break; case ComponentTypeTN.Reactor: CurrentPowerGen = CurrentPowerGen - (int)(Math.Round(ShipReactor[ShipComponents[ID].componentIndex].reactorDef.powerGen)); ExpTest = DacRNG.Next(1, 100); if (ExpTest < ShipReactor[ShipComponents[ID].componentIndex].reactorDef.expRisk) { /// <summary> /// *** Do secondary damage here. *** /// </summary> /// SecondaryExplosion(SecondaryType.Reactor,ShipReactor[ShipComponents[ID].componentIndex].reactorDef.powerGen); } break; /// <summary> /// For shields I will preserve ShieldIsActive as is, but set the other values down on component destruction. /// </summary. case ComponentTypeTN.Shield: CurrentShieldPoolMax = CurrentShieldPoolMax - ShipShield[ShipComponents[ID].componentIndex].shieldDef.shieldPool; CurrentShieldGen = CurrentShieldGen - ShipShield[ShipComponents[ID].componentIndex].shieldDef.shieldGenPerTick; CurrentShieldFuelUse = CurrentShieldFuelUse - (ShipShield[ShipComponents[ID].componentIndex].shieldDef.fuelCostPerHour / 720.0f); /// <summary> /// In the event of meson damage/mixed meson and non-meson damage: /// </summary> if (CurrentShieldPool != 0.0f && CurrentShieldPool > CurrentShieldPoolMax) CurrentShieldPool = CurrentShieldPoolMax; if (ShieldIsActive == true) { CurrentEMSignature = CurrentEMSignature - (int)(ShipShield[ShipComponents[ID].componentIndex].shieldDef.shieldPool * 30.0f); ShipsTaskGroup.SortShipBySignature(EMList, ShipsTaskGroup.EMSortList, 1); } break; case ComponentTypeTN.AbsorptionShield: CurrentShieldPool = 0.0f; CurrentShieldPoolMax = 0.0f; CurrentShieldGen = 0.0f; CurrentShieldFuelUse = 0.0f; if (ShieldIsActive == true) { CurrentEMSignature = CurrentEMSignature - (int)(ShipShield[ShipComponents[ID].componentIndex].shieldDef.shieldPool * 30.0f); ShipsTaskGroup.SortShipBySignature(EMList, ShipsTaskGroup.EMSortList, 1); } break; case ComponentTypeTN.MissileLauncher: /// <summary> /// If the ship has loaded ordnance then figuring out which one to destroy is simple: /// </summary> if (ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance != null) { if (ShipOrdnance.ContainsKey(ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance) == true) { ShipOrdnance[ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance] = ShipOrdnance[ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance] - 1; if (ShipOrdnance[ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance] == 0) { ShipOrdnance.Remove(ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance); } else if (ShipOrdnance[ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance] < 0) { #if LOG4NET_ENABLED #warning faction messagelog this? String Entry = String.Format("Ship ordnance subtraction below 0 on ship {0} due to launcher destruction.", this.Name); logger.Debug(Entry); #endif } } else { /// <summary> /// This condition could arise because all such missiles have been fired. Check the total ship ordnance vs magazine capacity to decide if another missile should be destroyed. /// </summary> if (CurrentMagazineCapacity > CurrentMagazineMagCapacityMax) { foreach (KeyValuePair<OrdnanceDefTN, int> pair in ShipOrdnance) { if (ShipOrdnance[pair.Key] > 0) { ShipOrdnance[pair.Key] = ShipOrdnance[pair.Key] - 1; if (ShipOrdnance[pair.Key] == 0) { ShipOrdnance.Remove(pair.Key); } break; } else { #if LOG4NET_ENABLED #warning faction messagelog this? String Entry = String.Format("Ship {0} has ship ordnance in quantities of zero from somewhere.", this.Name); logger.Debug(Entry); #endif } } } } ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance = null; } else { /// <summary> /// This condition could arise because all such missiles have been fired. Check the total ship ordnance vs magazine capacity to decide if another missile should be destroyed. /// This else is included twice due to paranoia over the possibility that loadedOrdnance = null /// </summary> if (CurrentMagazineCapacity > CurrentMagazineMagCapacityMax) { foreach (KeyValuePair<OrdnanceDefTN, int> pair in ShipOrdnance) { if (ShipOrdnance[pair.Key] > 0) { ShipOrdnance[pair.Key] = ShipOrdnance[pair.Key] - 1; if (ShipOrdnance[pair.Key] == 0) { ShipOrdnance.Remove(pair.Key); } break; } else { #if LOG4NET_ENABLED #warning faction messagelog this? String Entry = String.Format("Ship {0} has ship ordnance in quantities of zero from somewhere.", this.Name); logger.Debug(Entry); #endif } } } } CurrentLauncherMagCapacityMax = CurrentLauncherMagCapacityMax - ShipMLaunchers[ShipComponents[ID].componentIndex].missileLauncherDef.launchMaxSize; CurrentMagazineCapacityMax = CurrentMagazineCapacityMax - ShipMLaunchers[ShipComponents[ID].componentIndex].missileLauncherDef.launchMaxSize; CurrentMagazineCapacity = CurrentMagazineCapacity - (int)Math.Ceiling(ShipMLaunchers[ShipComponents[ID].componentIndex].loadedOrdnance.size); ShipMLaunchers[ShipComponents[ID].componentIndex].ClearMFC(); break; case ComponentTypeTN.Magazine: /// <summary> /// There must be missiles in the magazines rather than all of them being in the launch tubes, or the mags could be totally empty /// </summary> int WarheadTotal = 0; if (CurrentMagazineCapacity > CurrentLauncherMagCapacityMax) { /// <summary> /// Total percentage of all magazine space divided by all space total on the ship for missiles(includes launch tubes). /// </summary> float MagPercentage = (CurrentMagazineMagCapacityMax / CurrentMagazineCapacityMax); /// <summary> /// Percentage of total magazine space this one magazine represents. /// </summary> float ThisMagPercentage = (ShipMagazines[ShipComponents[ID].componentIndex].magazineDef.capacity / CurrentMagazineMagCapacityMax) * MagPercentage; /// <summary> /// Counter for missiles destroyed. /// </summary> int TempCapTotal = 0; /// <summary> /// Temporary key list, will be removing these from shipordnance when done. /// </summary> Dictionary<OrdnanceDefTN,int> TempKeyList = new Dictionary<OrdnanceDefTN,int>(); /// <summary> /// loop through all ordnance and determine the loadbalanced count of missiles that would be in this magazine. /// if ShipOrdnance is empty, this does not run. /// </summary> foreach (KeyValuePair<OrdnanceDefTN, int> pair in ShipOrdnance) { int Total = (int)Math.Ceiling(pair.Key.size) * pair.Value; int AmtInThisMag = (int)Math.Ceiling(ThisMagPercentage * Total); TempCapTotal = TempCapTotal + AmtInThisMag; TempKeyList.Add(pair.Key, AmtInThisMag); WarheadTotal = WarheadTotal + pair.Key.warhead; /// <summary> /// Some mags will have a little more than total cap, and some will have a little less than total cap because of how this could work out. /// </summary> if (TempCapTotal >= ShipMagazines[ShipComponents[ID].componentIndex].magazineDef.capacity) break; } /// <summary> /// I have to subtract values elsewhere because it was giving me some crap about "Collection was modified; enumeration operation may not execute" /// Atleast I hope this fixes the issue. /// </summary> if (TempKeyList.Count != 0) { foreach (KeyValuePair<OrdnanceDefTN,int> pair in TempKeyList) { ShipOrdnance[pair.Key] = ShipOrdnance[pair.Key] - pair.Value; if (ShipOrdnance[pair.Key] <= 0) { if (ShipOrdnance[pair.Key] < 0) { #if LOG4NET_ENABLED #warning faction messagelog this? logger.Debug("Ship ordnance key value inexplicably reduced below zero on magazine destruction."); #endif } ShipOrdnance.Remove(pair.Key); } } } } CurrentMagazineCapacityMax = CurrentMagazineCapacityMax - ShipMagazines[ShipComponents[ID].componentIndex].magazineDef.capacity; CurrentMagazineMagCapacityMax = CurrentMagazineMagCapacityMax - ShipMagazines[ShipComponents[ID].componentIndex].magazineDef.capacity; ExpTest = DacRNG.Next(1, 100); if (ExpTest < ShipMagazines[ShipComponents[ID].componentIndex].magazineDef.expRisk) { /// <summary> /// *** Do secondary damage here. *** /// </summary> /// SecondaryExplosion(SecondaryType.Magazine,WarheadTotal); } break; case ComponentTypeTN.MissileFireControl: ShipMFC[ShipComponents[ID].componentIndex].ClearAllWeapons(); ShipMFC[ShipComponents[ID].componentIndex].ClearAllMissiles(); ShipMFC[ShipComponents[ID].componentIndex].openFire = false; if (ShipsFaction.OpenFireFC.ContainsKey(ShipComponents[ID]) == true) { ShipsFaction.OpenFireFC.Remove(ShipComponents[ID]); ShipsFaction.OpenFireFCType.Remove(ShipComponents[ID]); } break; case ComponentTypeTN.CIWS: /// <summary> /// Do nothing for CIWS. /// </summary> break; case ComponentTypeTN.Turret: UnlinkWeapon(ShipTurret[ShipComponents[ID].componentIndex]); ShipTurret[ShipComponents[ID].componentIndex].currentCapacitor = 0; break; case ComponentTypeTN.JumpEngine: /// <summary> /// Nothing special needs to be done to ship in this case. /// </summary> break; } return DamageReturn; }
/// <summary> /// Initializes this basic component. /// </summary> /// <param name="Title">Name which will be displayed to the user, they don't choose the names of these particular components however.</param> /// <param name="ComponentSize">Size of the component. this will determine crew capacity, fuel capacity, engineering percentage, and htk in addition to being merely size.</param> /// <param name="ComponentCrew">Crew requirement of the component, fuel tanks won't require any, orbital habitats will require a lot.</param> /// <param name="ComponentCost">Cost requirement of the component, mineral costs have yet to be done though those are just a percentage of total cost.</param> /// <param name="GeneralComponentType">What type of component is this? see the enum in ComponentTN.cs for a list.</param> public GeneralComponentDefTN(string Title, float ComponentSize, byte ComponentCrew, decimal ComponentCost, ComponentTypeTN GeneralComponentType) { Id = Guid.NewGuid(); Name = Title; size = ComponentSize; crew = ComponentCrew; cost = ComponentCost; componentType = GeneralComponentType; minerialsCost = new decimal[Constants.Minerals.NO_OF_MINERIALS]; for (int mineralIterator = 0; mineralIterator < (int)Constants.Minerals.MinerialNames.MinerialCount; mineralIterator++) { minerialsCost[mineralIterator] = 0; } switch (componentType) { case ComponentTypeTN.Crew: //25% Duranium 75% Mercassium minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.25m; minerialsCost[(int)Constants.Minerals.MinerialNames.Mercassium] = cost * 0.75m; break; case ComponentTypeTN.Fuel: //50% Duranium 50% Boronide minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.50m; minerialsCost[(int)Constants.Minerals.MinerialNames.Boronide] = cost * 0.50m; break; case ComponentTypeTN.Engineering: //100% Duranium minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost; break; case ComponentTypeTN.Bridge: //50% Duranium, 50% corbomite minerialsCost[(int)Constants.Minerals.MinerialNames.Duranium] = cost * 0.50m; minerialsCost[(int)Constants.Minerals.MinerialNames.Corbomite] = cost * 0.50m; break; //case ComponentTypeTN.FlagBridge: 50% corbomite, 50% Uridium //case ComponentTypeTN.MaintenanceBay: 50% Duranium, 50% Neutronium //case ComponentTypeTN.OrbitalHabitat: 25% Duranium, 25% Boronide, 50% Mercassium //case ComponentTypeTN.RecFacility: 20% Duranium, 20% Tritanium, 60% Boronide //case ComponentTypeTN.DamageControl: 50% Duranium, 25% Neutronium, 25% Uridium } isDivisible = false; if (componentType <= ComponentTypeTN.MaintenanceBay) { if (size < 1.0f) htk = 0; else htk = 1; } else if (componentType == ComponentTypeTN.FlagBridge || componentType == ComponentTypeTN.DamageControl) { htk = 2; } else if (componentType == ComponentTypeTN.OrbitalHabitat || componentType == ComponentTypeTN.RecFacility) { htk = 25; isDivisible = true; } isMilitary = false; isObsolete = false; isSalvaged = false; isElectronic = false; }