static void evaluateWeaponAttackOnVehicle(float expectedDamage, Weapon w, ref DamageExpectationRecord damageExpectationRecord, Vector3 attackerPosition, Vehicle targetVehicle, Vector3 targetPosition, Quaternion targetRotation) { // use hit table to figure out where this will go Dictionary <VehicleChassisLocations, float> locations = GetLocationDictionary(attackerPosition, targetVehicle, targetPosition, targetRotation); foreach (KeyValuePair <VehicleChassisLocations, float> locKVP in locations) { VehicleChassisLocations loc = locKVP.Key; float probability = locKVP.Value; DamageExpectationRecord locRecord = new DamageExpectationRecord(); damageExpectationRecord.AddChildRecord(probability, locRecord); float existingArmor = targetVehicle.ArmorForLocation((int)loc); float armorThatWillBeRemoved = Mathf.Min(existingArmor, expectedDamage); float damageRemaining = expectedDamage - existingArmor; locRecord.AddVehicleArmorDamage(armorThatWillBeRemoved, loc); if (damageRemaining > 0) { // some goes in to the structure float currentStructure = targetVehicle.GetCurrentStructure(loc); float structureDamage = Mathf.Min(damageRemaining, currentStructure); //float damageAfterStructure = damageRemaining - structureDamage; locRecord.AddVehicleStructureDamage(structureDamage, loc); } } }
// 0-19 == 1-20 = left side -> 20 // 20-39 == 21-40 = right side -> 20 // 40-83 == 41-85 = front / rear -> 45 // 84-99 == 85-100 = turret -> 15 public static VehicleChassisLocations GetRandomVehicleLocation() { VehicleChassisLocations location = VehicleChassisLocations.Front; bool isFront = Mod.Random.Next(0, 100) < 80; int locationIdx = Mod.Random.Next(0, 100); if (locationIdx <= 19) { location = VehicleChassisLocations.Left; } else if (locationIdx <= 39) { location = VehicleChassisLocations.Right; } else if (locationIdx <= 83) { location = isFront ? VehicleChassisLocations.Front : VehicleChassisLocations.Rear; } else if (locationIdx <= 99) { location = VehicleChassisLocations.Turret; } Mod.Log.Trace?.Write($" - Returning random location: {location}"); return(location); }
public static void RecordVehicleDamage(Vehicle __instance, VehicleChassisLocations vLoc, float totalDamage) { if (vLoc == VehicleChassisLocations.None || vLoc == VehicleChassisLocations.Invalid) { return; } RecordUnitDamage(vLoc.ToString(), totalDamage, __instance.GetCurrentArmor(vLoc), __instance.GetCurrentStructure(vLoc)); }
public static void LogVehicleHit(VehicleChassisLocations __result, Dictionary <VehicleChassisLocations, int> hitTable, float randomRoll, VehicleChassisLocations bonusLocation, float bonusLocationMultiplier) { LogHitSequence(__result, randomRoll, bonusLocation, bonusLocationMultiplier, TryGet(hitTable, VehicleChassisLocations.Turret) + Separator + TryGet(hitTable, VehicleChassisLocations.Front) + Separator + TryGet(hitTable, VehicleChassisLocations.Left) + Separator + TryGet(hitTable, VehicleChassisLocations.Right) + Separator + TryGet(hitTable, VehicleChassisLocations.Rear) + FillBlanks(3)); }
public void AddVehicleArmorDamage(float damage, VehicleChassisLocations loc) { float existingDamage = 0.0f; if (vehicleArmorLocationDictionary.ContainsKey(loc)) { existingDamage = vehicleArmorLocationDictionary[loc]; } vehicleArmorLocationDictionary[loc] = existingDamage + damage; }
public static void LogVehicleDamage(Vehicle __instance, VehicleChassisLocations vLoc) { try { if (vLoc == VehicleChassisLocations.None || vLoc == VehicleChassisLocations.Invalid) { return; } LogActorDamage(__instance.GetCurrentArmor(vLoc), __instance.GetCurrentStructure(vLoc)); } catch (Exception ex) { Error(ex); } }
public RepairRecord() { InnerStructure = 0f; Armor = 0f; Components = 0; TurnsSinceDamage = 1; MechStructureLocations = new ChassisLocations[0]; MechArmorLocations = new ArmorLocation[0]; VehicleLocations = new VehicleChassisLocations[0]; AffectInstalledLocation = false; repairTrigger = new RepairTrigger(); }
internal static void applyStructureStatDamage( Vehicle vehicle, VehicleChassisLocations location, float damage, WeaponHitInfo hitInfo ) { try { if (!ComponentExplosionsFeature.IsInternalExplosion) { return; } var properties = ComponentExplosionsFeature.Shared.GetCASEProperties(vehicle, (int)location); if (properties?.MaximumDamage == null) { return; } var directDamage = Mathf.Min(damage, properties.MaximumDamage.Value); var backDamage = damage - directDamage; Control.Logger.Debug?.Log($"reducing structure damage from {damage} to {directDamage} in {location}"); damage = directDamage; if (backDamage <= 0) { return; } vehicle.PublishFloatieMessage("EXPLOSION REDIRECTED"); var armorLocation = VehicleChassisLocations.Rear; var armor = vehicle.GetCurrentArmor(armorLocation); if (armor <= 0) { return; } var armorDamage = Mathf.Min(backDamage, armor); Control.Logger.Debug?.Log($"added blowout armor damage {armorDamage} to {armorLocation}"); vehicle.applyArmorStatDamage(armorLocation, armorDamage, hitInfo); } catch (Exception e) { Control.Logger.Error.Log(e); } finally { vehicle.applyStructureStatDamage(location, damage, hitInfo); } }
internal static float FixMultiplier(VehicleChassisLocations location, float multiplier) { if (location == VehicleChassisLocations.None) { return(0); } if (VehicleCalledShotMultiplier != 1) { multiplier *= VehicleCalledShotMultiplier; } // ClusterChanceNeverMultiplyHead does not apply to Vehicle return(multiplier); }
private static void ShowDamageFloatie(Vehicle vehicle, VehicleChassisLocations location, float damage, string sourceGUID) { if (vehicle != null && vehicle.GameRep != null) { Vector3 vector = vehicle.GameRep.GetHitPosition((int)location) + UnityEngine.Random.insideUnitSphere * 5f; FloatieMessage.MessageNature nature = vehicle.GetCurrentArmor(location) > 0f ? FloatieMessage.MessageNature.ArmorDamage : FloatieMessage.MessageNature.StructureDamage; FloatieMessage message = new FloatieMessage(sourceGUID, vehicle.GUID, $"{damage}", SharedState.Combat.Constants.CombatUIConstants.floatieSizeMedium, nature, vector.x, vector.y, vector.z); SharedState.Combat.MessageCenter.PublishMessage(message); } }
public float GetVehicleStructureDamageForLocation(VehicleChassisLocations loc) { float dmg = 0.0f; if (vehicleChassisLocationDictionary.ContainsKey(loc)) { dmg = vehicleChassisLocationDictionary[loc]; } for (int childIndex = 0; childIndex < children.Count; ++childIndex) { ChildWithProbability c = children[childIndex]; dmg += c.DamageExpectationRecord.GetVehicleStructureDamageForLocation(loc) * c.Probability; } return(dmg); }
public static ChassisLocations FakeVehicleLocation(this VehicleChassisLocations loc) { switch (loc) { case VehicleChassisLocations.Front: return(ChassisLocations.LeftArm); case VehicleChassisLocations.Rear: return(ChassisLocations.RightArm); case VehicleChassisLocations.Turret: return(ChassisLocations.Head); case VehicleChassisLocations.Left: return(ChassisLocations.LeftLeg); case VehicleChassisLocations.Right: return(ChassisLocations.RightLeg); default: return(ChassisLocations.None); } }
internal static float GetCurrentArmor( Vehicle vehicle, VehicleChassisLocations location ) { try { if (ComponentExplosionsFeature.IsInternalExplosion) { return(0); } } catch (Exception e) { Control.mod.Logger.LogError(e); } return(vehicle.GetCurrentArmor(location)); }
public static bool OverrideHUDVehicleCalledShotPercent(ref string __result, VehicleChassisLocations location, VehicleChassisLocations targetedLocation) { try { Dictionary <VehicleChassisLocations, int> hitTable = Combat.HitLocation.GetVehicleHitTable(AttackDirection); if (CacheNeedRefresh(hitTable, (int)targetedLocation)) { HitTableTotalWeight = SumWeight(hitTable, targetedLocation, FixMultiplier(targetedLocation, ActorCalledShotBonus), scale); } int local = TryGet(hitTable, location) * scale; if (location == targetedLocation) { local = (int)(local * FixMultiplier(targetedLocation, ActorCalledShotBonus)); } __result = FineTuneAndFormat(hitTable, location, local, Settings.ShowRealVehicleCalledShotChance); return(false); } catch (Exception ex) { return(Error(ex)); } }
public static VehicleChassisLocations GetSwarmLocationForVehicle() { int randomIdx = Mod.Random.Next(0, Mod.Config.Melee.Swarm.VehicleLocationsTotalWeight); int currentIdx = 0; VehicleChassisLocations selectedLocation = VehicleChassisLocations.Rear; foreach (KeyValuePair <VehicleChassisLocations, int> kvp in Mod.Config.Melee.Swarm.VehicleLocations) { if (randomIdx <= currentIdx + kvp.Value) { Mod.Log.Debug?.Write($"randomIdx: {randomIdx} is <= currentIdx: {currentIdx} + weight: {kvp.Value}, using location: {kvp.Key}"); selectedLocation = kvp.Key; break; } else { currentIdx += kvp.Value; } } Mod.Log.Debug?.Write($"Returning randomly selected swarm location: {selectedLocation}"); return(selectedLocation); }
public static void Postfix(Vehicle __instance, VehicleChassisLocations location, float damage, WeaponHitInfo hitInfo) { Mod.Log.Trace("V:ASSD - entered."); if (ModState.BreachCheck == 0f) { return; } // nothing to do if (hitInfo.attackSequenceId != ModState.BreachAttackId) { Mod.Log.Error("INCOHERENT ATTACK SEQUENCE- SKIPPING!"); return; } Mod.Log.Debug($" --- Location: {location} needs breach check."); if (ModState.BreachHitsVehicle.ContainsKey(location)) { ModState.BreachHitsVehicle[location]++; } else { ModState.BreachHitsVehicle.Add(location, 1); } }
public static void Postfix(Vehicle __instance, VehicleChassisLocations location, float damage, WeaponHitInfo hitInfo) { Mod.Log.Trace?.Write("V:ASSD - entered."); if (ModState.BreachCheck == 0f || ModState.BreachAttackId == ModState.NO_ATTACK_SEQUENCE_ID) { return; } // nothing to do if (hitInfo.attackSequenceId != ModState.BreachAttackId) { Mod.Log.Warn?.Write($"AttackSequenceId: {hitInfo.attackSequenceId} does not match hull breach attack sequence id: {ModState.BreachAttackId}... wasn't expecting this, skipping!"); return; } Mod.Log.Debug?.Write($" --- Location: {location} needs breach check."); if (ModState.BreachHitsVehicle.ContainsKey(location)) { ModState.BreachHitsVehicle[location]++; } else { ModState.BreachHitsVehicle.Add(location, 1); } }
internal VehiclePlaceholderInterpolation(MechComponent mechComponent) { MechComponent = mechComponent; Location = mechComponent.vehicleComponentRef.MountedLocation; }
private static float PercentForLocation(Vehicle v, VehicleChassisLocations location) { if (v != null) { var maxs = MaxStructureForLocation(v, (int)location); var maxa = MaxArmorForLocation(v, (int)location); var cs = maxs; var ca = maxa; if (maxs == 0 || maxa == 0) { LogDebug($"Invalid location in vehicle {location.ToString()}"); return(1); } switch (location) { case VehicleChassisLocations.Turret: cs = v.TurretStructure; ca = v.TurretArmor; break; case VehicleChassisLocations.Left: cs = v.LeftSideStructure; ca = v.LeftSideArmor; break; case VehicleChassisLocations.Right: cs = v.RightSideStructure; ca = v.RightSideArmor; break; case VehicleChassisLocations.Front: cs = v.FrontStructure; ca = v.FrontArmor; break; case VehicleChassisLocations.Rear: cs = v.RearStructure; ca = v.RearArmor; break; default: LogDebug($"Invalid location {location}"); break; } float percentArmor = ca / maxa; float percentStructure = cs / maxs; //since its easy to kill vehicles once past armor use the armor instead of structure unless structure is damaged. //this is reverse of mechs. //Remember the vehicle pilot motto - in armor we trust , structure is for the dead and defeated. float percentLocation = percentArmor; float numAdditions = 2; // Use the minimum percentage between structure and armor // This emphasizes internal damage from a blow through (back armor gone or tandem weapons) percentLocation += Math.Min(percentArmor, percentStructure); percentLocation /= numAdditions; LogReport($"{location.ToString(),-20} | A:{ca:F3}/{maxa:F3} = {percentArmor * 100,10}% , S:{cs:F3}/{maxs:F3} = {percentStructure * 100,10:F3}%"); return(percentLocation); } LogDebug($"Vehicle null"); return(0); }
internal static bool DamageLocation(this Vehicle vehicle, WeaponHitInfo hitInfo, int originalHitLoc, VehicleChassisLocations vLoc, Weapon weapon, float totalDamage, AttackImpactQuality impactQuality) { return(Traverse.Create(vehicle).Method(nameof(DamageLocation), hitInfo, originalHitLoc, vLoc, weapon, totalDamage, impactQuality).GetValue <bool>()); }
public static void PrefixVehicleCalledShot(VehicleChassisLocations bonusLocation, ref float bonusLocationMultiplier) { try { bonusLocationMultiplier = FixMultiplier(bonusLocation, bonusLocationMultiplier); } catch (Exception ex) { Error(ex); } }
internal static void applyArmorStatDamage(this Vehicle vehicle, VehicleChassisLocations location, float damage, WeaponHitInfo hitInfo) { Traverse.Create(vehicle).Method(nameof(applyArmorStatDamage), location, damage, hitInfo).GetValue(); }
static bool Prefix(PoorlyMaintainedEffect __instance, Vehicle targetVehicle) { Mod.Log.Trace?.Write("PME:AETV - entered."); // Note that OnEffectBegin will invoke *every* ApplyEffects, and expects the ApplyEfect to check that the target isn't null. if (targetVehicle == null) { return(false); } Mod.Log.Info?.Write($" Applying PoorlyMaintainedEffect to unit: {CombatantUtils.Label(targetVehicle)}"); ModState.SuppressShowActorSequences = true; WeaponHitInfo hitInfo = new WeaponHitInfo(-1, -1, -1, -1, "", "", -1, null, null, null, null, null, null, null, new AttackDirection[] { AttackDirection.FromFront }, null, null, null); // Apply any structure damage first StringBuilder componentDamageSB = new StringBuilder(); VehicleRepairState repairState = new VehicleRepairState(__instance, targetVehicle); foreach (MechComponent mc in repairState.DamagedComponents) { if (mc.componentType == ComponentType.AmmunitionBox) { AmmunitionBox ab = (AmmunitionBox)mc; float ammoReduction = Mod.Random.Next( (int)(Mod.Config.PerHitPenalties.MinAmmoRemaining * 100f), (int)(Mod.Config.PerHitPenalties.MaxAmmoRemaining * 100f) ) / 100f; int newAmmo = (int)Math.Floor(ab.CurrentAmmo * ammoReduction); Mod.Log.Info?.Write($"Reducing ammoBox: {mc.UIName} from {ab.CurrentAmmo} x {ammoReduction} = {newAmmo}"); ab.StatCollection.Set <int>(ModStats.AmmoBoxCurrentAmmo, newAmmo); } else { Mod.Log.Info?.Write($"Damaging component: {mc.UIName}"); Text localText = new Text(" - {0}\n", new object[] { mc.UIName }); componentDamageSB.Append(localText.ToString()); mc.DamageComponent(hitInfo, ComponentDamageLevel.Destroyed, false); } } // Then apply any armor hits HashSet <VehicleChassisLocations> armorHitLocs = new HashSet <VehicleChassisLocations>(); for (int i = 0; i < repairState.ArmorHits; i++) { VehicleChassisLocations location = LocationHelper.GetRandomVehicleLocation(); armorHitLocs.Add(location); float maxArmor = targetVehicle.GetMaxArmor(location); float maxDamageRatio = Mod.Random.Next( (int)(Mod.Config.PerHitPenalties.MinArmorLoss * 100), (int)(Mod.Config.PerHitPenalties.MaxArmorLoss * 100) ) / 100f; float damage = (float)Math.Floor(maxArmor * maxDamageRatio); if (targetVehicle.GetCurrentArmor(location) - damage < 0) { damage = targetVehicle.GetCurrentArmor(location); } Mod.Log.Info?.Write($"Reducing armor in location {location} by {maxDamageRatio}% for {damage} points"); if (damage != 0) { targetVehicle.StatCollection.ModifyStat <float>(hitInfo.attackerId, hitInfo.stackItemUID, targetVehicle.GetStringForArmorLocation(location), StatCollection.StatOperation.Float_Subtract, damage, -1, true); } } // We don't limit to armor damage locations here so we can represent that armor is easily scavenged HashSet <VehicleChassisLocations> structHitLocs = new HashSet <VehicleChassisLocations>(); for (int i = 0; i < repairState.StructureHits; i++) { VehicleChassisLocations location = LocationHelper.GetRandomVehicleLocation(); structHitLocs.Add(location); float maxStructure = targetVehicle.GetMaxStructure(location); float maxDamageRatio = Mod.Random.Next( (int)(Mod.Config.PerHitPenalties.MinStructureLoss * 100), (int)(Mod.Config.PerHitPenalties.MaxStructureLoss * 100) ) / 100f; float damage = (float)Math.Floor(maxStructure * maxDamageRatio); if (targetVehicle.GetCurrentStructure(location) - damage < 1) { // Never allow a hit to completely remove a limb or location damage = targetVehicle.GetCurrentStructure(location) - 1; } Mod.Log.Info?.Write($"Reducing structure in location {location} by {maxDamageRatio}% for {damage} points"); if (damage != 0) { targetVehicle.StatCollection.ModifyStat <float>(hitInfo.attackerId, hitInfo.stackItemUID, targetVehicle.GetStringForStructureLocation(location), StatCollection.StatOperation.Float_Subtract, damage, -1, true); } targetVehicle.UpdateLocationDamageLevel(location, hitInfo.attackerId, hitInfo.stackItemUID); } // Vehicles have no head armor, can't take health hits PilotHelper.ApplyPilotSkillDamage(targetVehicle, hitInfo, repairState.PilotSkillHits, out string pilotSkillDamageTooltipText); // Build the tooltip StringBuilder descSB = new StringBuilder(); if (repairState.ArmorHits > 0) { Text localText = new Text(Mod.Config.LocalizedText[ModConfig.LT_TT_DAMAGE_ARMOR], new object[] { repairState.ArmorHits }); descSB.Append(localText.ToString()); foreach (ChassisLocations hitLoc in armorHitLocs) { Text locationText = new Text(" - {0}\n", new object[] { hitLoc }); descSB.Append(locationText.ToString()); } } if (repairState.StructureHits > 0) { Text localText = new Text(Mod.Config.LocalizedText[ModConfig.LT_TT_DAMAGE_STRUCTURE], new object[] { repairState.StructureHits }); descSB.Append(localText.ToString()); foreach (ChassisLocations hitLoc in structHitLocs) { Text locationText = new Text(" - {0}\n", new object[] { hitLoc }); descSB.Append(locationText.ToString()); } } if (componentDamageSB.Length > 0) { Text localText = new Text(Mod.Config.LocalizedText[ModConfig.LT_TT_DAMAGE_COMP]); descSB.Append(localText.ToString()); descSB.Append(componentDamageSB.ToString()); } if (pilotSkillDamageTooltipText != null) { Text localText = new Text(Mod.Config.LocalizedText[ModConfig.LT_TT_DAMAGE_SKILL]); descSB.Append(localText.ToString()); descSB.Append(pilotSkillDamageTooltipText.ToString()); } Text titleText = new Text(ModState.CurrentTheme.Label, new object[] { repairState.effectRating }); __instance.EffectData.Description = new BaseDescriptionDef("PoorlyMaintained", titleText.ToString(), descSB.ToString(), __instance.EffectData.Description.Icon); ModState.SuppressShowActorSequences = false; return(false); }
public static void FixZombieVehicle(Vehicle __instance, ref float totalDamage, VehicleChassisLocations vLoc) { try { if (vLoc == VehicleChassisLocations.None || vLoc == VehicleChassisLocations.Invalid) { return; } KillZombie("vehicle", __instance.DisplayName, __instance.GetCurrentArmor(vLoc) + __instance.GetCurrentStructure(vLoc), ref totalDamage); } catch (Exception ex) { Error(ex); } }
public static void CreateImaginaryAttack(Mech attacker, Weapon attackWeapon, ICombatant target, int weaponHitInfoStackItemUID, float[] damageClusters, DamageType damageType, MeleeAttackType attackType) { Mod.Log.Info?.Write($" Creating imaginary attack for attacker: {attacker.DistinctId()} at position: {attacker?.CurrentPosition} and rot: {attacker?.CurrentRotation} " + $"vs. target: {target.DistinctId()} at position: {target?.CurrentPosition} and rot: {target?.CurrentRotation} " + $"using weapon => isNull: {attackWeapon == null} name: {attackWeapon?.Name} damageType: {damageType} attackType: {attackType}"); if (attackWeapon.ammo() == null) { Mod.Log.Error?.Write($"AMMO is null!"); } if (attackWeapon.mode() == null) { Mod.Log.Error?.Write($"Mode is null!"); } if (attackWeapon.exDef() == null) { Mod.Log.Error?.Write($"exDef is null!"); } AttackDirector.AttackSequence attackSequence = target.Combat.AttackDirector.CreateAttackSequence(0, attacker, target, attacker.CurrentPosition, attacker.CurrentRotation, 0, new List <Weapon>() { attackWeapon }, attackType, 0, false ); AttackDirection[] attackDirections = new AttackDirection[damageClusters.Length]; WeaponHitInfo hitInfo = new WeaponHitInfo(0, attackSequence.id, 0, 0, attacker.GUID, target.GUID, 1, null, null, null, null, null, null, null, attackDirections, null, null, null) { attackerId = attacker.GUID, targetId = target.GUID, numberOfShots = damageClusters.Length, stackItemUID = weaponHitInfoStackItemUID, locationRolls = new float[damageClusters.Length], hitLocations = new int[damageClusters.Length], hitPositions = new Vector3[damageClusters.Length], hitQualities = new AttackImpactQuality[damageClusters.Length] }; AttackDirection attackDirection = attacker.Combat.HitLocation.GetAttackDirection(attacker, target); Mod.Log.Info?.Write($" Attack direction is: {attackDirection}"); int i = 0; foreach (int damage in damageClusters) { // Set hit qualities hitInfo.attackDirections[i] = attackDirection; hitInfo.hitQualities[i] = AttackImpactQuality.Solid; hitInfo.hitPositions[i] = attacker.CurrentPosition; float adjustedDamage = damage; float randomRoll = (float)Mod.Random.NextDouble(); if (target is Mech mech) { ArmorLocation location = SharedState.Combat.HitLocation.GetHitLocation(attacker.CurrentPosition, mech, randomRoll, ArmorLocation.None, 0f); hitInfo.hitLocations[i] = (int)location; adjustedDamage = mech.GetAdjustedDamageForMelee(damage, attackWeapon.WeaponCategoryValue); Mod.Log.Info?.Write($" {adjustedDamage} damage to location: {location}"); ShowDamageFloatie(mech, location, adjustedDamage, hitInfo.attackerId); } else if (target is Vehicle vehicle) { VehicleChassisLocations location = SharedState.Combat.HitLocation.GetHitLocation(attacker.CurrentPosition, vehicle, randomRoll, VehicleChassisLocations.None, 0f); hitInfo.hitLocations[i] = (int)location; adjustedDamage = vehicle.GetAdjustedDamageForMelee(damage, attackWeapon.WeaponCategoryValue); Mod.Log.Info?.Write($" {adjustedDamage} damage to location: {location}"); ShowDamageFloatie(vehicle, location, adjustedDamage, hitInfo.attackerId); } else if (target is Turret turret) { BuildingLocation location = BuildingLocation.Structure; hitInfo.hitLocations[i] = (int)BuildingLocation.Structure; adjustedDamage = turret.GetAdjustedDamageForMelee(damage, attackWeapon.WeaponCategoryValue); Mod.Log.Info?.Write($" {adjustedDamage} damage to location: {location}"); ShowDamageFloatie(turret, adjustedDamage, hitInfo.attackerId); } // Make the target take weapon damage target.TakeWeaponDamage(hitInfo, hitInfo.hitLocations[i], attackWeapon, adjustedDamage, 0, 0, damageType); i++; } // Cleanup after myself target.Combat.AttackDirector.RemoveAttackSequence(attackSequence); }
internal VehicleLocationNaming(VehicleChassisLocations location) { this.location = location; }