Decompiled source of JewelsAndEssence v1.1.2

BepInEx/plugins/UniversalWeaponInfusions/UniversalWeaponInfusions.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("UniversalWeaponInfusions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+b76119d9f8b21fc1afbaa75a5486fe137d73fb29")]
[assembly: AssemblyProduct("UniversalWeaponInfusions")]
[assembly: AssemblyTitle("UniversalWeaponInfusions")]
[assembly: AssemblyVersion("1.1.0.0")]
[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 UniversalWeaponInfusions
{
	[BepInPlugin("horizoncreativeworks.universalweaponinfusions", "Jewels&Essence", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private enum Gem
		{
			Bloodstone,
			Iolite,
			Jade
		}

		private enum Essence
		{
			Thunderblood,
			Frostfire
		}

		private sealed class EffectSpec
		{
			public string MaterialPrefab;

			public string BaseTemplate;

			public string VariantTemplate;
		}

		private sealed class Family
		{
			public string BasePrefab;

			public bool Ashlands;

			public string BloodPrefab;

			public string LightningPrefab;

			public string NaturePrefab;

			public string ThunderbloodPrefab;

			public string FrostfirePrefab;
		}

		private sealed class Combo
		{
			public Gem Gem;

			public Essence Essence;

			public string Name;
		}

		private sealed class UpgradeCost
		{
			public ItemDrop Material;

			public int StepAmount;
		}

		private sealed class RuntimeEffect
		{
			public ItemDrop Material;

			public ItemDrop BaseTemplate;

			public ItemDrop VariantTemplate;
		}

		public const string Guid = "horizoncreativeworks.universalweaponinfusions";

		public const string Name = "Jewels&Essence";

		public const string Version = "1.1.0";

		internal static ManualLogSource Log;

		private static bool generated;

		private static GameObject dualChainProcPrefab;

		private static readonly Dictionary<Gem, EffectSpec> GemEffects = new Dictionary<Gem, EffectSpec>
		{
			[Gem.Bloodstone] = new EffectSpec
			{
				MaterialPrefab = "GemstoneRed",
				BaseTemplate = "SwordNiedhogg",
				VariantTemplate = "SwordNiedhoggBlood"
			},
			[Gem.Iolite] = new EffectSpec
			{
				MaterialPrefab = "GemstoneBlue",
				BaseTemplate = "SwordNiedhogg",
				VariantTemplate = "SwordNiedhoggLightning"
			},
			[Gem.Jade] = new EffectSpec
			{
				MaterialPrefab = "GemstoneGreen",
				BaseTemplate = "SwordNiedhogg",
				VariantTemplate = "SwordNiedhoggNature"
			}
		};

		private static readonly Dictionary<Essence, EffectSpec> EssenceEffects = new Dictionary<Essence, EffectSpec>
		{
			[Essence.Thunderblood] = new EffectSpec
			{
				MaterialPrefab = "OrbThunderBlood",
				BaseTemplate = "SwordGold",
				VariantTemplate = "SwordGold_BloodLightning"
			},
			[Essence.Frostfire] = new EffectSpec
			{
				MaterialPrefab = "OrbFrostFire",
				BaseTemplate = "SwordGold",
				VariantTemplate = "SwordGold_FrostFire"
			}
		};

		private static readonly Combo[] Combos = new Combo[6]
		{
			new Combo
			{
				Gem = Gem.Iolite,
				Essence = Essence.Thunderblood,
				Name = "Thundrvarg"
			},
			new Combo
			{
				Gem = Gem.Bloodstone,
				Essence = Essence.Thunderblood,
				Name = "Bloodgale"
			},
			new Combo
			{
				Gem = Gem.Jade,
				Essence = Essence.Thunderblood,
				Name = "Stormvein"
			},
			new Combo
			{
				Gem = Gem.Iolite,
				Essence = Essence.Frostfire,
				Name = "Rimewrath"
			},
			new Combo
			{
				Gem = Gem.Bloodstone,
				Essence = Essence.Frostfire,
				Name = "Helfrost"
			},
			new Combo
			{
				Gem = Gem.Jade,
				Essence = Essence.Frostfire,
				Name = "Winterwild"
			}
		};

		private static readonly Family[] Families = new Family[19]
		{
			new Family
			{
				BasePrefab = "BowAshlands",
				Ashlands = true,
				BloodPrefab = "BowAshlandsBlood",
				LightningPrefab = "BowAshlandsStorm",
				NaturePrefab = "BowAshlandsRoot"
			},
			new Family
			{
				BasePrefab = "CrossbowRipper",
				Ashlands = true,
				BloodPrefab = "CrossbowRipperBlood",
				LightningPrefab = "CrossbowRipperLightning",
				NaturePrefab = "CrossbowRipperNature"
			},
			new Family
			{
				BasePrefab = "SpearSplitner",
				Ashlands = true,
				BloodPrefab = "SpearSplitner_Blood",
				LightningPrefab = "SpearSplitner_Lightning",
				NaturePrefab = "SpearSplitner_Nature"
			},
			new Family
			{
				BasePrefab = "AxeBerzerkr",
				Ashlands = true,
				BloodPrefab = "AxeBerzerkrBlood",
				LightningPrefab = "AxeBerzerkrLightning",
				NaturePrefab = "AxeBerzerkrNature"
			},
			new Family
			{
				BasePrefab = "MaceEldner",
				Ashlands = true,
				BloodPrefab = "MaceEldnerBlood",
				LightningPrefab = "MaceEldnerLightning",
				NaturePrefab = "MaceEldnerNature"
			},
			new Family
			{
				BasePrefab = "SwordNiedhogg",
				Ashlands = true,
				BloodPrefab = "SwordNiedhoggBlood",
				LightningPrefab = "SwordNiedhoggLightning",
				NaturePrefab = "SwordNiedhoggNature"
			},
			new Family
			{
				BasePrefab = "THSwordSlayer",
				Ashlands = true,
				BloodPrefab = "THSwordSlayerBlood",
				LightningPrefab = "THSwordSlayerLightning",
				NaturePrefab = "THSwordSlayerNature"
			},
			new Family
			{
				BasePrefab = "BowGold",
				ThunderbloodPrefab = "BowGold_BloodLightning",
				FrostfirePrefab = "BowGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "CrossbowGold",
				ThunderbloodPrefab = "CrossbowGold_BloodLightning",
				FrostfirePrefab = "CrossbowGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "SpearGold",
				ThunderbloodPrefab = "SpearGold_BloodLightning",
				FrostfirePrefab = "SpearGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "AtgeirGold",
				ThunderbloodPrefab = "AtgeirGold_BloodLightning",
				FrostfirePrefab = "AtgeirGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "AxeGold",
				ThunderbloodPrefab = "AxeGold_BloodLightning",
				FrostfirePrefab = "AxeGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "BattleaxeGold",
				ThunderbloodPrefab = "BattleaxeGold_BloodLightning",
				FrostfirePrefab = "BattleaxeGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "MaceGold",
				ThunderbloodPrefab = "MaceGold_BloodLightning",
				FrostfirePrefab = "MaceGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "SledgeGold",
				ThunderbloodPrefab = "SledgeGold_BloodLightning",
				FrostfirePrefab = "SledgeGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "SwordGold",
				ThunderbloodPrefab = "SwordGold_BloodLightning",
				FrostfirePrefab = "SwordGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "THSwordGold",
				ThunderbloodPrefab = "THSwordGold_BloodLightning",
				FrostfirePrefab = "THSwordGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "KnifeGold",
				ThunderbloodPrefab = "KnifeGold_BloodLightning",
				FrostfirePrefab = "KnifeGold_FrostFire"
			},
			new Family
			{
				BasePrefab = "FistGold",
				ThunderbloodPrefab = "FistGold_BloodLightning",
				FrostfirePrefab = "FistGold_FrostFire"
			}
		};

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			ItemManager.OnItemsRegisteredFejd += GenerateVariants;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Jewels&Essence 1.1.0 loaded. Waiting for the complete native item database.");
		}

		private static void GenerateVariants()
		{
			if (generated)
			{
				return;
			}
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Log.LogError((object)"ObjectDB unavailable; no stacked infusions were generated.");
				return;
			}
			dualChainProcPrefab = CreateDualChainProcPrefab();
			Dictionary<Gem, RuntimeEffect> dictionary = ResolveGemEffects();
			Dictionary<Essence, RuntimeEffect> dictionary2 = ResolveEssenceEffects();
			if (dictionary.Count != GemEffects.Count || dictionary2.Count != EssenceEffects.Count)
			{
				Log.LogError((object)"One or more native infusion templates were missing. Aborting generation.");
				return;
			}
			int num = 0;
			int num2 = 0;
			Family[] families = Families;
			foreach (Family family in families)
			{
				ItemDrop itemDrop = GetItemDrop(family.BasePrefab);
				if ((Object)(object)itemDrop == (Object)null)
				{
					Log.LogWarning((object)("Missing base weapon " + family.BasePrefab + "; skipping family."));
					num2 += Combos.Length;
					continue;
				}
				Combo[] combos = Combos;
				foreach (Combo combo in combos)
				{
					try
					{
						ItemDrop parent = GetParent(family, combo);
						if ((Object)(object)parent == (Object)null)
						{
							Log.LogWarning((object)("Missing native parent for " + combo.Name + " " + family.BasePrefab + "; skipping."));
							num2++;
							continue;
						}
						Recipe val = FindRecipeForItem(instance, parent);
						if ((Object)(object)val == (Object)null)
						{
							Log.LogWarning((object)("No native recipe found for parent " + ((Object)((Component)parent).gameObject).name + "; skipping."));
							num2++;
							continue;
						}
						UpgradeCost upgradeCost = FindPrimaryUpgradeCost(val, family.Ashlands ? "FlametalNew" : "Gold");
						if (upgradeCost == null)
						{
							Log.LogWarning((object)("Could not determine primary upgrade cost for " + ((Object)((Component)parent).gameObject).name + "; skipping."));
							num2++;
						}
						else if ((Object)(object)CreateStackedVariant(instance, family, combo, itemDrop, parent, val, upgradeCost, dictionary[combo.Gem], dictionary2[combo.Essence]) != (Object)null)
						{
							num++;
						}
						else
						{
							num2++;
						}
					}
					catch (Exception arg)
					{
						Log.LogWarning((object)$"Could not create {combo.Name} {family.BasePrefab}: {arg}");
						num2++;
					}
				}
			}
			generated = true;
			ItemManager.OnItemsRegisteredFejd -= GenerateVariants;
			Log.LogInfo((object)$"Generated {num} native-parent stacked weapons; skipped {num2}. Expected total: 114.");
		}

		private static Dictionary<Gem, RuntimeEffect> ResolveGemEffects()
		{
			Dictionary<Gem, RuntimeEffect> dictionary = new Dictionary<Gem, RuntimeEffect>();
			foreach (KeyValuePair<Gem, EffectSpec> gemEffect in GemEffects)
			{
				RuntimeEffect runtimeEffect = ResolveEffect(gemEffect.Value);
				if (runtimeEffect != null)
				{
					dictionary[gemEffect.Key] = runtimeEffect;
				}
			}
			return dictionary;
		}

		private static Dictionary<Essence, RuntimeEffect> ResolveEssenceEffects()
		{
			Dictionary<Essence, RuntimeEffect> dictionary = new Dictionary<Essence, RuntimeEffect>();
			foreach (KeyValuePair<Essence, EffectSpec> essenceEffect in EssenceEffects)
			{
				RuntimeEffect runtimeEffect = ResolveEffect(essenceEffect.Value);
				if (runtimeEffect != null)
				{
					dictionary[essenceEffect.Key] = runtimeEffect;
				}
			}
			return dictionary;
		}

		private static RuntimeEffect ResolveEffect(EffectSpec spec)
		{
			ItemDrop itemDrop = GetItemDrop(spec.MaterialPrefab);
			ItemDrop itemDrop2 = GetItemDrop(spec.BaseTemplate);
			ItemDrop itemDrop3 = GetItemDrop(spec.VariantTemplate);
			if ((Object)(object)itemDrop == (Object)null || (Object)(object)itemDrop2 == (Object)null || (Object)(object)itemDrop3 == (Object)null)
			{
				Log.LogError((object)("Missing native effect template: material=" + spec.MaterialPrefab + ", base=" + spec.BaseTemplate + ", variant=" + spec.VariantTemplate));
				return null;
			}
			return new RuntimeEffect
			{
				Material = itemDrop,
				BaseTemplate = itemDrop2,
				VariantTemplate = itemDrop3
			};
		}

		private static ItemDrop GetParent(Family family, Combo combo)
		{
			string prefabName = ((!family.Ashlands) ? ((combo.Essence == Essence.Thunderblood) ? family.ThunderbloodPrefab : family.FrostfirePrefab) : (combo.Gem switch
			{
				Gem.Bloodstone => family.BloodPrefab, 
				Gem.Iolite => family.LightningPrefab, 
				_ => family.NaturePrefab, 
			}));
			return GetItemDrop(prefabName);
		}

		private static ItemDrop CreateStackedVariant(ObjectDB db, Family family, Combo combo, ItemDrop baseItem, ItemDrop parent, Recipe parentRecipe, UpgradeCost upgrade, RuntimeEffect gemEffect, RuntimeEffect essenceEffect)
		{
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Expected O, but got Unknown
			//IL_01da: Expected O, but got Unknown
			string text = "UWI_STACK_" + family.BasePrefab + "_" + combo.Name;
			if ((Object)(object)PrefabManager.Instance.GetPrefab(text) != (Object)null)
			{
				return null;
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(text, ((Component)parent).gameObject);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			component.m_itemData.m_dropPrefab = val;
			SharedData shared = component.m_itemData.m_shared;
			shared.m_name = combo.Name + " " + LocalizedName(baseItem.m_itemData.m_shared.m_name);
			shared.m_description = baseItem.m_itemData.m_shared.m_description + "\n\n" + combo.Name + ": " + GemLabel(combo.Gem) + " + " + EssenceLabel(combo.Essence) + ".";
			if (family.Ashlands)
			{
				ApplyNativeEffect(shared, essenceEffect.BaseTemplate.m_itemData.m_shared, essenceEffect.VariantTemplate.m_itemData.m_shared);
			}
			else
			{
				ApplyNativeEffect(shared, gemEffect.BaseTemplate.m_itemData.m_shared, gemEffect.VariantTemplate.m_itemData.m_shared);
			}
			if (combo.Gem == Gem.Iolite && combo.Essence == Essence.Thunderblood && (Object)(object)dualChainProcPrefab != (Object)null)
			{
				ApplyDualChainProc(shared.m_attack);
				ApplyDualChainProc(shared.m_secondaryAttack);
			}
			Recipe val2 = MakeStackedRecipe("Recipe_" + text, component, parentRecipe, parent, upgrade, gemEffect.Material, essenceEffect.Material);
			CustomItem val3 = new CustomItem(val, false)
			{
				Recipe = new CustomRecipe(val2, false, false)
			};
			if (!ItemManager.Instance.AddItem(val3))
			{
				return null;
			}
			if (!db.m_recipes.Contains(val2))
			{
				db.m_recipes.Add(val2);
			}
			return component;
		}

		private static Recipe MakeStackedRecipe(string recipeName, ItemDrop output, Recipe parentRecipe, ItemDrop parent, UpgradeCost upgrade, ItemDrop gemMaterial, ItemDrop essenceMaterial)
		{
			Recipe val = ScriptableObject.CreateInstance<Recipe>();
			((Object)val).name = recipeName;
			val.m_enabled = true;
			val.m_item = output;
			val.m_amount = 1;
			val.m_craftingStation = parentRecipe.m_craftingStation;
			val.m_repairStation = parentRecipe.m_repairStation;
			val.m_minStationLevel = parentRecipe.m_minStationLevel;
			val.m_resources = (Requirement[])(object)new Requirement[4]
			{
				Requirement(parent, 1, 0),
				Requirement(upgrade.Material, upgrade.StepAmount, upgrade.StepAmount),
				Requirement(gemMaterial, 1, 1),
				Requirement(essenceMaterial, 1, 1)
			};
			return val;
		}

		private static Requirement Requirement(ItemDrop item, int amount, int amountPerLevel)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = item,
				m_amount = amount,
				m_amountPerLevel = amountPerLevel,
				m_recover = false
			};
		}

		private static Recipe FindRecipeForItem(ObjectDB db, ItemDrop item)
		{
			if (db?.m_recipes == null || (Object)(object)((item != null) ? ((Component)item).gameObject : null) == (Object)null)
			{
				return null;
			}
			string prefabName = ((Object)((Component)item).gameObject).name;
			return ((IEnumerable<Recipe>)db.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => (Object)(object)r != (Object)null && r.m_enabled && (Object)(object)r.m_item != (Object)null && (Object)(object)((Component)r.m_item).gameObject != (Object)null && ((Object)((Component)r.m_item).gameObject).name == prefabName));
		}

		private static UpgradeCost FindPrimaryUpgradeCost(Recipe parentRecipe, string preferredPrefab)
		{
			if (parentRecipe?.m_resources == null)
			{
				return null;
			}
			Requirement val = ((IEnumerable<Requirement>)parentRecipe.m_resources).FirstOrDefault((Func<Requirement, bool>)delegate(Requirement r)
			{
				object obj;
				if (r == null)
				{
					obj = null;
				}
				else
				{
					ItemDrop resItem = r.m_resItem;
					obj = ((resItem != null) ? ((Component)resItem).gameObject : null);
				}
				return (Object)obj != (Object)null && ((Object)((Component)r.m_resItem).gameObject).name == preferredPrefab;
			});
			if (val == null)
			{
				return null;
			}
			int num = val.GetAmount(2);
			if (num <= 0)
			{
				num = ((val.m_amountPerLevel > 0) ? val.m_amountPerLevel : val.m_amount);
			}
			if (num <= 0)
			{
				return null;
			}
			return new UpgradeCost
			{
				Material = val.m_resItem,
				StepAmount = num
			};
		}

		private static void ApplyNativeEffect(SharedData target, SharedData templateBase, SharedData templateVariant)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			AddDamageDelta(ref target.m_damages, templateBase.m_damages, templateVariant.m_damages);
			AddDamageDelta(ref target.m_damagesPerLevel, templateBase.m_damagesPerLevel, templateVariant.m_damagesPerLevel);
			if ((Object)(object)templateVariant.m_attackStatusEffect != (Object)(object)templateBase.m_attackStatusEffect)
			{
				target.m_attackStatusEffect = templateVariant.m_attackStatusEffect;
				target.m_attackStatusEffectChance = templateVariant.m_attackStatusEffectChance;
			}
			OverlayAttackEffect(target.m_attack, templateBase.m_attack, templateVariant.m_attack);
			OverlayAttackEffect(target.m_secondaryAttack, templateBase.m_secondaryAttack, templateVariant.m_secondaryAttack);
		}

		private static void OverlayAttackEffect(Attack target, Attack templateBase, Attack templateVariant)
		{
			if (target != null && templateBase != null && templateVariant != null)
			{
				float num = templateVariant.m_damageMultiplierPerMissingHP - templateBase.m_damageMultiplierPerMissingHP;
				float num2 = templateVariant.m_damageMultiplierByTotalHealthMissing - templateBase.m_damageMultiplierByTotalHealthMissing;
				if (Math.Abs(num) > 1E-06f)
				{
					target.m_damageMultiplierPerMissingHP += num;
				}
				if (Math.Abs(num2) > 1E-06f)
				{
					target.m_damageMultiplierByTotalHealthMissing += num2;
				}
				if ((Object)(object)templateVariant.m_spawnOnHit != (Object)(object)templateBase.m_spawnOnHit)
				{
					target.m_spawnOnHit = templateVariant.m_spawnOnHit;
					target.m_spawnOnHitChance = templateVariant.m_spawnOnHitChance;
				}
			}
		}

		private static void AddDamageDelta(ref DamageTypes target, DamageTypes templateBase, DamageTypes templateVariant)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_003c: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00c6: 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)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			target.m_blunt += templateVariant.m_blunt - templateBase.m_blunt;
			target.m_slash += templateVariant.m_slash - templateBase.m_slash;
			target.m_pierce += templateVariant.m_pierce - templateBase.m_pierce;
			target.m_chop += templateVariant.m_chop - templateBase.m_chop;
			target.m_pickaxe += templateVariant.m_pickaxe - templateBase.m_pickaxe;
			target.m_fire += templateVariant.m_fire - templateBase.m_fire;
			target.m_frost += templateVariant.m_frost - templateBase.m_frost;
			target.m_lightning += templateVariant.m_lightning - templateBase.m_lightning;
			target.m_poison += templateVariant.m_poison - templateBase.m_poison;
			target.m_spirit += templateVariant.m_spirit - templateBase.m_spirit;
		}

		private static string GemLabel(Gem gem)
		{
			return gem switch
			{
				Gem.Bloodstone => "Bleeding", 
				Gem.Iolite => "Thundering", 
				_ => "Primal", 
			};
		}

		private static string EssenceLabel(Essence essence)
		{
			if (essence != Essence.Thunderblood)
			{
				return "Frostfire";
			}
			return "Thunderblood";
		}

		private static string LocalizedName(string token)
		{
			if (string.IsNullOrEmpty(token))
			{
				return "Weapon";
			}
			if (Localization.instance == null)
			{
				return token.TrimStart(new char[1] { '$' });
			}
			return Localization.instance.Localize(token);
		}

		private static ItemDrop GetItemDrop(string prefabName)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName);
			if (!((Object)(object)prefab != (Object)null))
			{
				return null;
			}
			return prefab.GetComponent<ItemDrop>();
		}

		private static void ApplyDualChainProc(Attack attack)
		{
			if (attack != null)
			{
				attack.m_spawnOnHit = dualChainProcPrefab;
				attack.m_spawnOnHitChance = 1f;
			}
		}

		private static GameObject CreateDualChainProcPrefab()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("ChainLightning");
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("ChainLightningRed");
			if ((Object)(object)prefab == (Object)null || (Object)(object)prefab2 == (Object)null)
			{
				Log.LogWarning((object)"Could not find one or both native chain-lightning prefabs; Thundrvarg will fall back to its cloned parent proc.");
				return null;
			}
			GameObject prefab3 = PrefabManager.Instance.GetPrefab("UWI_DualChainProc");
			if ((Object)(object)prefab3 != (Object)null)
			{
				DualChainProc.BlueChain = prefab;
				DualChainProc.RedChain = prefab2;
				return prefab3;
			}
			GameObject val = PrefabManager.Instance.CreateEmptyPrefab("UWI_DualChainProc", false);
			val.AddComponent<DualChainProc>();
			DualChainProc.BlueChain = prefab;
			DualChainProc.RedChain = prefab2;
			PrefabManager.Instance.AddPrefab(val);
			return val;
		}
	}
	public sealed class DualChainProc : MonoBehaviour, IProjectile
	{
		internal static GameObject BlueChain;

		internal static GameObject RedChain;

		public void Setup(Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemData item, ItemData ammo)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			TrySpawn(BlueChain, 0.25f, owner, velocity, hitNoise, hitData, item, ammo);
			TrySpawn(RedChain, 0.25f, owner, velocity, hitNoise, hitData, item, ammo);
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		public string GetTooltipString(int itemQuality)
		{
			return string.Empty;
		}

		private void TrySpawn(GameObject prefab, float chance, Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemData item, ItemData ammo)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)prefab == (Object)null) && !(Random.value > chance))
			{
				IProjectile componentInChildren = Object.Instantiate<GameObject>(prefab, ((Component)this).transform.position, ((Component)this).transform.rotation).GetComponentInChildren<IProjectile>();
				if (componentInChildren != null)
				{
					componentInChildren.Setup(owner, velocity, hitNoise, hitData, item, ammo);
				}
			}
		}
	}
}