// Per BT Manual pg.36, // * target takes 1 pt. each 10 tons of attacker, which is then multiplied by 3 and rounded up // * attacker takes tonnage / 5, rounded up // * Damage clustered in 5 (25) point groupings for both attacker & defender // * Target resolves on punch table // * Prone targets resolve on rear table // * Attacker resolves on kick table // * Comparative attack modifier; difference in attacker and defender is applied to attack // * +3 modifier to hit for jumping // * +2 to hit if upper or lower leg actuators are hit // * -2 modifier if target is prone // * Attacker makes PSR with +4, target with +2 and fall public DFAAttack(MeleeState state) : base(state) { Mod.MeleeLog.Info?.Write($"Building DFA state for attacker: {CombatantUtils.Label(state.attacker)} @ attackPos: {state.attackPos} vs. target: {CombatantUtils.Label(state.target)}"); this.Label = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_DeathFromAbove]; this.IsValid = ValidateAttack(state.attacker, state.target); if (IsValid) { this.UsePilotingDelta = Mod.Config.Melee.DFA.UsePilotingDelta; CalculateDamages(state.attacker, state.target); CalculateInstability(state.attacker, state.target); CalculateModifiers(state.attacker, state.target); CreateDescriptions(state.attacker, state.target); // Damage tables this.AttackerTable = DamageTable.KICK; this.TargetTable = state.target.IsProne ? DamageTable.REAR : DamageTable.PUNCH; // Unsteady this.UnsteadyAttackerOnHit = Mod.Config.Melee.DFA.UnsteadyAttackerOnHit; this.UnsteadyAttackerOnMiss = Mod.Config.Melee.DFA.UnsteadyAttackerOnMiss; this.OnTargetMechHitForceUnsteady = Mod.Config.Melee.DFA.UnsteadyTargetOnHit; this.OnTargetVehicleHitEvasionPipsRemoved = Mod.Config.Melee.DFA.TargetVehicleEvasionPipsRemoved; // Set the animation type this.AttackAnimation = MeleeAttackType.DFA; } }
// Per BT Manual pg.38, // * target takes 1 pt. each 10 tons of attacker, rounded up // * x0.5 damage for each missing upper & lower actuator // * Resolves on punch table // * Requires a shoulder actuator // * +1 to hit if hand actuator missing // * +2 to hit if lower arm actuator missing // * -2 modifier if target is prone public PunchAttack(MeleeState state) : base(state) { Mod.MeleeLog.Info?.Write($"Building PUNCH state for attacker: {state.attacker.DistinctId()} @ attackPos: {state.attackPos} vs. target: {state.target.DistinctId()}"); this.Label = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Punch]; this.IsValid = ValidateAttack(state.attacker, state.target, state.validAnimations); if (IsValid) { CalculateDamages(state.attacker, state.target); CalculateInstability(state.attacker, state.target); CalculateModifiers(state.attacker, state.target); CreateDescriptions(state.attacker, state.target); // Damage tables this.AttackerTable = DamageTable.NONE; this.TargetTable = DamageTable.PUNCH; // Unsteady this.UnsteadyAttackerOnHit = Mod.Config.Melee.Punch.UnsteadyAttackerOnHit; this.UnsteadyAttackerOnMiss = Mod.Config.Melee.Punch.UnsteadyAttackerOnMiss; this.OnTargetMechHitForceUnsteady = Mod.Config.Melee.Punch.UnsteadyTargetOnHit; this.OnTargetVehicleHitEvasionPipsRemoved = Mod.Config.Melee.Punch.TargetVehicleEvasionPipsRemoved; // Set the animation type this.AttackAnimation = state.validAnimations.Contains(MeleeAttackType.Punch) ? MeleeAttackType.Punch : MeleeAttackType.Tackle; } }
// Per BT Manual pg.38, // * target takes 1 pt. each 5 tons of attacker, rounded up // * x0.5 damage for each missing leg actuator // * One attack // * Normally resolves on kick table // * -2 to hit base // * +1 for foot actuator, +2 to hit for each upper/lower actuator hit // * -2 modifier if target is prone public KickAttack(MeleeState state) : base(state) { Mod.MeleeLog.Info?.Write($"Building KICK state for attacker: {CombatantUtils.Label(state.attacker)} @ attackPos: {state.attackPos} vs. target: {CombatantUtils.Label(state.target)}"); this.Label = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Kick]; this.IsValid = ValidateAttack(state.attacker, state.target, state.validAnimations); if (IsValid) { CalculateDamages(state.attacker, state.target); CalculateInstability(state.attacker, state.target); CalculateModifiers(state.attacker, state.target); CreateDescriptions(state.attacker, state.target); // Damage tables this.AttackerTable = DamageTable.NONE; this.TargetTable = DamageTable.KICK; // Unsteady this.UnsteadyAttackerOnHit = Mod.Config.Melee.Kick.UnsteadyAttackerOnHit; this.UnsteadyAttackerOnMiss = Mod.Config.Melee.Kick.UnsteadyAttackerOnMiss; this.OnTargetMechHitForceUnsteady = Mod.Config.Melee.Kick.UnsteadyTargetOnHit; this.OnTargetVehicleHitEvasionPipsRemoved = Mod.Config.Melee.Kick.TargetVehicleEvasionPipsRemoved; // Set the animation type if (state.target is Vehicle) { this.AttackAnimation = MeleeAttackType.Stomp; } else { this.AttackAnimation = MeleeAttackType.Kick; } } }
// Per BT Manual pg.38, // * target takes 1 pt. each 4-10 tons of attacker, rounded up (varies by weapon) // * One attack // * Resolves on main table // * Optional - Can resolve on punch table // * Optional - Can resolve on kick table // * Requires a shoulder actuator AND hand actuator // * +2 to hit if lower or upper arm actuator missing // * -2 modifier if target is prone public WeaponAttack(MeleeState state) : base(state) { Mod.MeleeLog.Info?.Write($"Building PHYSICAL WEAPON state for attacker: {CombatantUtils.Label(state.attacker)} @ attackPos: {state.attackPos} vs. target: {CombatantUtils.Label(state.target)}"); this.Label = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Physical_Weapon]; this.IsValid = ValidateAttack(state.attacker, state.target, state.validAnimations); if (IsValid) { CalculateDamages(state.attacker, state.target); CalculateInstability(state.attacker, state.target); CalculateModifiers(state.attacker, state.target); CreateDescriptions(state.attacker, state.target); // Damage tables this.AttackerTable = DamageTable.NONE; this.TargetTable = DamageTable.STANDARD; if (state.attacker.StatCollection.ContainsStatistic(ModStats.PhysicalWeaponLocationTable)) { string tableName = state.attacker.StatCollection.GetValue <string>(ModStats.PhysicalWeaponLocationTable).ToUpper(); if (tableName.Equals("KICK")) { this.TargetTable = DamageTable.KICK; } else if (tableName.Equals("PUNCH")) { this.TargetTable = DamageTable.PUNCH; } else if (tableName.Equals("STANDARD")) { this.TargetTable = DamageTable.STANDARD; } } if (state.attacker is TrooperSquad) { this.TargetTable = DamageTable.SWARM; } // Unsteady this.UnsteadyAttackerOnHit = state.attacker.StatCollection.ContainsStatistic(ModStats.PhysicalWeaponUnsteadyAttackerOnHit) ? state.attacker.StatCollection.GetValue <bool>(ModStats.PhysicalWeaponUnsteadyAttackerOnHit) : Mod.Config.Melee.PhysicalWeapon.DefaultUnsteadyAttackerOnHit; this.UnsteadyAttackerOnMiss = state.attacker.StatCollection.ContainsStatistic(ModStats.PhysicalWeaponUnsteadyAttackerOnMiss) ? state.attacker.StatCollection.GetValue <bool>(ModStats.PhysicalWeaponUnsteadyAttackerOnMiss) : Mod.Config.Melee.PhysicalWeapon.DefaultUnsteadyAttackerOnMiss; this.OnTargetMechHitForceUnsteady = state.attacker.StatCollection.ContainsStatistic(ModStats.PhysicalWeaponUnsteadyTargetOnHit) ? state.attacker.StatCollection.GetValue <bool>(ModStats.PhysicalWeaponUnsteadyTargetOnHit) : Mod.Config.Melee.PhysicalWeapon.DefaultUnsteadyTargetOnHit; this.OnTargetVehicleHitEvasionPipsRemoved = Mod.Config.Melee.PhysicalWeapon.TargetVehicleEvasionPipsRemoved; // Set the animation type this.AttackAnimation = MeleeAttackType.Punch; } }
// Per BT Manual pg.35, // * attacker takes 1 pt. each 10 tons of target, rounded up // * defender takes 1 pt. each 10 tons of attacker * # hexes moved, rounded up // * Groupings by 5 (25) points // * Resolves on regular table // * Prone targets cannot be attacked // * Attacker makes PSR with +4, target with +2 to avoid falling // * Create instab damage instead // * Modifier for attack is comparative skill public ChargeAttack(MeleeState state) : base(state) { Mod.MeleeLog.Info?.Write($"Building CHARGE state for attacker: {CombatantUtils.Label(state.attacker)} @ attackPos: {state.attackPos} vs. target: {CombatantUtils.Label(state.target)}"); this.Label = Mod.LocalizedText.Labels[ModText.LT_Label_Melee_Type_Charge]; this.IsValid = ValidateAttack(state.attacker, state.target, state.validAnimations); if (IsValid) { float distance = (state.attacker.CurrentPosition - state.target.CurrentPosition).magnitude; int hexesMoved = (int)Math.Ceiling(distance / Mod.Config.Move.MPMetersPerHex); Mod.MeleeLog.Info?.Write($" - Hexes moved is {hexesMoved} = distance: {distance} / MPMetersPerHex: {Mod.Config.Move.MPMetersPerHex}"); this.UsePilotingDelta = Mod.Config.Melee.Charge.UsePilotingDelta; CalculateDamages(state.attacker, state.target, hexesMoved); CalculateInstability(state.attacker, state.target, hexesMoved); CalculateModifiers(state.attacker, state.target); CreateDescriptions(state.attacker, state.target); // Damage tables this.AttackerTable = DamageTable.STANDARD; this.TargetTable = DamageTable.STANDARD; // Unsteady this.UnsteadyAttackerOnHit = Mod.Config.Melee.Charge.UnsteadyAttackerOnHit; this.UnsteadyAttackerOnMiss = Mod.Config.Melee.Charge.UnsteadyAttackerOnMiss; this.OnTargetMechHitForceUnsteady = Mod.Config.Melee.Charge.UnsteadyTargetOnHit; this.OnTargetVehicleHitEvasionPipsRemoved = Mod.Config.Melee.Charge.TargetVehicleEvasionPipsRemoved; // Set the animation type if (state.target is Vehicle) { this.AttackAnimation = MeleeAttackType.Stomp; } else { this.AttackAnimation = MeleeAttackType.Tackle; } } }
public MeleeAttack(MeleeState state) { this.state = state; }