Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CarryWeightSkill v1.0.2
plugins\CarrySkill.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using CarrySkill.Patches; using HarmonyLib; using Jotunn.Configs; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Carry Skill")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Carry Skill")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e6b72c5a-9fe8-49d7-855e-8165656a6777")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CarrySkill { [BepInPlugin("shadymods.carryskill.carry_weight", "Carry Weight Skill", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class CarrySkillPlugin : BaseUnityPlugin { public const string PluginGuid = "shadymods.carryskill.carry_weight"; public const string PluginName = "Carry Weight Skill"; public const string PluginVersion = "1.0.2"; public const string SkillIdentifier = "com.shadymods.carryskill.carry_weight_v1"; public static SkillType CarrySkillType { get; private set; } internal static ManualLogSource CarrySkillLog { get; private set; } private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown CarrySkillLog = ((BaseUnityPlugin)this).Logger; CarrySkillType = SkillManager.Instance.AddSkill(new SkillConfig { Identifier = "com.shadymods.carryskill.carry_weight_v1", Name = "Carry Weight", Description = "Gain skill while sprinting or swimming with a heavy load (50%+ of max weight). No XP while over-encumbered. Heavier loads train faster. Each level adds +3 carry weight (up to +300 at level 100).", IncreaseStep = 1f }); Harmony val = new Harmony("shadymods.carryskill.carry_weight"); TryPatchGetMaxCarryWeight(val); TryPatchUpdateWalking(val); TryPatchSwimming(val); try { val.PatchAll(); } catch (Exception ex) { CarrySkillLog.LogError((object)("CarrySkill: PatchAll failed: " + ex)); } Game.isModded = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Carry Weight Skill loaded."); } private static void TryPatchSwimming(Harmony harmony) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Expected O, but got Unknown Type[] array = new Type[2] { typeof(Vector3), typeof(float) }; MethodBase methodBase = AccessTools.DeclaredMethod(typeof(Player), "OnSwimming", array, (Type[])null) ?? AccessTools.DeclaredMethod(typeof(Character), "OnSwimming", array, (Type[])null) ?? AccessTools.DeclaredMethod(typeof(Humanoid), "OnSwimming", array, (Type[])null); if (methodBase != null) { MethodInfo methodInfo = AccessTools.Method(typeof(CarrySkillPatches), "OnSwimming_Postfix", new Type[3] { typeof(Character), typeof(Vector3), typeof(float) }, (Type[])null); if (methodInfo == null) { CarrySkillLog.LogError((object)"CarrySkill: Could not resolve OnSwimming_Postfix — swim carry XP will not apply."); return; } try { harmony.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return; } catch (Exception ex) { CarrySkillLog.LogError((object)("CarrySkill: Manual OnSwimming patch failed: " + ex)); return; } } MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(Character), "UpdateSwimming", new Type[1] { typeof(float) }, (Type[])null); if (methodInfo2 == null) { CarrySkillLog.LogError((object)"CarrySkill: Could not resolve Player/Character.OnSwimming or Character.UpdateSwimming — swim carry XP will not apply."); return; } MethodInfo methodInfo3 = AccessTools.Method(typeof(CarrySkillPatches), "UpdateSwimming_Postfix", new Type[2] { typeof(Character), typeof(float) }, (Type[])null); if (methodInfo3 == null) { CarrySkillLog.LogError((object)"CarrySkill: Could not resolve UpdateSwimming_Postfix — swim carry XP will not apply."); return; } try { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex2) { CarrySkillLog.LogError((object)("CarrySkill: Manual UpdateSwimming patch failed: " + ex2)); } } private static void TryPatchGetMaxCarryWeight(Harmony harmony) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Player), "GetMaxCarryWeight", Type.EmptyTypes, (Type[])null) ?? AccessTools.Method(typeof(Player), "GetMaxCarryWeight", Type.EmptyTypes, (Type[])null); if (methodInfo == null) { CarrySkillLog.LogError((object)"CarrySkill: Could not resolve Player.GetMaxCarryWeight() — carry weight bonus will not apply."); return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(CarrySkillPatches), "GetMaxCarryWeight_Postfix", new Type[2] { typeof(Player), typeof(float).MakeByRefType() }, (Type[])null); if (methodInfo2 == null) { CarrySkillLog.LogError((object)"CarrySkill: Could not resolve GetMaxCarryWeight_Postfix — carry weight bonus will not apply."); return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { CarrySkillLog.LogError((object)("CarrySkill: Manual GetMaxCarryWeight patch failed: " + ex)); } } private static void TryPatchUpdateWalking(Harmony harmony) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Character), "UpdateWalking", new Type[1] { typeof(float) }, (Type[])null) ?? AccessTools.Method(typeof(Character), "UpdateWalking", new Type[1] { typeof(float) }, (Type[])null); if (methodInfo == null) { CarrySkillLog.LogError((object)"CarrySkill: Could not resolve Character.UpdateWalking(float) — run/sprint carry XP will not apply."); return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(CarrySkillPatches), "UpdateWalking_Postfix", new Type[2] { typeof(Character), typeof(float) }, (Type[])null); if (methodInfo2 == null) { CarrySkillLog.LogError((object)"CarrySkill: Could not resolve UpdateWalking_Postfix — run/sprint carry XP will not apply."); return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { CarrySkillLog.LogError((object)("CarrySkill: Manual UpdateWalking patch failed: " + ex)); } } } } namespace CarrySkill.Patches { public static class CarrySkillPatches { private const float MinFill = 0.5f; private const float MaxLerpFill = 1f; private const float SwimVelThreshold = 0.1f; private const float SwimVelThresholdHeavy = 0.001f; private static float _lastZeroGainWarningTime = -1000f; private static bool _loggedMissingSkillsGetSkill; private static readonly MethodInfo SkillsGetSkill = AccessTools.Method(typeof(Skills), "GetSkill", new Type[1] { typeof(SkillType) }, (Type[])null); internal static void GetMaxCarryWeight_Postfix(Player __instance, ref float __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && ((Character)__instance).IsPlayer()) { Skills skills = ((Character)__instance).GetSkills(); if (!((Object)(object)skills == (Object)null)) { float skillLevel = skills.GetSkillLevel(CarrySkillPlugin.CarrySkillType); __result += skillLevel * 3f; } } } internal static void UpdateWalking_Postfix(Character __instance, float dt) { if (!(dt <= 0f)) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !((Character)val).IsDead() && !((Character)val).IsSwimming() && !((Character)val).IsEncumbered() && Traverse.Create((object)__instance).Field("m_running").GetValue<bool>()) { TryApplyRunCarryXp(val, dt); } } } internal static void OnSwimming_Postfix(Character __instance, Vector3 targetVel, float dt) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !((Character)val).IsDead() && !((Character)val).IsEncumbered() && TryGetFill(val, out var fill)) { float num = ((fill >= 0.5f) ? 0.001f : 0.1f); bool flag = ((Vector3)(ref targetVel)).magnitude > num; if (!flag && fill >= 0.5f && TryGetSwimMoveSpeed(val, out var horizontalSpeed)) { flag = horizontalSpeed > num; } if (flag) { TryApplySwimCarryXp(val, dt); } } } internal static void UpdateSwimming_Postfix(Character __instance, float dt) { if (dt <= 0f) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !((Character)val).IsDead() && ((Character)val).IsSwimming() && !((Character)val).IsEncumbered() && TryGetSwimMoveSpeed(val, out var horizontalSpeed)) { float fill; float num = ((TryGetFill(val, out fill) && fill >= 0.5f) ? 0.001f : 0.1f); if (!(horizontalSpeed <= num)) { TryApplySwimCarryXp(val, dt); } } } private static bool TryGetSwimMoveSpeed(Player player, out float horizontalSpeed) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) horizontalSpeed = 0f; Rigidbody value = Traverse.Create((object)player).Field("m_body").GetValue<Rigidbody>(); if ((Object)(object)value == (Object)null) { return false; } Vector3 linearVelocity = value.linearVelocity; linearVelocity.y = 0f; horizontalSpeed = ((Vector3)(ref linearVelocity)).magnitude; return true; } private static void TryApplyRunCarryXp(Player player, float dt) { Skills skills = ((Character)player).GetSkills(); if (!((Object)(object)skills == (Object)null) && !(dt <= 0f) && TryGetFill(player, out var fill) && !(fill < 0.5f)) { float num = WeightFillMultiplier(fill); float raiseFactor = GetIncreaseStep(skills, (SkillType)102) * num * dt; ApplyCarrySkillXp(player, skills, raiseFactor); } } private static void TryApplySwimCarryXp(Player player, float dt) { Skills skills = ((Character)player).GetSkills(); if (!((Object)(object)skills == (Object)null) && !(dt <= 0f) && TryGetFill(player, out var fill) && !(fill < 0.5f)) { float num = WeightFillMultiplier(fill); float raiseFactor = GetIncreaseStep(skills, (SkillType)103) * num * dt; ApplyCarrySkillXp(player, skills, raiseFactor); } } private static bool TryGetFill(Player player, out float fill) { fill = 0f; float maxCarryWeight = player.GetMaxCarryWeight(); if (maxCarryWeight <= 0f) { return false; } float totalWeight = ((Humanoid)player).GetInventory().GetTotalWeight(); fill = Mathf.Clamp01(totalWeight / maxCarryWeight); return true; } private static void ApplyCarrySkillXp(Player player, Skills skills, float raiseFactor) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Skill orCreateCarrySkill = GetOrCreateCarrySkill(skills); if (orCreateCarrySkill == null) { if (!_loggedMissingSkillsGetSkill && CarrySkillPlugin.CarrySkillLog != null) { _loggedMissingSkillsGetSkill = true; CarrySkillPlugin.CarrySkillLog.LogError((object)"CarrySkill: Skills.GetSkill reflection failed — carry XP may not apply correctly."); } ((Character)player).RaiseSkill(CarrySkillPlugin.CarrySkillType, raiseFactor); return; } float nextLevelRequirement = GetNextLevelRequirement(orCreateCarrySkill); float accumulator = orCreateCarrySkill.m_accumulator; float level = orCreateCarrySkill.m_level; ((Character)player).RaiseSkill(CarrySkillPlugin.CarrySkillType, raiseFactor); float num = ComputeAccumulatorGain(accumulator, level, nextLevelRequirement, orCreateCarrySkill.m_accumulator, orCreateCarrySkill.m_level); if (raiseFactor > 1E-08f && num <= 0f && CarrySkillPlugin.CarrySkillLog != null && Time.time - _lastZeroGainWarningTime > 30f) { _lastZeroGainWarningTime = Time.time; CarrySkillPlugin.CarrySkillLog.LogWarning((object)($"CarryWeight: RaiseSkill had no accumulator gain (factor={raiseFactor:E3}). " + "At skill 100, or if a status blocks skill XP, this is normal.")); } } internal static Skill GetOrCreateCarrySkill(Skills skills) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) Skill val = TryGetCarrySkillInstance(skills); if (val != null) { return val; } if (SkillsGetSkill == null) { return null; } object? obj = SkillsGetSkill.Invoke(skills, new object[1] { CarrySkillPlugin.CarrySkillType }); return (Skill)((obj is Skill) ? obj : null); } internal static Skill TryGetCarrySkillInstance(Skills skills) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected I4, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) Dictionary<SkillType, Skill> value = Traverse.Create((object)skills).Field("m_skillData").GetValue<Dictionary<SkillType, Skill>>(); if (value == null) { return null; } SkillType carrySkillType = CarrySkillPlugin.CarrySkillType; if (value.TryGetValue(carrySkillType, out var value2)) { return value2; } int num = (int)carrySkillType; if (num != 0 && num != int.MinValue) { SkillType val = (SkillType)Math.Abs(num); if (val != carrySkillType && value.TryGetValue(val, out value2)) { return value2; } SkillType val2 = (SkillType)(-num); if (val2 != carrySkillType && value.TryGetValue(val2, out value2)) { return value2; } } return null; } private static float GetNextLevelRequirement(Skill skill) { return Traverse.Create((object)skill).Method("GetNextLevelRequirement", Array.Empty<object>()).GetValue<float>(); } private static float ComputeAccumulatorGain(float accBefore, float levelBefore, float nextReqBefore, float accAfter, float levelAfter) { if (levelAfter > levelBefore) { return nextReqBefore - accBefore + accAfter; } return accAfter - accBefore; } private static float WeightFillMultiplier(float fillClamped01) { if (fillClamped01 >= 1f) { return 2f; } float num = (fillClamped01 - 0.5f) / 0.5f; return Mathf.Lerp(1f, 2f, num); } private static float GetIncreaseStep(Skills skills, SkillType type) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (skills?.m_skills == null) { return 1f; } foreach (SkillDef skill in skills.m_skills) { if (skill.m_skill == type) { return skill.m_increseStep; } } return 1f; } } [HarmonyPatch(typeof(Character), "Jump")] internal static class CharacterJumpMessageCompatPatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo shim = AccessTools.Method(typeof(PlayerMessageCompat), "ShowFromCharacter", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (shim != null && instruction.opcode == OpCodes.Callvirt && instruction.operand is MethodInfo { Name: "Message" } methodInfo && methodInfo.DeclaringType == typeof(Character)) { yield return new CodeInstruction(OpCodes.Call, (object)shim); } else { yield return instruction; } } } } [HarmonyPatch(typeof(InventoryGui), "OnTabCraftPressed")] internal static class InventoryGuiTabCraftGuardPatch { [HarmonyPrefix] private static bool Prefix(InventoryGui __instance) { if (__instance.InCraftTab()) { return false; } return true; } } [HarmonyPatch(typeof(InventoryGui), "OnTabUpgradePressed")] internal static class InventoryGuiTabUpgradeGuardPatch { [HarmonyPrefix] private static bool Prefix(InventoryGui __instance) { if (!__instance.InCraftTab()) { return false; } return true; } } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] internal static class MultiCraftInputFixPatch { private static FieldRef<InventoryGui, bool> _multiCrafting; private static FieldRef<InventoryGui, ItemData> _craftUpgradeItem; [HarmonyPostfix] private static void Postfix(InventoryGui __instance) { EnsureFields(); if (_craftUpgradeItem.Invoke(__instance) == null) { bool button = ZInput.GetButton("AltPlace"); bool num = ZInput.IsGamepadActive(); bool flag = _multiCrafting.Invoke(__instance); if (!num && flag && !button) { _multiCrafting.Invoke(__instance) = false; } } } private static void EnsureFields() { if (_multiCrafting == null) { _multiCrafting = AccessTools.FieldRefAccess<InventoryGui, bool>("m_multiCrafting"); _craftUpgradeItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_craftUpgradeItem"); } } } internal static class PlayerMessageCompat { internal static void ShowFromCharacter(Character character, MessageType type, string msg, int amount = 0, Sprite icon = null) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Show((Player)(object)((character is Player) ? character : null), type, msg, amount, icon); } internal static void Show(Player player, MessageType type, string msg, int amount = 0, Sprite icon = null) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected I4, but got Unknown if ((Object)(object)player == (Object)null || (Object)(object)MessageHud.instance == (Object)null) { return; } ZNetView component = ((Component)player).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { if (!component.IsOwner()) { component.InvokeRPC("Message", new object[3] { (int)type, msg, amount }); } else { MessageHud.instance.ShowMessage(type, msg, amount, icon, false, true); } } } } [HarmonyPatch(typeof(Player), "Message")] internal static class PlayerMessageCompatPatch { [HarmonyPrefix] private static bool Prefix(Player __instance, MessageType type, string msg, int amount, Sprite icon) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayerMessageCompat.Show(__instance, type, msg, amount, icon); return false; } } [HarmonyPatch(typeof(InventoryGui), "RepairOneItem")] internal static class RepairOneItemCompatPatch { private static FieldRef<InventoryGui, List<ItemData>> _tempWornItems; private static MethodInfo _canRepair; [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(InventoryGui __instance) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } try { return RunRepair(__instance, localPlayer); } catch (Exception ex) { ManualLogSource carrySkillLog = CarrySkillPlugin.CarrySkillLog; if (carrySkillLog != null) { carrySkillLog.LogWarning((object)("RepairOneItemCompatPatch: " + ex.Message)); } return false; } } private static bool RunRepair(InventoryGui __instance, Player player) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) EnsureReflection(__instance); CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); if (((Object)(object)currentCraftingStation == (Object)null && !player.NoCostCheat()) || ((Object)(object)currentCraftingStation != (Object)null && !currentCraftingStation.CheckUsable(player, false))) { return false; } List<ItemData> list = _tempWornItems.Invoke(__instance); list.Clear(); ((Humanoid)player).GetInventory().GetWornItems(list); foreach (ItemData item in list) { if ((bool)_canRepair.Invoke(__instance, new object[1] { item })) { ((Character)player).RaiseSkill((SkillType)107, 1f - item.m_durability / item.GetMaxDurability()); item.m_durability = item.GetMaxDurability(); if ((Object)(object)currentCraftingStation != (Object)null) { currentCraftingStation.m_repairItemDoneEffects.Create(((Component)currentCraftingStation).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } PlayerMessageCompat.Show(player, (MessageType)2, LocalizeRepaired(item.m_shared.m_name)); return false; } } PlayerMessageCompat.Show(player, (MessageType)2, "No more item to repair"); return false; } private static void EnsureReflection(InventoryGui gui) { if (_tempWornItems == null) { _tempWornItems = AccessTools.FieldRefAccess<InventoryGui, List<ItemData>>("m_tempWornItems"); } if (_canRepair == null) { _canRepair = AccessTools.Method(typeof(InventoryGui), "CanRepair", new Type[1] { typeof(ItemData) }, (Type[])null); } } private static string LocalizeRepaired(string itemName) { Type type = AccessTools.TypeByName("Localization"); object obj = (type?.GetProperty("instance", BindingFlags.Static | BindingFlags.Public))?.GetValue(null, null); MethodInfo methodInfo = type?.GetMethod("Localize", new Type[2] { typeof(string), typeof(string) }); if (obj != null && methodInfo != null) { return (string)methodInfo.Invoke(obj, new object[2] { "$msg_repaired", itemName }); } return "$msg_repaired " + itemName; } } [HarmonyPatch(typeof(InventoryGui), "RepairOneItem")] internal static class RepairOneItemMessageCompatPatch { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo shim = AccessTools.Method(typeof(PlayerMessageCompat), "ShowFromCharacter", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (shim != null && instruction.opcode == OpCodes.Callvirt && instruction.operand is MethodInfo { Name: "Message" } methodInfo && typeof(Character).IsAssignableFrom(methodInfo.DeclaringType)) { yield return new CodeInstruction(OpCodes.Call, (object)shim); } else { yield return instruction; } } } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] internal static class SkillsRaiseSkillCompatPatch { private static MethodInfo _rebalanceSkills; private static MethodInfo _getSkill; private static MethodInfo _goganLogEvent; [HarmonyPrefix] private static bool Prefix(Skills __instance, SkillType skillType, float factor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if ((int)skillType == 0) { return true; } try { EnsureReflection(); if (_getSkill == null) { return true; } Skill val = ResolveSkill(__instance, skillType); if (val == null) { return true; } float level = val.m_level; if (val.Raise(factor)) { if (Traverse.Create((object)__instance).Field("m_useSkillCap").GetValue<bool>() && _rebalanceSkills != null) { _rebalanceSkills.Invoke(__instance, new object[1] { skillType }); } Player value = Traverse.Create((object)__instance).Field("m_player").GetValue<Player>(); if (value != null) { value.OnSkillLevelup(skillType, val.m_level); } MessageType type = (MessageType)(((int)level != 0) ? 1 : 2); string msg = "$msg_skillup $skill_" + ((object)Unsafe.As<SkillType, SkillType>(ref val.m_info.m_skill)/*cast due to .constrained prefix*/).ToString().ToLower() + ": " + (int)val.m_level; ShowSkillMessage(value, type, msg, val.m_info.m_icon); TryGoganLogEvent(skillType, val.m_level); } return false; } catch (Exception ex) { ManualLogSource carrySkillLog = CarrySkillPlugin.CarrySkillLog; if (carrySkillLog != null) { carrySkillLog.LogWarning((object)("SkillsRaiseSkillCompatPatch: " + ex.Message)); } return true; } } private static Skill ResolveSkill(Skills __instance, SkillType skillType) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected I4, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected I4, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown EnsureReflection(); if (_getSkill == null) { return null; } Skill val = (Skill)_getSkill.Invoke(__instance, new object[1] { skillType }); if (val != null) { return val; } int num = (int)skillType; if (num != 0 && num != int.MinValue) { SkillType val2 = (SkillType)Math.Abs(num); if (val2 != skillType) { val = (Skill)_getSkill.Invoke(__instance, new object[1] { val2 }); if (val != null) { return val; } } SkillType val3 = (SkillType)(-num); if (val3 != skillType) { val = (Skill)_getSkill.Invoke(__instance, new object[1] { val3 }); if (val != null) { return val; } } } if (skillType == CarrySkillPlugin.CarrySkillType || Math.Abs(num) == Math.Abs((int)CarrySkillPlugin.CarrySkillType)) { return CarrySkillPatches.GetOrCreateCarrySkill(__instance); } return null; } private static void EnsureReflection() { if (!(_getSkill != null)) { _getSkill = AccessTools.DeclaredMethod(typeof(Skills), "GetSkill", new Type[1] { typeof(SkillType) }, (Type[])null); _rebalanceSkills = AccessTools.DeclaredMethod(typeof(Skills), "RebalanceSkills", new Type[1] { typeof(SkillType) }, (Type[])null); _goganLogEvent = AccessTools.TypeByName("Gogan")?.GetMethod("LogEvent", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(string), typeof(string), typeof(string), typeof(int) }, null); } } private static void ShowSkillMessage(Player player, MessageType type, string msg, Sprite icon) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected I4, but got Unknown if ((Object)(object)player == (Object)null || (Object)(object)MessageHud.instance == (Object)null) { return; } ZNetView value = Traverse.Create((object)player).Field("m_nview").GetValue<ZNetView>(); if (!((Object)(object)value == (Object)null) && value.IsValid()) { if (!value.IsOwner()) { value.InvokeRPC("Message", new object[3] { (int)type, msg, 0 }); } else { MessageHud.instance.ShowMessage(type, msg, 0, icon, false, true); } } } private unsafe static void TryGoganLogEvent(SkillType skillType, float level) { if (_goganLogEvent == null) { return; } try { _goganLogEvent.Invoke(null, new object[4] { "Game", "Levelup", ((object)(*(SkillType*)(&skillType))/*cast due to .constrained prefix*/).ToString(), (int)level }); } catch { } } } }