-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMechFallSequenceDamageAdder.cs
More file actions
88 lines (82 loc) · 4.76 KB
/
MechFallSequenceDamageAdder.cs
File metadata and controls
88 lines (82 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using BattleTech;
using Harmony;
using UnityEngine;
namespace CharlesB
{
[HarmonyPatch(typeof(MechFallSequence), "setState")]
public static class MechFallSequenceDamageAdder
{
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
if (!Core.ModSettings.FallingDamage) return instructions;
var instructionList = instructions.ToList();
var insertionIndex =
instructionList.FindIndex(
instruction => instruction.opcode == OpCodes.Ret // find early return
) + 2;
var nopLabelReplaceIndex = insertionIndex - 1;
instructionList[nopLabelReplaceIndex].opcode = OpCodes.Nop; // preserve jump label
instructionList.Insert(insertionIndex, new CodeInstruction(OpCodes.Ldarg_0)); // replace code we just mangled
var stateField = AccessTools.Field(typeof(MechFallSequence), "state");
var owningMechGetter = AccessTools.Property(typeof(MechFallSequence), "OwningMech").GetGetMethod();
var calculator = AccessTools.Method(
typeof(MechFallSequenceDamageAdder), "ApplyFallingDamage", new Type[] {typeof(MechFallSequence), typeof(int), typeof(int)}
);
var damageMethodCalloutInstructions = new List<CodeInstruction>();
damageMethodCalloutInstructions.Add(new CodeInstruction(OpCodes.Ldarg_0)); // this
damageMethodCalloutInstructions.Add(new CodeInstruction(OpCodes.Ldarg_0)); // this
damageMethodCalloutInstructions.Add(new CodeInstruction(OpCodes.Ldfld, stateField)); // this.state
damageMethodCalloutInstructions.Add(new CodeInstruction(OpCodes.Ldarg_1)); // newState (Argument)
damageMethodCalloutInstructions.Add(new CodeInstruction(OpCodes.Call, calculator)); // MechFallSequenceDamageAdder.DoDamage(this, this.state, newState)
instructionList.InsertRange(insertionIndex, damageMethodCalloutInstructions);
return instructionList;
}
private const int FinishedState = 3;
private static readonly ArmorLocation[] possibleLocations = new[]
{
ArmorLocation.Head,
ArmorLocation.CenterTorso,
ArmorLocation.CenterTorsoRear,
ArmorLocation.LeftTorso,
ArmorLocation.LeftTorsoRear,
ArmorLocation.RightTorso,
ArmorLocation.RightTorsoRear,
ArmorLocation.LeftArm,
ArmorLocation.RightArm,
ArmorLocation.RightLeg,
ArmorLocation.LeftLeg
};
static void ApplyFallingDamage(MechFallSequence sequence, int oldState, int newState)
{
if (newState != FinishedState) return;
var mech = sequence.OwningMech;
if (mech.IsFlaggedForDeath || mech.IsDead) return; // TODO: maybe even the dead should take damage?
var locationTakingDamage = possibleLocations[UnityEngine.Random.Range(0, possibleLocations.Length)];
Logger.Debug($"falling happened!\nlocation taking damage: {locationTakingDamage}");
var rawFallingDamage = Core.ModSettings.FallingAmountDamagePerTon * mech.tonnage;
var fallingDamageValue = rawFallingDamage;
if (Core.ModSettings.PilotingSkillFallingDamageMitigation)
{
var mitigation = Calculator.PilotingMitigation(mech);
var mitigationPercent = Mathf.RoundToInt(mitigation * 100);
fallingDamageValue = rawFallingDamage - (mitigation * rawFallingDamage);
Logger.Debug($"falling damage numbers\n" +
$"pilotSkill: {mech.SkillPiloting}\n" +
$"mitigation: {mitigation}\n" +
$"rawFallingDamage: {rawFallingDamage}\n" +
$"mitigationPercent: {mitigationPercent}\n" +
$"fallingDamageValue: {fallingDamageValue}");
mech.Combat.MessageCenter.PublishMessage(new AddSequenceToStackMessage(new ShowActorInfoSequence(mech, $"Pilot Check: Avoided {mitigationPercent}% Falling Damage!", FloatieMessage.MessageNature.Neutral, true)));
}
mech.DEBUG_DamageLocation(locationTakingDamage, fallingDamageValue, mech, damageType: DamageType.Knockdown);
if (AttackDirector.damageLogger.IsLogEnabled)
{
AttackDirector.damageLogger.Log($"@@@@@@@@ {mech.DisplayName} takes {fallingDamageValue} damage to its {Mech.GetLongArmorLocation(locationTakingDamage)} from falling!");
}
}
}
}