source: FiniteItemRepairs/FiniteItemRepairsPatch.cs

Last change on this file was 509, checked in by alloc, 24 hours ago

Initial commit for FiniteItemRepairs mod

File size: 6.3 KB
Line 
1using System.Collections.Generic;
2using System.Reflection;
3using System.Reflection.Emit;
4using HarmonyLib;
5using JetBrains.Annotations;
6using UnityEngine;
7
8namespace 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}
Note: See TracBrowser for help on using the repository browser.