1 | using System.Collections.Generic;
|
---|
2 | using System.Reflection;
|
---|
3 | using System.Reflection.Emit;
|
---|
4 | using HarmonyLib;
|
---|
5 | using JetBrains.Annotations;
|
---|
6 | using UnityEngine;
|
---|
7 |
|
---|
8 | namespace FiniteItemRepairs
|
---|
9 | {
|
---|
10 | [UsedImplicitly]
|
---|
11 | public class FiniteItemRepairsPatch
|
---|
12 | {
|
---|
13 | private const string MetaDataName = "DurabilityModifier";
|
---|
14 |
|
---|
15 | private static readonly PassiveEffects EnumDegradationMax = EnumUtils.Parse<PassiveEffects> (nameof (PassiveEffects.DegradationMax));
|
---|
16 | private const string CustomNameDegradationMax = "DegradationMax";
|
---|
17 |
|
---|
18 |
|
---|
19 | [HarmonyPatch(typeof(XUiC_RecipeStack))]
|
---|
20 | [HarmonyPatch(nameof(XUiC_RecipeStack.outputStack))]
|
---|
21 | public static class XUiC_RecipeStack_outputStack
|
---|
22 | {
|
---|
23 | private static readonly MethodInfo VanillaItemValueCloneMethod = AccessTools.Method(typeof(ItemValue), "Clone");
|
---|
24 | private static readonly MethodInfo GetHandleDegradationMethod = SymbolExtensions.GetMethodInfo(() => HandleDegradation(null));
|
---|
25 |
|
---|
26 | [UsedImplicitly]
|
---|
27 | private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
---|
28 | {
|
---|
29 | return new CodeMatcher(instructions)
|
---|
30 | .MatchForward(true,
|
---|
31 | new CodeMatch(OpCodes.Ldarg_0),
|
---|
32 | new CodeMatch(OpCodes.Ldfld),
|
---|
33 | new CodeMatch(OpCodes.Callvirt, VanillaItemValueCloneMethod)
|
---|
34 | ).InsertAndAdvance(
|
---|
35 | new CodeInstruction(OpCodes.Dup),
|
---|
36 | new CodeInstruction(OpCodes.Call, GetHandleDegradationMethod)
|
---|
37 | ).InstructionEnumeration();
|
---|
38 | }
|
---|
39 |
|
---|
40 | private static void HandleDegradation(ItemValue outItem)
|
---|
41 | {
|
---|
42 | float currentDurabilityModifier = 1;
|
---|
43 | if (outItem.HasMetadata(MetaDataName, TypedMetadataValue.TypeTag.Float))
|
---|
44 | {
|
---|
45 | object metadata = outItem.GetMetadata(MetaDataName);
|
---|
46 | currentDurabilityModifier = (float)metadata;
|
---|
47 | }
|
---|
48 |
|
---|
49 | currentDurabilityModifier = (1 - (1 - outItem.PercentUsesLeft) * Settings.Data.DegradationPercent) * currentDurabilityModifier;
|
---|
50 | currentDurabilityModifier = Mathf.Max(currentDurabilityModifier, 0.01f);
|
---|
51 |
|
---|
52 | outItem.SetMetadata(MetaDataName, currentDurabilityModifier, TypedMetadataValue.TypeTag.Float);
|
---|
53 | }
|
---|
54 | }
|
---|
55 |
|
---|
56 |
|
---|
57 | [HarmonyPatch(typeof(ItemValue))]
|
---|
58 | [HarmonyPatch(nameof(ItemValue.MaxUseTimes))]
|
---|
59 | [HarmonyPatch(MethodType.Getter)]
|
---|
60 | public static class ItemValue_MaxUseTimes
|
---|
61 | {
|
---|
62 | [UsedImplicitly]
|
---|
63 | private static void Postfix(ref int __result, ItemValue __instance)
|
---|
64 | {
|
---|
65 | __result = ModMaxUseTimes(__result, __instance);
|
---|
66 | }
|
---|
67 | }
|
---|
68 |
|
---|
69 | [HarmonyPatch(typeof(XUiM_ItemStack))]
|
---|
70 | [HarmonyPatch(nameof(XUiM_ItemStack.GetStatItemValueTextWithCompareInfo))]
|
---|
71 | public static class XUiM_ItemStack_GetStatItemValueTextWithCompareInfo
|
---|
72 | {
|
---|
73 | [UsedImplicitly]
|
---|
74 | private static void Prefix (DisplayInfoEntry infoEntry)
|
---|
75 | {
|
---|
76 | if (infoEntry.StatType != EnumDegradationMax)
|
---|
77 | {
|
---|
78 | return;
|
---|
79 | }
|
---|
80 |
|
---|
81 | infoEntry.CustomName = CustomNameDegradationMax;
|
---|
82 | }
|
---|
83 | }
|
---|
84 |
|
---|
85 | [HarmonyPatch(typeof(XUiM_ItemStack))]
|
---|
86 | [HarmonyPatch(nameof(XUiM_ItemStack.GetStatItemValueTextWithModColoring))]
|
---|
87 | public static class XUiM_ItemStack_GetStatItemValueTextWithModColoring
|
---|
88 | {
|
---|
89 | [UsedImplicitly]
|
---|
90 | private static void Prefix (DisplayInfoEntry infoEntry)
|
---|
91 | {
|
---|
92 | if (infoEntry.StatType != EnumDegradationMax)
|
---|
93 | {
|
---|
94 | return;
|
---|
95 | }
|
---|
96 |
|
---|
97 | infoEntry.CustomName = CustomNameDegradationMax;
|
---|
98 | }
|
---|
99 | }
|
---|
100 |
|
---|
101 | [HarmonyPatch(typeof(XUiM_ItemStack))]
|
---|
102 | [HarmonyPatch(nameof(XUiM_ItemStack.GetStatItemValueTextWithModInfo))]
|
---|
103 | public static class XUiM_ItemStack_GetStatItemValueTextWithModInfo
|
---|
104 | {
|
---|
105 | [UsedImplicitly]
|
---|
106 | private static void Prefix (DisplayInfoEntry infoEntry)
|
---|
107 | {
|
---|
108 | if (infoEntry.StatType != EnumDegradationMax)
|
---|
109 | {
|
---|
110 | return;
|
---|
111 | }
|
---|
112 |
|
---|
113 | infoEntry.CustomName = CustomNameDegradationMax;
|
---|
114 | }
|
---|
115 | }
|
---|
116 |
|
---|
117 | [HarmonyPatch(typeof(XUiM_ItemStack))]
|
---|
118 | [HarmonyPatch(nameof(XUiM_ItemStack.GetCustomValue))]
|
---|
119 | public static class XUiM_ItemStack_GetCustomValue
|
---|
120 | {
|
---|
121 | [UsedImplicitly]
|
---|
122 | private static bool Prefix (ref float __result, DisplayInfoEntry entry, ItemValue itemValue, bool useMods)
|
---|
123 | {
|
---|
124 | if (entry.StatType != EnumDegradationMax)
|
---|
125 | {
|
---|
126 | return true;
|
---|
127 | }
|
---|
128 |
|
---|
129 | __result = DegradationMaxMod(entry.StatType, itemValue, null, entry.tags, useMods, 0);
|
---|
130 | return false;
|
---|
131 | }
|
---|
132 | }
|
---|
133 |
|
---|
134 | private static float DegradationMaxMod (PassiveEffects statType, ItemValue itemValue, EntityPlayer player, FastTags<TagGroup.Global> tags, bool useMods, float value) {
|
---|
135 | if (statType != EnumDegradationMax) {
|
---|
136 | return value;
|
---|
137 | }
|
---|
138 |
|
---|
139 | value = EffectManager.GetValue(PassiveEffects.DegradationMax, itemValue, 0, player, tags: tags, calcEquipment: false, calcHoldingItem: false, calcProgression: false, calcBuffs: false, useMods: useMods);
|
---|
140 | value = ModMaxUseTimes ((int)value, itemValue);
|
---|
141 | return value;
|
---|
142 | }
|
---|
143 |
|
---|
144 | private static int ModMaxUseTimes(int value, ItemValue iv)
|
---|
145 | {
|
---|
146 | if (value <= 0)
|
---|
147 | {
|
---|
148 | return value;
|
---|
149 | }
|
---|
150 |
|
---|
151 | if (!iv.HasMetadata(MetaDataName, TypedMetadataValue.TypeTag.Float))
|
---|
152 | {
|
---|
153 | return value;
|
---|
154 | }
|
---|
155 |
|
---|
156 | object metadata = iv.GetMetadata(MetaDataName);
|
---|
157 | float currentDurabilityModifier = (float)metadata;
|
---|
158 | value = Mathf.RoundToInt(value * currentDurabilityModifier);
|
---|
159 | value = Mathf.Max(value, 1);
|
---|
160 | return value;
|
---|
161 | }
|
---|
162 | }
|
---|
163 | }
|
---|