using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WeaponCraftingMod")]
[assembly: AssemblyDescription("Valheim mod adding SES/Perk Tiers with Smithing skill")]
[assembly: AssemblyCompany("proflupin")]
[assembly: AssemblyProduct("WeaponCraftingMod")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("proflupin.weaponcrafting", "WeaponCrafting", "1.0.0")]
public class WeaponCraftingMod : BaseUnityPlugin
{
private const string DataFileName = "weaponcrafting_smithing.json";
private SmithingDataStore _store;
private string DataFilePath => Path.Combine(Paths.ConfigPath, "weaponcrafting_smithing.json");
private void Awake()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
Harmony val = new Harmony("proflupin.weaponcrafting");
val.PatchAll();
LoadData();
try
{
Type typeFromHandle = typeof(ZRoutedRpc);
ZRoutedRpc instance = ZRoutedRpc.instance;
if (instance != null)
{
MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
if (methodInfo.Name != "Register")
{
continue;
}
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length == 2 && !(parameters[0].ParameterType != typeof(string)))
{
Type parameterType = parameters[1].ParameterType;
bool flag = false;
try
{
MethodInfo method = ((object)this).GetType().GetMethod("OnMasterForgeRpc_Long", BindingFlags.Instance | BindingFlags.NonPublic);
Delegate @delegate = Delegate.CreateDelegate(parameterType, this, method);
methodInfo.Invoke(instance, new object[2] { "WeaponCrafting_MasterForge", @delegate });
flag = true;
}
catch
{
}
if (flag)
{
break;
}
try
{
MethodInfo method2 = ((object)this).GetType().GetMethod("OnMasterForgeRpc_ZRpc", BindingFlags.Instance | BindingFlags.NonPublic);
Delegate delegate2 = Delegate.CreateDelegate(parameterType, this, method2);
methodInfo.Invoke(instance, new object[2] { "WeaponCrafting_MasterForge", delegate2 });
flag = true;
}
catch
{
}
if (flag)
{
break;
}
}
}
}
}
catch
{
}
try
{
SetupUpgradePatches(val);
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to setup upgrade patches: {arg}");
}
}
private void OnDestroy()
{
SaveData();
}
private void LoadData()
{
try
{
if (File.Exists(DataFilePath))
{
string text = File.ReadAllText(DataFilePath);
_store = JsonConvert.DeserializeObject<SmithingDataStore>(text) ?? new SmithingDataStore();
}
else
{
_store = new SmithingDataStore();
}
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to load data: {arg}");
_store = new SmithingDataStore();
}
}
private void SaveData()
{
try
{
string directoryName = Path.GetDirectoryName(DataFilePath);
if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
string contents = JsonConvert.SerializeObject((object)_store, (Formatting)1);
File.WriteAllText(DataFilePath, contents);
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to save data: {arg}");
}
}
private void OnMasterForgeRpc_Long(long sender, ZPackage pkg)
{
try
{
if (pkg != null)
{
string text = pkg.ReadString();
string text2 = pkg.ReadString();
string text3 = pkg.ReadString();
string text4 = ((Random.Range(0, 100) >= 50) ? ("The " + text2 + " of " + text + " shall be revered throughout the ages") : ("Odin smiles upon " + text + "'s " + text2 + ", bestowing his great power upon it"));
if ((Object)(object)MessageHud.instance != (Object)null)
{
MessageHud.instance.ShowMessage((MessageType)2, text4, 0, (Sprite)null, false);
}
Debug.Log((object)("[WeaponCrafting] Master-forge broadcast: " + text + " -> " + text2 + " (boon: " + text3 + ")"));
}
}
catch
{
}
}
private void OnMasterForgeRpc_ZRpc(ZRpc rpc, ZPackage pkg)
{
try
{
if (pkg != null)
{
string text = pkg.ReadString();
string text2 = pkg.ReadString();
string text3 = pkg.ReadString();
string text4 = ((Random.Range(0, 100) >= 50) ? ("The " + text2 + " of " + text + " shall be revered throughout the ages") : ("Odin smiles upon " + text + "'s " + text2 + ", bestowing his great power upon it"));
if ((Object)(object)MessageHud.instance != (Object)null)
{
MessageHud.instance.ShowMessage((MessageType)2, text4, 0, (Sprite)null, false);
}
Debug.Log((object)("[WeaponCrafting] Master-forge broadcast: " + text + " -> " + text2 + " (boon: " + text3 + ")"));
}
}
catch
{
}
}
public void AddSmithingXP(string playerName, int xp)
{
if (!string.IsNullOrEmpty(playerName) && xp > 0)
{
SmithingEntry orCreate = _store.GetOrCreate(playerName);
orCreate.XP += xp;
orCreate.Level = ComputeLevelFromXP(orCreate.XP);
SaveData();
}
}
private int ComputeLevelFromXP(int xp)
{
int i = 1;
int num = xp;
for (; i < 100; i++)
{
int num2 = (int)Math.Floor(80.0 * Math.Pow(1.05, i - 1));
if (num < num2)
{
break;
}
num -= num2;
}
if (i < 1)
{
i = 1;
}
if (i > 100)
{
i = 100;
}
return i;
}
public SmithingEntry GetSmithingFor(string playerName)
{
return _store.GetOrCreate(playerName);
}
private void SetupUpgradePatches(Harmony harmony)
{
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Expected O, but got Unknown
try
{
Assembly assembly = typeof(Player).Assembly;
List<MethodInfo> list = new List<MethodInfo>();
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsGenericType || type.IsInterface)
{
continue;
}
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
string text = methodInfo.Name.ToLower();
if ((text.Contains("upgrade") || text.Contains("upgradeitem") || text.Contains("do_upgrade") || text.Contains("upgrade_piece") || text.Contains("upgradepiece")) && methodInfo.ReturnType == typeof(void))
{
list.Add(methodInfo);
}
}
}
MethodInfo method = typeof(WeaponCraftingMod).GetMethod("Upgrade_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
int num = 0;
foreach (MethodInfo item in list)
{
try
{
HarmonyMethod val = new HarmonyMethod(method);
harmony.Patch((MethodBase)item, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
((BaseUnityPlugin)this).Logger.LogInfo((object)("WeaponCrafting: patched upgrade method " + item.DeclaringType.FullName + "." + item.Name));
num++;
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to patch {item.DeclaringType.FullName}.{item.Name}: {arg}");
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)$"WeaponCrafting: patched {num} upgrade methods");
}
catch (Exception arg2)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: SetupUpgradePatches error: {arg2}");
}
}
private static int GetPieceLevel(Piece piece)
{
if ((Object)(object)piece == (Object)null)
{
return 1;
}
try
{
FieldInfo field = typeof(Piece).GetField("m_level", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
object value = field.GetValue(piece);
if (value is int)
{
int num = (int)value;
return (num <= 0) ? 1 : num;
}
}
}
catch
{
}
return 1;
}
private static void Upgrade_Postfix(object __instance, object[] __args)
{
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
try
{
Player val = null;
Player val2 = (Player)((__instance is Player) ? __instance : null);
if (val2 != null)
{
val = val2;
}
if ((Object)(object)val == (Object)null && __args != null)
{
foreach (object obj in __args)
{
Player val3 = (Player)((obj is Player) ? obj : null);
if (val3 != null)
{
val = val3;
break;
}
}
}
if ((Object)(object)val == (Object)null)
{
val = Player.m_localPlayer;
}
if ((Object)(object)val == (Object)null)
{
return;
}
Piece val4 = null;
Piece val5 = null;
try
{
Piece[] array = Object.FindObjectsOfType<Piece>();
float num = 999f;
float num2 = 999f;
Piece[] array2 = array;
foreach (Piece val6 in array2)
{
if ((Object)(object)val6 == (Object)null || (Object)(object)((Component)val6).gameObject == (Object)null)
{
continue;
}
float num3 = Vector3.Distance(((Component)val6).transform.position, ((Component)val).transform.position);
if (!(num3 > 3f))
{
string text = ((Object)((Component)val6).gameObject).name.ToLower();
if ((text.Contains("blackforge") || text.Contains("forge_black")) && num3 < num2)
{
val5 = val6;
num2 = num3;
}
if (text.Contains("forge") && !text.Contains("black") && num3 < num)
{
val4 = val6;
num = num3;
}
}
}
}
catch
{
}
WeaponCraftingMod component = Chainloader.ManagerObject.GetComponent<WeaponCraftingMod>();
if (!((Object)(object)component == (Object)null))
{
if ((Object)(object)val5 != (Object)null)
{
int pieceLevel = GetPieceLevel(val5);
int num4 = 13 + 2 * pieceLevel;
component.AddSmithingXP(val.GetPlayerName(), num4);
Debug.Log((object)$"[WeaponCrafting] Upgrade near black forge level {pieceLevel}: +{num4} XP to {val.GetPlayerName()}");
}
else if ((Object)(object)val4 != (Object)null)
{
int pieceLevel2 = GetPieceLevel(val4);
int num5 = 8 + 2 * pieceLevel2;
component.AddSmithingXP(val.GetPlayerName(), num5);
Debug.Log((object)$"[WeaponCrafting] Upgrade near forge level {pieceLevel2}: +{num5} XP to {val.GetPlayerName()}");
}
}
}
catch
{
}
}
private void BroadcastMasterForgeRpc(string playerName, string itemName, string boon)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
try
{
ZPackage val = new ZPackage();
val.Write(playerName);
val.Write(itemName);
val.Write(boon ?? string.Empty);
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "WeaponCrafting_MasterForge", new object[1] { val });
Debug.Log((object)("[WeaponCrafting] Broadcast master-forge RPC: " + playerName + " -> " + itemName));
}
catch (Exception arg)
{
Debug.LogWarning((object)$"[WeaponCrafting] BroadcastMasterForgeRpc error: {arg}");
}
}
private static bool InventoryBelongsTo(Inventory inv, params string[] keywords)
{
try
{
if (inv == null)
{
return false;
}
Type type = ((object)inv).GetType();
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
try
{
object value = fieldInfo.GetValue(inv);
if (value == null)
{
continue;
}
GameObject val = (GameObject)((value is GameObject) ? value : null);
string[] array;
if (val != null)
{
string text = ((Object)val).name.ToLower();
array = keywords;
foreach (string text2 in array)
{
if (text.Contains(text2.ToLower()))
{
return true;
}
}
continue;
}
Component val2 = (Component)((value is Component) ? value : null);
if (val2 != null)
{
string text3 = ((Object)val2.gameObject).name.ToLower();
array = keywords;
foreach (string text4 in array)
{
if (text3.Contains(text4.ToLower()))
{
return true;
}
}
continue;
}
string text5 = value.ToString();
if (string.IsNullOrEmpty(text5))
{
continue;
}
string text6 = text5.ToLower();
array = keywords;
foreach (string text7 in array)
{
if (text6.Contains(text7.ToLower()))
{
return true;
}
}
}
catch
{
}
}
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (PropertyInfo propertyInfo in properties)
{
try
{
object value2 = propertyInfo.GetValue(inv);
if (value2 == null)
{
continue;
}
GameObject val3 = (GameObject)((value2 is GameObject) ? value2 : null);
string[] array;
if (val3 != null)
{
string text8 = ((Object)val3).name.ToLower();
array = keywords;
foreach (string text9 in array)
{
if (text8.Contains(text9.ToLower()))
{
return true;
}
}
continue;
}
Component val4 = (Component)((value2 is Component) ? value2 : null);
if (val4 != null)
{
string text10 = ((Object)val4.gameObject).name.ToLower();
array = keywords;
foreach (string text11 in array)
{
if (text10.Contains(text11.ToLower()))
{
return true;
}
}
continue;
}
string text12 = value2.ToString();
if (string.IsNullOrEmpty(text12))
{
continue;
}
string text13 = text12.ToLower();
array = keywords;
foreach (string text14 in array)
{
if (text13.Contains(text14.ToLower()))
{
return true;
}
}
}
catch
{
}
}
}
catch
{
}
return false;
}
public void ApplySmithingOnCreate(Player player, ItemData item)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_0313: Unknown result type (might be due to invalid IL or missing references)
//IL_0331: Unknown result type (might be due to invalid IL or missing references)
//IL_034f: Unknown result type (might be due to invalid IL or missing references)
//IL_036d: Unknown result type (might be due to invalid IL or missing references)
//IL_038b: Unknown result type (might be due to invalid IL or missing references)
//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0422: Unknown result type (might be due to invalid IL or missing references)
//IL_040a: Unknown result type (might be due to invalid IL or missing references)
//IL_044a: Unknown result type (might be due to invalid IL or missing references)
//IL_0432: Unknown result type (might be due to invalid IL or missing references)
//IL_0472: Unknown result type (might be due to invalid IL or missing references)
//IL_045a: Unknown result type (might be due to invalid IL or missing references)
//IL_049a: Unknown result type (might be due to invalid IL or missing references)
//IL_0482: Unknown result type (might be due to invalid IL or missing references)
//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
//IL_0512: Unknown result type (might be due to invalid IL or missing references)
//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0525: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)player == (Object)null || item == null)
{
return;
}
int level = GetSmithingFor(player.GetPlayerName()).Level;
_ = item.m_shared.m_damages;
bool flag = item.m_shared.m_damages.m_slash > 0f || item.m_shared.m_damages.m_blunt > 0f || item.m_shared.m_damages.m_pierce > 0f;
bool flag2 = item.m_shared.m_armor > 0f || item.m_shared.m_blockPower > 0f;
int num = Random.Range(5, 9) + Mathf.FloorToInt((float)level / 3f) + 2;
if (item.m_durability > 0f)
{
item.m_durability += (float)num;
}
if (item.m_shared.m_maxDurability > 0f)
{
SharedData shared = item.m_shared;
shared.m_maxDurability += (float)num;
}
if (flag)
{
int num2 = Random.Range(3, 6) + Mathf.Max(2, Mathf.FloorToInt((float)level / 5f));
DamageTypes damages = item.m_shared.m_damages;
if (damages.m_slash > 0f)
{
damages.m_slash += num2;
}
if (damages.m_blunt > 0f)
{
damages.m_blunt += num2;
}
if (damages.m_pierce > 0f)
{
damages.m_pierce += num2;
}
if (damages.m_fire > 0f)
{
damages.m_fire += num2;
}
if (damages.m_frost > 0f)
{
damages.m_frost += num2;
}
if (damages.m_poison > 0f)
{
damages.m_poison += num2;
}
if (damages.m_lightning > 0f)
{
damages.m_lightning += num2;
}
if (damages.m_spirit > 0f)
{
damages.m_spirit += num2;
}
}
if (flag2)
{
int num3 = Random.Range(4, 7) + Mathf.Max(2, Mathf.FloorToInt((float)level / 4f));
SharedData shared2 = item.m_shared;
shared2.m_armor += (float)num3;
SharedData shared3 = item.m_shared;
shared3.m_blockPower += (float)num3;
}
int num4 = Mathf.Clamp(level, 1, 100);
int num5 = ((num4 <= 40) ? 40 : ((num4 <= 75) ? 50 : 60));
if (Random.Range(0, 100) >= num5)
{
return;
}
if (item.m_shared.m_maxDurability > 0f)
{
SharedData shared4 = item.m_shared;
shared4.m_maxDurability += 20f;
}
DamageTypes damages2 = item.m_shared.m_damages;
if (damages2.m_slash > 0f)
{
damages2.m_slash += 5f;
}
if (damages2.m_blunt > 0f)
{
damages2.m_blunt += 5f;
}
if (damages2.m_pierce > 0f)
{
damages2.m_pierce += 5f;
}
if (damages2.m_fire > 0f)
{
damages2.m_fire += 5f;
}
if (damages2.m_frost > 0f)
{
damages2.m_frost += 5f;
}
if (damages2.m_poison > 0f)
{
damages2.m_poison += 5f;
}
if (damages2.m_lightning > 0f)
{
damages2.m_lightning += 5f;
}
if (damages2.m_spirit > 0f)
{
damages2.m_spirit += 5f;
}
int num6 = 40 + Mathf.FloorToInt((float)level / 3f);
int num7 = Random.Range(0, 100);
string text = null;
if (num7 < num6)
{
if (flag)
{
int num8 = Random.Range(0, 100);
if (num8 < 40)
{
text = "Razor";
DamageTypes damages3 = item.m_shared.m_damages;
if (damages3.m_slash > 0f)
{
damages3.m_slash = Mathf.FloorToInt(damages3.m_slash * 1.25f);
}
if (damages3.m_blunt > 0f)
{
damages3.m_blunt = Mathf.FloorToInt(damages3.m_blunt * 1.25f);
}
if (damages3.m_pierce > 0f)
{
damages3.m_pierce = Mathf.FloorToInt(damages3.m_pierce * 1.25f);
}
if (damages3.m_fire > 0f)
{
damages3.m_fire = Mathf.FloorToInt(damages3.m_fire * 1.25f);
}
if (damages3.m_frost > 0f)
{
damages3.m_frost = Mathf.FloorToInt(damages3.m_frost * 1.25f);
}
if (damages3.m_poison > 0f)
{
damages3.m_poison = Mathf.FloorToInt(damages3.m_poison * 1.25f);
}
if (damages3.m_lightning > 0f)
{
damages3.m_lightning = Mathf.FloorToInt(damages3.m_lightning * 1.25f);
}
if (damages3.m_spirit > 0f)
{
damages3.m_spirit = Mathf.FloorToInt(damages3.m_spirit * 1.25f);
}
}
else if (num8 < 80)
{
text = "Ogre";
item.m_shared.m_attackForce = Mathf.FloorToInt(item.m_shared.m_attackForce * 1.75f);
}
else
{
text = "Goblin";
if (item.m_customData == null)
{
item.m_customData = new Dictionary<string, string>();
}
item.m_customData["GOBLIN_BOON"] = "1";
}
}
else if (flag2)
{
if (item.m_shared.m_blockPower > 0f)
{
if (Random.Range(0, 100) < 50)
{
text = "Stalwart";
item.m_shared.m_blockPower = Mathf.FloorToInt(item.m_shared.m_blockPower * 1.6f);
}
else
{
text = "Sealed";
item.m_shared.m_armor = Mathf.FloorToInt(item.m_shared.m_armor * 1.35f);
}
}
else if (Random.Range(0, 100) < 60)
{
text = "Reinforced";
item.m_shared.m_armor = Mathf.FloorToInt(item.m_shared.m_armor * 1.25f);
}
else
{
text = "Feather";
if (item.m_customData == null)
{
item.m_customData = new Dictionary<string, string>();
}
item.m_customData["FEATHER_BOON"] = "1";
}
}
}
string playerName = player.GetPlayerName();
string name = item.m_shared.m_name;
string text2 = "Odin smiles upon " + playerName + "'s " + name + ", bestowing his great power upon it";
if ((Object)(object)MessageHud.instance != (Object)null)
{
MessageHud.instance.ShowMessage((MessageType)2, text2, 0, (Sprite)null, false);
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("[WeaponCrafting] Master-forged: " + playerName + " -> " + name + " (boon: " + (text ?? "None") + ")"));
BroadcastMasterForgeRpc(playerName, name, text ?? string.Empty);
}
}
public class SmithingDataStore
{
public List<SmithingEntry> Players = new List<SmithingEntry>();
public SmithingEntry GetOrCreate(string name)
{
SmithingEntry smithingEntry = Players.Find((SmithingEntry x) => x.Name == name);
if (smithingEntry == null)
{
smithingEntry = new SmithingEntry
{
Name = name,
XP = 0,
Level = 1
};
Players.Add(smithingEntry);
}
return smithingEntry;
}
}
public class SmithingEntry
{
public string Name;
public int XP;
public int Level;
}
public static class CharacterExtensions
{
private static readonly FieldInfo RightItemField = typeof(Humanoid).GetField("m_rightItem", BindingFlags.Instance | BindingFlags.NonPublic);
public static ItemData GetRightHandItem(this Character character)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
if (val != null)
{
return (ItemData)RightItemField.GetValue(val);
}
return null;
}
}
[HarmonyPatch(typeof(Inventory), "AddItem")]
public class Inventory_AddItem_Smithing_Patch
{
private static void Postfix(ItemData item, Inventory __instance)
{
//IL_0375: Unknown result type (might be due to invalid IL or missing references)
//IL_037a: Unknown result type (might be due to invalid IL or missing references)
//IL_0298: Unknown result type (might be due to invalid IL or missing references)
//IL_029d: Unknown result type (might be due to invalid IL or missing references)
try
{
if (item == null || __instance == null)
{
return;
}
WeaponCraftingMod component = Chainloader.ManagerObject.GetComponent<WeaponCraftingMod>();
if ((Object)(object)component == (Object)null)
{
return;
}
Player localPlayer = Player.m_localPlayer;
object obj = ((object)component).GetType().GetMethod("InventoryBelongsTo", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[2]
{
__instance,
new string[1] { "kiln" }
});
bool flag = default(bool);
int num;
if (obj is bool)
{
flag = (bool)obj;
num = 1;
}
else
{
num = 0;
}
if (((uint)num & (flag ? 1u : 0u)) != 0 && item.m_shared.m_name.ToLower().Contains("wood") && (Object)(object)localPlayer != (Object)null)
{
component.AddSmithingXP(localPlayer.GetPlayerName(), 5);
Debug.Log((object)("[WeaponCrafting] Kiln fed by " + localPlayer.GetPlayerName() + ": +5 XP"));
}
obj = ((object)component).GetType().GetMethod("InventoryBelongsTo", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[2]
{
__instance,
new string[1] { "smelter" }
});
bool flag2 = default(bool);
int num2;
if (obj is bool)
{
flag2 = (bool)obj;
num2 = 1;
}
else
{
num2 = 0;
}
if (((uint)num2 & (flag2 ? 1u : 0u)) != 0)
{
string text = item.m_shared.m_name.ToLower();
if ((text.Contains("coal") || text.Contains("ore") || text.Contains("iron") || text.Contains("copper") || text.Contains("silver")) && (Object)(object)localPlayer != (Object)null)
{
component.AddSmithingXP(localPlayer.GetPlayerName(), 10);
Debug.Log((object)("[WeaponCrafting] Smelter fed by " + localPlayer.GetPlayerName() + ": +10 XP"));
}
}
obj = ((object)component).GetType().GetMethod("InventoryBelongsTo", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[2]
{
__instance,
new string[1] { "blast" }
});
bool flag3 = default(bool);
int num3;
if (obj is bool)
{
flag3 = (bool)obj;
num3 = 1;
}
else
{
num3 = 0;
}
if (((uint)num3 & (flag3 ? 1u : 0u)) != 0)
{
string text2 = item.m_shared.m_name.ToLower();
if ((text2.Contains("coal") || text2.Contains("ore") || text2.Contains("iron") || text2.Contains("copper") || text2.Contains("silver")) && (Object)(object)localPlayer != (Object)null)
{
component.AddSmithingXP(localPlayer.GetPlayerName(), 15);
Debug.Log((object)("[WeaponCrafting] Blast furnace fed by " + localPlayer.GetPlayerName() + ": +15 XP"));
}
}
if (!((Object)(object)localPlayer != (Object)null) || __instance != ((Humanoid)localPlayer).GetInventory())
{
return;
}
Vector3 position = ((Component)localPlayer).transform.position;
Piece val = null;
Piece val2 = null;
float num4 = 999f;
float num5 = 999f;
try
{
IEnumerable<Piece> enumerable = null;
MethodInfo method = typeof(Object).GetMethod("FindObjectsByType", BindingFlags.Static | BindingFlags.Public);
if (method != null)
{
try
{
MethodInfo methodInfo = (method.IsGenericMethod ? method.MakeGenericMethod(typeof(Piece)) : null);
if (methodInfo != null)
{
enumerable = (IEnumerable<Piece>)methodInfo.Invoke(null, new object[1] { 0 });
}
}
catch
{
}
}
if (enumerable == null)
{
enumerable = Object.FindObjectsOfType<Piece>();
}
foreach (Piece item2 in enumerable)
{
if ((Object)(object)item2 == (Object)null || (Object)(object)((Component)item2).gameObject == (Object)null)
{
continue;
}
float num6 = Vector3.Distance(((Component)item2).transform.position, position);
if (!(num6 > 3f))
{
string text3 = ((Object)((Component)item2).gameObject).name.ToLower();
if ((text3.Contains("blackforge") || text3.Contains("forge_black")) && num6 < num5)
{
val2 = item2;
num5 = num6;
}
if (text3.Contains("forge") && !text3.Contains("black") && num6 < num4)
{
val = item2;
num4 = num6;
}
}
}
}
catch
{
}
if ((Object)(object)val2 != (Object)null)
{
int num8 = ((!(((object)component).GetType().GetMethod("GetPieceLevel", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[1] { val2 }) is int num7)) ? 1 : num7);
int num9 = 26 + 4 * num8;
component.AddSmithingXP(localPlayer.GetPlayerName(), num9);
component.ApplySmithingOnCreate(localPlayer, item);
Debug.Log((object)$"[WeaponCrafting] Craft on black forge level {num8}: +{num9} XP to {localPlayer.GetPlayerName()}");
}
else if ((Object)(object)val != (Object)null)
{
int num11 = ((!(((object)component).GetType().GetMethod("GetPieceLevel", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[1] { val }) is int num10)) ? 1 : num10);
int num12 = 13 + 2 * num11;
component.AddSmithingXP(localPlayer.GetPlayerName(), num12);
component.ApplySmithingOnCreate(localPlayer, item);
Debug.Log((object)$"[WeaponCrafting] Craft on forge level {num11}: +{num12} XP to {localPlayer.GetPlayerName()}");
}
}
catch (Exception arg)
{
Debug.LogWarning((object)$"WeaponCrafting: Inventory.AddItem patch error: {arg}");
}
}
}
[HarmonyPatch(typeof(Humanoid), "UpdateEquipment")]
public class Humanoid_Equip_Boons_Patch
{
private static readonly Dictionary<int, float> OrigAttackSpeed = new Dictionary<int, float>();
private static readonly Dictionary<int, float> OrigMoveSpeed = new Dictionary<int, float>();
private static void Postfix(Humanoid __instance)
{
if ((Object)(object)__instance == (Object)null)
{
return;
}
try
{
ItemData rightHandItem = ((Character)(object)__instance).GetRightHandItem();
int instanceID = ((Object)__instance).GetInstanceID();
FieldInfo fieldInfo = typeof(Humanoid).GetField("m_attackSpeed", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(Humanoid).GetField("m_attackSpeedMultiplier", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo != null)
{
float value = ((fieldInfo.GetValue(__instance) is float num) ? num : 1f);
if (!OrigAttackSpeed.ContainsKey(instanceID))
{
OrigAttackSpeed[instanceID] = value;
}
float num2 = OrigAttackSpeed[instanceID];
if (rightHandItem != null && rightHandItem.m_customData != null && rightHandItem.m_customData.ContainsKey("GOBLIN_BOON"))
{
fieldInfo.SetValue(__instance, num2 * 0.85f);
}
else
{
fieldInfo.SetValue(__instance, num2);
}
}
string[] obj = new string[4] { "m_runSpeed", "m_moveSpeed", "m_walkSpeed", "m_speed" };
FieldInfo fieldInfo2 = null;
string[] array = obj;
foreach (string name in array)
{
fieldInfo2 = typeof(Humanoid).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo2 != null)
{
break;
}
}
if (fieldInfo2 != null)
{
float value2 = ((fieldInfo2.GetValue(__instance) is float num3) ? num3 : 1f);
if (!OrigMoveSpeed.ContainsKey(instanceID))
{
OrigMoveSpeed[instanceID] = value2;
}
float num4 = OrigMoveSpeed[instanceID];
if (rightHandItem != null && rightHandItem.m_customData != null && rightHandItem.m_customData.ContainsKey("FEATHER_BOON"))
{
fieldInfo2.SetValue(__instance, num4 * 1.03f);
}
else
{
fieldInfo2.SetValue(__instance, num4);
}
}
}
catch
{
}
}
}