Decompiled source of Recht v1.0.1

Recht.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Recht;

[BepInPlugin("0zzerod.recht", "Recht", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class RechtPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "0zzerod.recht";

	public const string PluginName = "Recht";

	public const string PluginVersion = "1.0.1";

	private const string ItemPrefabName = "THSwordRecht";

	private const string BasePrefabName = "THSwordKrom";

	private const float RefMinY = -0.3335f;

	private const float RefMaxY = 1.0525f;

	private const float RefGripCenter = -0.13525f;

	private const float ModelGripCenter = -0.142825f;

	private const float DefaultRangeMultiplier = 1.12f;

	private ConfigEntry<string> cfgRecipe;

	private ConfigEntry<string> cfgStation;

	private ConfigEntry<int> cfgStationLevel;

	private ConfigEntry<float> cfgScale;

	private ConfigEntry<Vector3> cfgOffset;

	private ConfigEntry<Vector3> cfgRotation;

	private ConfigEntry<bool> cfgClearOtherTextures;

	private ConfigEntry<bool> cfgDebug;

	private ConfigEntry<string> cfgStatsFrom;

	private ConfigEntry<float> cfgParry;

	private ConfigEntry<float> cfgRange;

	private ConfigEntry<int> cfgMaxQuality;

	private static readonly string[] OldRecipeDefaults = new string[2] { "Iron:30:15,Bronze:20:10,ScaleHide:5:5", "Iron:30:15,Bronze:10:5,FlametalNew:10:5,ScaleHide:5:5" };

	private const string RecipeDefault = "FlametalNew:20:10,Iron:20:10,Bronze:10:5,AskHide:5:3";

	private static readonly string[] AttackFields = new string[15]
	{
		"m_attackStamina", "m_attackEitr", "m_attackHealth", "m_attackHealthPercentage", "m_attackAdrenaline", "m_damageMultiplier", "m_damageMultiplierPerMissingHP", "m_damageMultiplierByTotalHealthMissing", "m_forceMultiplier", "m_staggerMultiplier",
		"m_recoilPushback", "m_selfDamage", "m_lastChainDamageMultiplier", "m_speedFactor", "m_speedFactorRotation"
	};

	private void Awake()
	{
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Expected O, but got Unknown
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		cfgRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Requirements", "FlametalNew:20:10,Iron:20:10,Bronze:10:5,AskHide:5:3", "Comma separated Item:Amount:AmountPerUpgradeLevel (prefab names). FlametalNew = Ashlands flametal, AskHide = Asksvin hide.");
		if (Array.IndexOf(OldRecipeDefaults, cfgRecipe.Value) >= 0)
		{
			cfgRecipe.Value = "FlametalNew:20:10,Iron:20:10,Bronze:10:5,AskHide:5:3";
		}
		cfgStatsFrom = ((BaseUnityPlugin)this).Config.Bind<string>("Stats", "CopyStatsFrom", "THSwordSlayer", "Prefab whose weapon stats (damage, durability, block, weight, stamina, etc.) are copied. Empty = keep Krom's.");
		cfgParry = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "ParryBonus", 2.5f, "Parry (timed block) bonus multiplier.");
		cfgMaxQuality = ((BaseUnityPlugin)this).Config.Bind<int>("Stats", "MaxQuality", 4, new ConfigDescription("Maximum upgrade level (1 = no upgrades). Slayer's is 4.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
		cfgRange = ((BaseUnityPlugin)this).Config.Bind<float>("Stats", "AttackRangeMultiplier", 1.12f, "Multiplier on Krom's attack reach (primary and secondary). Default matches Recht's longer blade.");
		cfgStation = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "CraftingStation", CraftingStations.BlackForge, "Crafting station prefab name (forge, blackforge, piece_workbench, ...).");
		cfgStationLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "MinStationLevel", 3, "Required crafting station level (Slayer needs Black forge level 3).");
		ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "ConfigVersion", 0, "Used to migrate old defaults. Don't change this.");
		if (val.Value < 2)
		{
			if (cfgStationLevel.Value == 1)
			{
				cfgStationLevel.Value = 3;
			}
			if (cfgMaxQuality.Value == 0)
			{
				cfgMaxQuality.Value = 4;
			}
			val.Value = 2;
		}
		cfgScale = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "ScaleMultiplier", 1f, "Extra scale applied on top of the automatic fit.");
		cfgOffset = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Visual", "PositionOffset", Vector3.zero, "Extra offset in the hand attach point's local space. Z slides the sword along the blade axis (try small steps like 0.02 either way); X and Y shift it sideways.");
		cfgRotation = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Visual", "RotationOffset", Vector3.zero, "Extra rotation in degrees (x, y, z), applied after the automatic fit.");
		cfgClearOtherTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "ClearUnusedKromTextures", true, "Remove Krom's extra texture maps (they don't match this model's UV layout).");
		cfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDetails", false, "Log Krom's prefab hierarchy, shader properties and the computed fit to BepInEx/LogOutput.log.");
		AddLocalizations();
		PrefabManager.OnVanillaPrefabsAvailable += AddItem;
	}

	private void AddLocalizations()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "item_thsword_recht", "Recht" },
			{ "item_thsword_recht_desc", "A sword for those who don't bend." }
		});
		string text2 = "Dutch";
		localization.AddTranslation(ref text2, new Dictionary<string, string>
		{
			{ "item_thsword_recht", "Recht" },
			{ "item_thsword_recht_desc", "Een zwaard voor wie niet buigt." }
		});
	}

	private void AddItem()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Expected O, but got Unknown
		PrefabManager.OnVanillaPrefabsAvailable -= AddItem;
		try
		{
			ItemConfig val = new ItemConfig();
			val.Name = "$item_thsword_recht";
			val.Description = "$item_thsword_recht_desc";
			val.CraftingStation = cfgStation.Value;
			val.MinStationLevel = cfgStationLevel.Value;
			ItemConfig val2 = val;
			string[] array = cfgRecipe.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array)
			{
				string[] array2 = text.Trim().Split(':');
				if (array2.Length >= 2)
				{
					int num = int.Parse(array2[1].Trim(), CultureInfo.InvariantCulture);
					int num2 = ((array2.Length > 2) ? int.Parse(array2[2].Trim(), CultureInfo.InvariantCulture) : 0);
					val2.AddRequirement(array2[0].Trim(), num, num2);
				}
			}
			Sprite val3 = LoadSprite("recht_icon.png");
			if ((Object)(object)val3 != (Object)null)
			{
				val2.Icons = (Sprite[])(object)new Sprite[1] { val3 };
			}
			CustomItem val4 = new CustomItem("THSwordRecht", "THSwordKrom", val2);
			if ((Object)(object)val4.ItemPrefab == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("Could not clone {0}; is the game version too old/new?", "THSwordKrom"));
				return;
			}
			ReplaceVisual(val4.ItemPrefab);
			ApplyStats(val4.ItemPrefab);
			ItemManager.Instance.AddItem(val4);
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Added {0} (clone of {1}).", "THSwordRecht", "THSwordKrom"));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to add Recht: " + ex));
		}
	}

	private void ApplyStats(GameObject prefab)
	{
		//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		SharedData shared = prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
		string text = cfgStatsFrom.Value.Trim();
		if (text.Length > 0)
		{
			GameObject prefab2 = PrefabManager.Instance.GetPrefab(text);
			ItemDrop val = ((!((Object)(object)prefab2 != (Object)null)) ? null : prefab2.GetComponent<ItemDrop>());
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Stats source '{text}' not found; keeping Krom's stats.");
			}
			else
			{
				SharedData shared2 = val.m_itemData.m_shared;
				shared.m_maxQuality = shared2.m_maxQuality;
				shared.m_weight = shared2.m_weight;
				shared.m_scaleWeightByQuality = shared2.m_scaleWeightByQuality;
				shared.m_value = shared2.m_value;
				shared.m_equipDuration = shared2.m_equipDuration;
				shared.m_movementModifier = shared2.m_movementModifier;
				shared.m_eitrRegenModifier = shared2.m_eitrRegenModifier;
				shared.m_homeItemsStaminaModifier = shared2.m_homeItemsStaminaModifier;
				shared.m_heatResistanceModifier = shared2.m_heatResistanceModifier;
				shared.m_jumpStaminaModifier = shared2.m_jumpStaminaModifier;
				shared.m_attackStaminaModifier = shared2.m_attackStaminaModifier;
				shared.m_blockStaminaModifier = shared2.m_blockStaminaModifier;
				shared.m_dodgeStaminaModifier = shared2.m_dodgeStaminaModifier;
				shared.m_swimStaminaModifier = shared2.m_swimStaminaModifier;
				shared.m_sneakStaminaModifier = shared2.m_sneakStaminaModifier;
				shared.m_runStaminaModifier = shared2.m_runStaminaModifier;
				shared.m_blockPower = shared2.m_blockPower;
				shared.m_blockPowerPerLevel = shared2.m_blockPowerPerLevel;
				shared.m_deflectionForce = shared2.m_deflectionForce;
				shared.m_deflectionForcePerLevel = shared2.m_deflectionForcePerLevel;
				shared.m_perfectBlockStaminaRegen = shared2.m_perfectBlockStaminaRegen;
				shared.m_maxAdrenaline = shared2.m_maxAdrenaline;
				shared.m_blockAdrenaline = shared2.m_blockAdrenaline;
				shared.m_perfectBlockAdrenaline = shared2.m_perfectBlockAdrenaline;
				shared.m_skillType = shared2.m_skillType;
				shared.m_toolTier = shared2.m_toolTier;
				shared.m_damages = shared2.m_damages;
				shared.m_damagesPerLevel = shared2.m_damagesPerLevel;
				shared.m_attackForce = shared2.m_attackForce;
				shared.m_backstabBonus = shared2.m_backstabBonus;
				shared.m_attackStatusEffect = shared2.m_attackStatusEffect;
				shared.m_attackStatusEffectChance = shared2.m_attackStatusEffectChance;
				shared.m_useDurability = shared2.m_useDurability;
				shared.m_maxDurability = shared2.m_maxDurability;
				shared.m_durabilityPerLevel = shared2.m_durabilityPerLevel;
				shared.m_useDurabilityDrain = shared2.m_useDurabilityDrain;
				shared.m_durabilityDrain = shared2.m_durabilityDrain;
				CopyAttack(shared2.m_attack, shared.m_attack, "primary");
				CopyAttack(shared2.m_secondaryAttack, shared.m_secondaryAttack, "secondary");
			}
		}
		shared.m_timedBlockBonus = cfgParry.Value;
		if (cfgMaxQuality.Value > 0)
		{
			shared.m_maxQuality = cfgMaxQuality.Value;
		}
		ScaleRange(shared.m_attack, "primary");
		ScaleRange(shared.m_secondaryAttack, "secondary");
		DamageTypes damages = shared.m_damages;
		((BaseUnityPlugin)this).Logger.LogInfo((object)($"Recht stats: slash={damages.m_slash} pierce={damages.m_pierce} blunt={damages.m_blunt} fire={damages.m_fire} spirit={damages.m_spirit} " + $"durability={shared.m_maxDurability}(+{shared.m_durabilityPerLevel}) block={shared.m_blockPower} parry={shared.m_timedBlockBonus} " + $"weight={shared.m_weight} knockback={shared.m_attackForce} backstab={shared.m_backstabBonus} maxQuality={shared.m_maxQuality}"));
	}

	private void ScaleRange(object attack, string label)
	{
		if (attack != null && !Mathf.Approximately(cfgRange.Value, 1f))
		{
			FieldInfo field = attack.GetType().GetField("m_attackRange", BindingFlags.Instance | BindingFlags.Public);
			if (field == null || field.FieldType != typeof(float))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Attack has no m_attackRange field; reach left unchanged.");
				return;
			}
			float num = (float)field.GetValue(attack);
			field.SetValue(attack, num * cfgRange.Value);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Recht {label} attack range {num:F2} -> {num * cfgRange.Value:F2}");
		}
	}

	private void CopyAttack(object src, object dst, string label)
	{
		if (src == null || dst == null)
		{
			return;
		}
		List<string> list = new List<string>();
		string[] attackFields = AttackFields;
		foreach (string text in attackFields)
		{
			FieldInfo field = src.GetType().GetField(text, BindingFlags.Instance | BindingFlags.Public);
			if (!(field == null) && field.FieldType.IsValueType)
			{
				object value = field.GetValue(src);
				field.SetValue(dst, value);
				list.Add(text.Substring(2) + "=" + value);
			}
		}
		if (cfgDebug.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)($"Copied {label} attack values: " + string.Join(", ", list.ToArray())));
		}
	}

	private void ReplaceVisual(GameObject prefab)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Expected O, but got Unknown
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0453: Unknown result type (might be due to invalid IL or missing references)
		//IL_045b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: Unknown result type (might be due to invalid IL or missing references)
		//IL_0465: Unknown result type (might be due to invalid IL or missing references)
		//IL_0476: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0483: Unknown result type (might be due to invalid IL or missing references)
		//IL_0494: Unknown result type (might be due to invalid IL or missing references)
		//IL_049b: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Unknown result type (might be due to invalid IL or missing references)
		//IL_035e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: 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_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_0378: Unknown result type (might be due to invalid IL or missing references)
		//IL_037d: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0406: Unknown result type (might be due to invalid IL or missing references)
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		Transform val = prefab.transform.Find("attach");
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"No 'attach' child on the cloned prefab; using the root.");
			val = prefab.transform;
		}
		if (cfgDebug.Value)
		{
			StringBuilder stringBuilder = new StringBuilder("Krom prefab hierarchy:\n");
			DumpHierarchy(prefab.transform, 0, stringBuilder);
			((BaseUnityPlugin)this).Logger.LogInfo((object)stringBuilder.ToString());
		}
		Material val2 = null;
		bool flag = false;
		Bounds val3 = default(Bounds);
		List<Component> list = new List<Component>();
		Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val4 in componentsInChildren)
		{
			Mesh val5 = null;
			if (val4 is MeshRenderer)
			{
				MeshFilter component = ((Component)val4).GetComponent<MeshFilter>();
				if ((Object)(object)component != (Object)null)
				{
					val5 = component.sharedMesh;
					list.Add((Component)(object)component);
				}
			}
			else
			{
				if (!(val4 is SkinnedMeshRenderer))
				{
					continue;
				}
				val5 = ((SkinnedMeshRenderer)val4).sharedMesh;
			}
			list.Add((Component)(object)val4);
			if ((Object)(object)val2 == (Object)null && (Object)(object)val4.sharedMaterial != (Object)null)
			{
				val2 = val4.sharedMaterial;
			}
			if ((Object)(object)val5 == (Object)null)
			{
				continue;
			}
			foreach (Vector3 item2 in Corners(val5.bounds))
			{
				Vector3 val6 = val.InverseTransformPoint(((Component)val4).transform.TransformPoint(item2));
				if (!flag)
				{
					((Bounds)(ref val3))..ctor(val6, Vector3.zero);
					flag = true;
				}
				else
				{
					((Bounds)(ref val3)).Encapsulate(val6);
				}
			}
		}
		LODGroup[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<LODGroup>(true);
		foreach (LODGroup item in componentsInChildren2)
		{
			list.Add((Component)(object)item);
		}
		foreach (Component item3 in list)
		{
			if ((Object)(object)item3 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)item3, true);
			}
		}
		Mesh sharedMesh = LoadObj(ReadText("recht.obj"));
		GameObject val7 = new GameObject("recht_model");
		val7.layer = ((Component)val).gameObject.layer;
		val7.transform.SetParent(val, false);
		val7.AddComponent<MeshFilter>().sharedMesh = sharedMesh;
		MeshRenderer val8 = val7.AddComponent<MeshRenderer>();
		((Renderer)val8).sharedMaterial = BuildMaterial(val2);
		Vector3 zero = Vector3.zero;
		Quaternion val9 = Quaternion.identity;
		float num = 1f;
		if (flag)
		{
			Vector3 size = ((Bounds)(ref val3)).size;
			int num2 = MaxAxis(size);
			int num3 = SecondAxis(size, num2);
			Vector3 max = ((Bounds)(ref val3)).max;
			float num4 = ((Vector3)(ref max))[num2];
			Vector3 min = ((Bounds)(ref val3)).min;
			float num5 = ((Vector3)(ref min))[num2];
			float num6 = ((!(Mathf.Abs(num4) >= Mathf.Abs(num5))) ? (-1f) : 1f);
			float num7 = ((!(num6 > 0f)) ? num4 : num5);
			num = ((Vector3)(ref size))[num2] / 1.386f;
			Vector3 val10 = Axis(num2) * num6;
			Vector3 val11 = Axis(num3);
			Vector3 val12 = Vector3.Cross(val11, val10);
			val9 = Quaternion.LookRotation(val12, val10);
			zero = Vector3.zero;
			((Vector3)(ref zero))[num2] = num7 + 0.341075f * num * num6;
			if (cfgDebug.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Krom bounds (attach space) min={((Bounds)(ref val3)).min:F3} max={((Bounds)(ref val3)).max:F3}; long axis={num2} dir={num6} width axis={num3}; scale={num:F3} pos={zero:F3} rot={((Quaternion)(ref val9)).eulerAngles:F1}");
			}
		}
		else
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not measure Krom's model; using unscaled model at the attach point.");
		}
		num *= cfgScale.Value;
		val7.transform.localRotation = val9 * Quaternion.Euler(cfgRotation.Value);
		val7.transform.localPosition = zero + cfgOffset.Value;
		val7.transform.localScale = Vector3.one * num;
	}

	private Material BuildMaterial(Material baseMat)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Expected O, but got Unknown
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Invalid comparison between Unknown and I4
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Invalid comparison between Unknown and I4
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Invalid comparison between Unknown and I4
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Invalid comparison between Unknown and I4
		Material val;
		if ((Object)(object)baseMat != (Object)null)
		{
			val = new Material(baseMat);
		}
		else
		{
			Shader val2 = Shader.Find("Custom/Creature") ?? Shader.Find("Standard");
			val = new Material(val2);
		}
		((Object)val).name = "recht_mat";
		Texture2D t = LoadTexture("recht_albedo.png", linear: false);
		Texture2D t2 = LoadTexture("recht_normal.png", linear: true);
		Texture2D t3 = LoadTexture("recht_metallic.png", linear: true);
		Shader shader = val.shader;
		HashSet<string> hashSet = new HashSet<string>();
		StringBuilder stringBuilder = new StringBuilder($"Material shader: {((Object)shader).name}\n");
		int propertyCount = shader.GetPropertyCount();
		for (int i = 0; i < propertyCount; i++)
		{
			string propertyName = shader.GetPropertyName(i);
			ShaderPropertyType propertyType = shader.GetPropertyType(i);
			stringBuilder.Append($"  {propertyName} ({propertyType})");
			if ((int)propertyType == 4)
			{
				Texture texture = val.GetTexture(propertyName);
				stringBuilder.Append((!((Object)(object)texture != (Object)null)) ? " = <none>" : $" = {((Object)texture).name}");
			}
			else if ((int)propertyType == 2 || (int)propertyType == 3)
			{
				stringBuilder.Append($" = {val.GetFloat(propertyName)}");
			}
			else if ((int)propertyType == 0)
			{
				stringBuilder.Append($" = {val.GetColor(propertyName)}");
			}
			stringBuilder.Append('\n');
		}
		if (cfgDebug.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)stringBuilder.ToString());
		}
		SetTex(val, hashSet, "_MainTex", t);
		SetTex(val, hashSet, "_BaseMap", t);
		SetTex(val, hashSet, "_BumpMap", t2, "_NORMALMAP");
		SetTex(val, hashSet, "_MetallicGlossMap", t3, "_METALLICGLOSSMAP");
		SetTex(val, hashSet, "_MetalGlossMap", t3);
		if (val.HasProperty("_Color"))
		{
			val.SetColor("_Color", Color.white);
		}
		if (cfgClearOtherTextures.Value)
		{
			for (int j = 0; j < propertyCount; j++)
			{
				string propertyName2 = shader.GetPropertyName(j);
				if ((int)shader.GetPropertyType(j) == 4 && !hashSet.Contains(propertyName2) && (Object)(object)val.GetTexture(propertyName2) != (Object)null)
				{
					val.SetTexture(propertyName2, (Texture)null);
					if (cfgDebug.Value)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"Cleared Krom texture slot {propertyName2}");
					}
				}
			}
		}
		return val;
	}

	private static void SetTex(Material mat, HashSet<string> set, string prop, Texture2D t, string keyword = null)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (mat.HasProperty(prop))
		{
			mat.SetTexture(prop, (Texture)(object)t);
			mat.SetTextureScale(prop, Vector2.one);
			mat.SetTextureOffset(prop, Vector2.zero);
			set.Add(prop);
			if (keyword != null)
			{
				mat.EnableKeyword(keyword);
			}
		}
	}

	private static void DumpHierarchy(Transform t, int depth, StringBuilder sb)
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Expected O, but got Unknown
		sb.Append(new string(' ', depth * 2)).Append(((Object)t).name).Append("  [");
		Component[] components = ((Component)t).GetComponents<Component>();
		foreach (Component val in components)
		{
			if ((Object)(object)val != (Object)null)
			{
				sb.Append(((object)val).GetType().Name).Append(' ');
			}
		}
		StringBuilder stringBuilder = sb.Append("] pos=");
		Vector3 localPosition = t.localPosition;
		StringBuilder stringBuilder2 = stringBuilder.Append(((Vector3)(ref localPosition)).ToString("F3")).Append(" rot=");
		Vector3 localEulerAngles = t.localEulerAngles;
		StringBuilder stringBuilder3 = stringBuilder2.Append(((Vector3)(ref localEulerAngles)).ToString("F1")).Append(" scale=");
		Vector3 localScale = t.localScale;
		stringBuilder3.Append(((Vector3)(ref localScale)).ToString("F3")).Append('\n');
		foreach (Transform item in t)
		{
			Transform t2 = item;
			DumpHierarchy(t2, depth + 1, sb);
		}
	}

	private static IEnumerable<Vector3> Corners(Bounds b)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < 8; i++)
		{
			yield return new Vector3(((i & 1) != 0) ? ((Bounds)(ref b)).max.x : ((Bounds)(ref b)).min.x, ((i & 2) != 0) ? ((Bounds)(ref b)).max.y : ((Bounds)(ref b)).min.y, ((i & 4) != 0) ? ((Bounds)(ref b)).max.z : ((Bounds)(ref b)).min.z);
		}
	}

	private static int MaxAxis(Vector3 v)
	{
		return (!(v.x >= v.y) || !(v.x >= v.z)) ? ((v.y >= v.z) ? 1 : 2) : 0;
	}

	private static int SecondAxis(Vector3 v, int skip)
	{
		int num = (skip + 1) % 3;
		int num2 = (skip + 2) % 3;
		return (!(((Vector3)(ref v))[num] >= ((Vector3)(ref v))[num2])) ? num2 : num;
	}

	private static Vector3 Axis(int i)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		return (Vector3)(i switch
		{
			0 => Vector3.right, 
			1 => Vector3.up, 
			_ => Vector3.forward, 
		});
	}

	private static Stream Resource(string name)
	{
		Assembly executingAssembly = Assembly.GetExecutingAssembly();
		string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
		foreach (string text in manifestResourceNames)
		{
			if (text.EndsWith(name, StringComparison.OrdinalIgnoreCase))
			{
				return executingAssembly.GetManifestResourceStream(text);
			}
		}
		throw new FileNotFoundException("Embedded resource missing: " + name);
	}

	private static string ReadText(string name)
	{
		using StreamReader streamReader = new StreamReader(Resource(name));
		return streamReader.ReadToEnd();
	}

	private static byte[] ReadBytes(string name)
	{
		using Stream stream = Resource(name);
		using MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		return memoryStream.ToArray();
	}

	private static Texture2D LoadTexture(string name, bool linear)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear);
		ImageConversion.LoadImage(val, ReadBytes(name), false);
		((Object)val).name = Path.GetFileNameWithoutExtension(name);
		((Texture)val).wrapMode = (TextureWrapMode)1;
		((Texture)val).anisoLevel = 4;
		val.Apply(true, true);
		return val;
	}

	private Sprite LoadSprite(string name)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Expected O, but got Unknown
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, ReadBytes(name), false);
			((Object)val).name = "recht_icon";
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Icon load failed: " + ex.Message));
			return null;
		}
	}

	private static Mesh LoadObj(string text)
	{
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Expected O, but got Unknown
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		CultureInfo invariantCulture = CultureInfo.InvariantCulture;
		List<Vector3> list = new List<Vector3>();
		List<Vector2> list2 = new List<Vector2>();
		List<Vector3> list3 = new List<Vector3>();
		List<Vector3> list4 = new List<Vector3>();
		List<Vector3> list5 = new List<Vector3>();
		List<Vector2> list6 = new List<Vector2>();
		List<int> list7 = new List<int>();
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		string[] array = text.Split('\n');
		foreach (string text2 in array)
		{
			string text3 = text2.Trim();
			if (text3.Length == 0 || text3[0] == '#')
			{
				continue;
			}
			string[] array2 = text3.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			switch (array2[0])
			{
			case "v":
				list.Add(new Vector3(0f - float.Parse(array2[1], invariantCulture), float.Parse(array2[2], invariantCulture), float.Parse(array2[3], invariantCulture)));
				break;
			case "vt":
				list2.Add(new Vector2(float.Parse(array2[1], invariantCulture), float.Parse(array2[2], invariantCulture)));
				break;
			case "vn":
				list3.Add(new Vector3(0f - float.Parse(array2[1], invariantCulture), float.Parse(array2[2], invariantCulture), float.Parse(array2[3], invariantCulture)));
				break;
			case "f":
			{
				int[] array3 = new int[array2.Length - 1];
				for (int j = 1; j < array2.Length; j++)
				{
					if (!dictionary.TryGetValue(array2[j], out var value))
					{
						string[] array4 = array2[j].Split('/');
						value = list4.Count;
						list4.Add(list[int.Parse(array4[0], invariantCulture) - 1]);
						list6.Add((array4.Length <= 1 || array4[1].Length <= 0) ? Vector2.zero : list2[int.Parse(array4[1], invariantCulture) - 1]);
						list5.Add((array4.Length <= 2 || array4[2].Length <= 0) ? Vector3.up : list3[int.Parse(array4[2], invariantCulture) - 1]);
						dictionary[array2[j]] = value;
					}
					array3[j - 1] = value;
				}
				for (int k = 1; k + 1 < array3.Length; k++)
				{
					list7.Add(array3[0]);
					list7.Add(array3[k + 1]);
					list7.Add(array3[k]);
				}
				break;
			}
			}
		}
		Mesh val = new Mesh();
		((Object)val).name = "recht";
		Mesh val2 = val;
		if (list4.Count > 65000)
		{
			val2.indexFormat = (IndexFormat)1;
		}
		val2.SetVertices(list4);
		val2.SetNormals(list5);
		val2.SetUVs(0, list6);
		val2.SetTriangles(list7, 0);
		val2.RecalculateBounds();
		val2.RecalculateTangents();
		return val2;
	}
}