Decompiled source of ArtificerRework v1.1.3

ArtificerRework.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using ArtificerRework.Skills.ChainBolt;
using ArtificerRework.Skills.Fireball;
using ArtificerRework.Skills.Flamethrower;
using ArtificerRework.Skills.FrostPillar;
using ArtificerRework.Skills.IonGlide;
using ArtificerRework.Skills.Tectonic;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Mage;
using EntityStates.Mage.Weapon;
using HG;
using HG.GeneralSerializer;
using KinematicCharacterController;
using Microsoft.CodeAnalysis;
using R2API;
using RoR2;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.ResourceLocations;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ArtificerRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.3.0")]
[assembly: AssemblyInformationalVersion("1.1.3")]
[assembly: AssemblyProduct("ArtificerRework")]
[assembly: AssemblyTitle("ArtificerRework")]
[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 ArtificerRework
{
	public abstract class AreaZone : MonoBehaviour
	{
		public float radius = 8f;

		public float lifetime = 6f;

		public float tickInterval = 0.5f;

		protected ProjectileController controller;

		protected ProjectileDamage projectileDamage;

		protected TeamIndex team = (TeamIndex)(-1);

		protected GameObject owner;

		protected CharacterBody ownerBody;

		private float age;

		private float tickTimer;

		private readonly Dictionary<HealthComponent, float> timeInside = new Dictionary<HealthComponent, float>();

		private readonly List<HealthComponent> insideNow = new List<HealthComponent>();

		private readonly List<HealthComponent> toRemove = new List<HealthComponent>();

		protected float BaseTickDamage
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)projectileDamage))
				{
					return 0f;
				}
				return projectileDamage.damage;
			}
		}

		protected bool IsCrit
		{
			get
			{
				if (Object.op_Implicit((Object)(object)projectileDamage))
				{
					return projectileDamage.crit;
				}
				return false;
			}
		}

		protected virtual void Start()
		{
			//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)
			controller = ((Component)this).GetComponent<ProjectileController>();
			projectileDamage = ((Component)this).GetComponent<ProjectileDamage>();
			TeamFilter component = ((Component)this).GetComponent<TeamFilter>();
			if (Object.op_Implicit((Object)(object)component))
			{
				team = component.teamIndex;
			}
			owner = (Object.op_Implicit((Object)(object)controller) ? controller.owner : null);
			ownerBody = (Object.op_Implicit((Object)(object)owner) ? owner.GetComponent<CharacterBody>() : null);
			OnZoneStart();
		}

		protected virtual void OnZoneStart()
		{
		}

		private void FixedUpdate()
		{
			if (NetworkServer.active)
			{
				float fixedDeltaTime = Time.fixedDeltaTime;
				age += fixedDeltaTime;
				tickTimer += fixedDeltaTime;
				if (tickTimer >= tickInterval)
				{
					tickTimer -= tickInterval;
					Tick();
				}
				if (age >= lifetime)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
			}
		}

		private void Tick()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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)
			insideNow.Clear();
			Vector3 position = ((Component)this).transform.position;
			ReadOnlyCollection<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CharacterBody val = readOnlyInstancesList[i];
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.healthComponent) && val.healthComponent.alive && (!Object.op_Implicit((Object)(object)val.teamComponent) || val.teamComponent.teamIndex != team) && FriendlyFireManager.ShouldDirectHitProceed(val.healthComponent, team))
				{
					float num = radius + val.radius;
					Vector3 val2 = val.corePosition - position;
					if (!(((Vector3)(ref val2)).sqrMagnitude > num * num))
					{
						insideNow.Add(val.healthComponent);
					}
				}
			}
			for (int j = 0; j < insideNow.Count; j++)
			{
				HealthComponent val3 = insideNow[j];
				timeInside.TryGetValue(val3, out var value);
				value += tickInterval;
				timeInside[val3] = value;
				if (Object.op_Implicit((Object)(object)val3.body))
				{
					OnTick(val3.body, value);
				}
			}
			toRemove.Clear();
			foreach (KeyValuePair<HealthComponent, float> item in timeInside)
			{
				if (!Object.op_Implicit((Object)(object)item.Key) || !insideNow.Contains(item.Key))
				{
					toRemove.Add(item.Key);
				}
			}
			for (int k = 0; k < toRemove.Count; k++)
			{
				timeInside.Remove(toRemove[k]);
			}
		}

		protected abstract void OnTick(CharacterBody victim, float secondsInside);
	}
	internal static class Assets
	{
		public static GameObject MageBody;

		public static SkillFamily PrimaryFamily;

		public static SkillFamily SecondaryFamily;

		public static SkillFamily UtilityFamily;

		public static SkillFamily SpecialFamily;

		public static SkillDef SdFireBolt;

		public static SkillDef SdPlasmaBolt;

		public static SkillDef SdNanoBomb;

		public static SkillDef SdNanoSpear;

		public static SkillDef SdSnapfreeze;

		public static SkillDef SdFlamethrower;

		public static SkillDef SdIonSurge;

		public static GameObject PlasmaBoltProjectile;

		public static GameObject FireBoltProjectile;

		public static GameObject NanoBombProjectile;

		public static GameObject IceWallPillarProjectile;

		public static GameObject MuzzleLightning;

		public static GameObject MuzzleLightningLarge;

		public static GameObject MuzzleFire;

		public static GameObject MuzzleFireLarge;

		public static GameObject MuzzleIce;

		public static GameObject MuzzleIceLarge;

		public static GameObject FxLightningExplosion;

		public static GameObject FxFireExplosion;

		public static GameObject FxIceExplosion;

		public static GameObject FxGasolineExplosion;

		public static GameObject FxIceRing;

		public static GameObject NovaChargeVfx;

		public static Sprite OnFireIcon;

		public static void Init()
		{
			MageBody = Assets.Load<GameObject>("RoR2/Base/Mage/MageBody.prefab");
			PrimaryFamily = Assets.Load<SkillFamily>("RoR2/Base/Mage/MageBodyPrimaryFamily.asset");
			SecondaryFamily = Assets.Load<SkillFamily>("RoR2/Base/Mage/MageBodySecondaryFamily.asset");
			UtilityFamily = Assets.Load<SkillFamily>("RoR2/Base/Mage/MageBodyUtilityFamily.asset");
			SpecialFamily = Assets.Load<SkillFamily>("RoR2/Base/Mage/MageBodySpecialFamily.asset");
			SdFireBolt = Assets.Load<SkillDef>("RoR2/Base/Mage/MageBodyFireFirebolt.asset");
			SdPlasmaBolt = Assets.Load<SkillDef>("RoR2/Base/Mage/MageBodyFireLightningBolt.asset");
			SdNanoBomb = Assets.Load<SkillDef>("RoR2/Base/Mage/MageBodyNovaBomb.asset");
			SdNanoSpear = Assets.Load<SkillDef>("RoR2/Base/Mage/MageBodyIceBomb.asset");
			SdSnapfreeze = Assets.Load<SkillDef>("RoR2/Base/Mage/MageBodyWall.asset");
			SdFlamethrower = Assets.Load<SkillDef>("RoR2/Base/Mage/MageBodyFlamethrower.asset");
			SdIonSurge = Assets.Load<SkillDef>("RoR2/Base/Mage/MageBodyFlyUp.asset");
			PlasmaBoltProjectile = Assets.LoadFirst<GameObject>(new string[2] { "RoR2/Base/Mage/MageLightningboltBasic.prefab", "RoR2/Base/Mage/MageLightningBoltBasic.prefab" });
			if (!Object.op_Implicit((Object)(object)PlasmaBoltProjectile))
			{
				PlasmaBoltProjectile = Assets.EscObject<GameObject>("RoR2/Base/Mage/EntityStates.Mage.Weapon.FireLightningBolt.asset", "projectilePrefab");
			}
			FireBoltProjectile = Assets.LoadFirst<GameObject>(new string[2] { "RoR2/Base/Mage/MageFireboltBasic.prefab", "RoR2/Base/Mage/MageFirebolt.prefab" });
			if (!Object.op_Implicit((Object)(object)FireBoltProjectile))
			{
				FireBoltProjectile = Assets.EscObject<GameObject>("RoR2/Base/Mage/EntityStates.Mage.Weapon.FireFireBolt.asset", "projectilePrefab");
			}
			NanoBombProjectile = Assets.Load<GameObject>("RoR2/Base/Mage/MageLightningBombProjectile.prefab");
			IceWallPillarProjectile = Assets.Load<GameObject>("RoR2/Base/Mage/MageIcewallPillarProjectile.prefab");
			Log.Info("Proyectiles: plasma=" + (Object.op_Implicit((Object)(object)PlasmaBoltProjectile) ? ((Object)PlasmaBoltProjectile).name : "NO") + ", fire=" + (Object.op_Implicit((Object)(object)FireBoltProjectile) ? ((Object)FireBoltProjectile).name : "NO") + ", nanobomb=" + (Object.op_Implicit((Object)(object)NanoBombProjectile) ? ((Object)NanoBombProjectile).name : "NO") + ", pilar=" + (Object.op_Implicit((Object)(object)IceWallPillarProjectile) ? ((Object)IceWallPillarProjectile).name : "NO"));
			MuzzleLightning = Assets.Load<GameObject>("RoR2/Base/Mage/MuzzleflashMageLightning.prefab");
			MuzzleLightningLarge = Assets.LoadFirst<GameObject>(new string[2] { "RoR2/Base/Mage/MuzzleflashMageLightningLarge.prefab", "RoR2/Base/Mage/MuzzleflashMageLightning.prefab" });
			MuzzleFire = Assets.Load<GameObject>("RoR2/Base/Mage/MuzzleflashMageFire.prefab");
			MuzzleFireLarge = Assets.LoadFirst<GameObject>(new string[2] { "RoR2/Base/Mage/MuzzleflashMageFireLarge.prefab", "RoR2/Base/Mage/MuzzleflashMageFire.prefab" });
			MuzzleIceLarge = Assets.LoadFirst<GameObject>(new string[2] { "RoR2/Base/Mage/MuzzleflashMageIceLarge.prefab", "RoR2/Base/Mage/MuzzleflashMageIce.prefab" });
			MuzzleIce = Assets.LoadFirst<GameObject>(new string[2] { "RoR2/Base/Mage/MuzzleflashMageIce.prefab", "RoR2/Base/Mage/MuzzleflashMageIceLarge.prefab" });
			FxGasolineExplosion = Assets.Load<GameObject>("RoR2/Base/IgniteOnKill/IgniteExplosionVFX.prefab");
			FxIceRing = Assets.Load<GameObject>("RoR2/Base/ElementalRings/IceRingExplosion.prefab");
			FxLightningExplosion = ImpactEffectOf(NanoBombProjectile) ?? ImpactEffectOf(PlasmaBoltProjectile);
			FxFireExplosion = ImpactEffectOf(FireBoltProjectile);
			FxIceExplosion = ImpactEffectOf(IceWallPillarProjectile);
			NovaChargeVfx = Assets.EscObject<GameObject>("RoR2/Base/Mage/EntityStates.Mage.Weapon.ChargeNovabomb.asset", "chargeEffectPrefab");
			OnFireIcon = Assets.Load<Sprite>("RoR2/Base/Common/texBuffOnFireIcon.tif");
			Log.Info("Assets cargados. Faltantes (si hay) aparecen arriba como warnings.");
		}

		public static bool Exists(string key, Type type = null)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				IList<IResourceLocation> list = Addressables.LoadResourceLocationsAsync((object)key, type).WaitForCompletion();
				return list != null && list.Count > 0;
			}
			catch
			{
				return false;
			}
		}

		public static List<string> FindKeys(string contains, string endsWith = null)
		{
			List<string> list = new List<string>();
			try
			{
				foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
				{
					if (((resourceLocator != null) ? resourceLocator.Keys : null) == null)
					{
						continue;
					}
					foreach (object key in resourceLocator.Keys)
					{
						if (key is string text && text.IndexOf(contains, StringComparison.Ordinal) >= 0 && (endsWith == null || text.EndsWith(endsWith, StringComparison.Ordinal)) && !list.Contains(text))
						{
							list.Add(text);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.Warn("FindKeys falló: " + ex.Message);
			}
			return list;
		}

		public static T Load<T>(string key) where T : Object
		{
			//IL_0026: 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)
			try
			{
				if (!Exists(key))
				{
					Log.Warn("Addressable no encontrado: " + key);
					return default(T);
				}
				T val = Addressables.LoadAssetAsync<T>((object)key).WaitForCompletion();
				if (!Object.op_Implicit((Object)(object)val))
				{
					Log.Warn("Addressable vacío: " + key);
				}
				return val;
			}
			catch (Exception ex)
			{
				Log.Warn("Addressable falló: " + key + " -> " + ex.GetType().Name + ": " + ex.Message);
				return default(T);
			}
		}

		public static T LoadFirst<T>(params string[] keys) where T : Object
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < keys.Length; i++)
			{
				if (!Exists(keys[i]))
				{
					continue;
				}
				try
				{
					T val = Addressables.LoadAssetAsync<T>((object)keys[i]).WaitForCompletion();
					if (Object.op_Implicit((Object)(object)val))
					{
						return val;
					}
				}
				catch (Exception ex)
				{
					Log.Warn("Addressable falló: " + keys[i] + " -> " + ex.Message);
				}
			}
			Log.Warn("Ninguna de estas llaves existe: " + string.Join(" | ", keys));
			return default(T);
		}

		private static GameObject ImpactEffectOf(GameObject projectile)
		{
			if (!Object.op_Implicit((Object)(object)projectile))
			{
				return null;
			}
			ProjectileImpactExplosion component = projectile.GetComponent<ProjectileImpactExplosion>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			return component.impactEffect;
		}

		public static T EscObject<T>(string escKey, string fieldName) where T : Object
		{
			try
			{
				EntityStateConfiguration val = Assets.Load<EntityStateConfiguration>(escKey);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return default(T);
				}
				SerializedField[] serializedFields = val.serializedFieldsCollection.serializedFields;
				if (serializedFields == null)
				{
					return default(T);
				}
				for (int i = 0; i < serializedFields.Length; i++)
				{
					if (serializedFields[i].fieldName == fieldName)
					{
						Object objectValue = serializedFields[i].fieldValue.objectValue;
						return (T)(object)((objectValue is T) ? objectValue : null);
					}
				}
				Log.Warn("ESC " + escKey + ": no tiene campo '" + fieldName + "'.");
			}
			catch (Exception ex)
			{
				Log.Warn("ESC " + escKey + "." + fieldName + " falló: " + ex.Message);
			}
			return default(T);
		}

		public static string EscString(string escKey, string fieldName)
		{
			try
			{
				EntityStateConfiguration val = Assets.Load<EntityStateConfiguration>(escKey);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return null;
				}
				SerializedField[] serializedFields = val.serializedFieldsCollection.serializedFields;
				if (serializedFields == null)
				{
					return null;
				}
				for (int i = 0; i < serializedFields.Length; i++)
				{
					if (serializedFields[i].fieldName == fieldName)
					{
						return serializedFields[i].fieldValue.stringValue;
					}
				}
			}
			catch (Exception ex)
			{
				Log.Warn("ESC " + escKey + "." + fieldName + " falló: " + ex.Message);
			}
			return null;
		}
	}
	public enum ReworkMode
	{
		Replace,
		AddVariant
	}
	internal static class Cfg
	{
		public static ConfigEntry<ReworkMode> Mode;

		public static ConfigEntry<bool> UseVanillaStates;

		public static ConfigEntry<float> FadeOutTime;

		public static ConfigEntry<bool> ChainEnabled;

		public static ConfigEntry<float> ChainDamage;

		public static ConfigEntry<float> ChainRange;

		public static ConfigEntry<float> ChainRangePerLevels;

		public static ConfigEntry<int> ChainArcs;

		public static ConfigEntry<int> ChainLevelsPerBounce;

		public static ConfigEntry<int> ChainMaxBounces;

		public static ConfigEntry<float> ChainArcDamageMult;

		public static ConfigEntry<float> ChainBounceDamageMult;

		public static ConfigEntry<bool> ChainOnWorldHit;

		public static ConfigEntry<float> ChainSplashRadius;

		public static ConfigEntry<float> ChainCastDuration;

		public static ConfigEntry<bool> FireballEnabled;

		public static ConfigEntry<float> FireballCooldown;

		public static ConfigEntry<float> FireballChargeTime;

		public static ConfigEntry<float> FireballMaxHoldTime;

		public static ConfigEntry<float> FireballMinDamage;

		public static ConfigEntry<float> FireballMaxDamage;

		public static ConfigEntry<float> FireballBlastRadius;

		public static ConfigEntry<float> FireballSpeed;

		public static ConfigEntry<float> FireballLifetime;

		public static ConfigEntry<float> FireballVisualScale;

		public static ConfigEntry<string> FireballBaseProjectile;

		public static ConfigEntry<float> FireballGravity;

		public static ConfigEntry<float> FireballMinChargeScale;

		public static ConfigEntry<float> FireballMaxChargeScale;

		public static ConfigEntry<float> FireballRecoil;

		public static ConfigEntry<bool> FireballScreenShake;

		public static ConfigEntry<float> FirePatchVisualScale;

		public static ConfigEntry<bool> FirePatchEnabled;

		public static ConfigEntry<float> FirePatchRadius;

		public static ConfigEntry<float> FirePatchDuration;

		public static ConfigEntry<float> FirePatchTickInterval;

		public static ConfigEntry<float> FirePatchTickDamage;

		public static ConfigEntry<float> FirePatchProcCoefficient;

		public static ConfigEntry<bool> TectonicEnabled;

		public static ConfigEntry<float> TectonicChargeTime;

		public static ConfigEntry<bool> TectonicAutoFire;

		public static ConfigEntry<int> TectonicShardCount;

		public static ConfigEntry<float> TectonicShardDamage;

		public static ConfigEntry<float> TectonicSpreadAngle;

		public static ConfigEntry<float> TectonicVerticalSpread;

		public static ConfigEntry<bool> TectonicUseVanillaShard;

		public static ConfigEntry<float> TectonicShardSpeed;

		public static ConfigEntry<float> TectonicBaseRange;

		public static ConfigEntry<float> TectonicMaxRangeMult;

		public static ConfigEntry<float> TectonicShardBlastRadius;

		public static ConfigEntry<float> TectonicShardForce;

		public static ConfigEntry<float> TectonicBaseSelfForce;

		public static ConfigEntry<float> TectonicChargedSelfForce;

		public static ConfigEntry<float> TectonicGroundedMinUpward;

		public static ConfigEntry<float> OilDuration;

		public static ConfigEntry<string> OilBuffName;

		public static ConfigEntry<float> TectonicFallbackCooldown;

		public static ConfigEntry<bool> PillarEnabled;

		public static ConfigEntry<float> PillarRange;

		public static ConfigEntry<float> PillarCastDelay;

		public static ConfigEntry<float> PillarCastDuration;

		public static ConfigEntry<float> PillarChargeTime;

		public static ConfigEntry<float> PillarMaxHoldTime;

		public static ConfigEntry<float> PillarScaleMin;

		public static ConfigEntry<float> PillarScaleMax;

		public static ConfigEntry<float> PillarDuration;

		public static ConfigEntry<float> PillarBurstDamage;

		public static ConfigEntry<float> PillarBurstDamageMax;

		public static ConfigEntry<float> PillarBurstRadius;

		public static ConfigEntry<float> PillarBurstEffectScale;

		public static ConfigEntry<int> SnowRingPillars;

		public static ConfigEntry<float> SnowRingPillarScale;

		public static ConfigEntry<float> SnowVisualScale;

		public static ConfigEntry<bool> PillarEffectZUp;

		public static ConfigEntry<float> SnowRadius;

		public static ConfigEntry<float> SnowRadiusMax;

		public static ConfigEntry<float> SnowDuration;

		public static ConfigEntry<float> SnowTickInterval;

		public static ConfigEntry<float> SnowTickDamage;

		public static ConfigEntry<float> SnowSlowAfter;

		public static ConfigEntry<float> SnowFreezeAfter;

		public static ConfigEntry<float> SnowFreezeDuration;

		public static ConfigEntry<float> SnowRefreezeCooldown;

		public static ConfigEntry<bool> FlameEnabled;

		public static ConfigEntry<float> FlameRange;

		public static ConfigEntry<float> FlameTotalDamage;

		public static ConfigEntry<float> FlameRadius;

		public static ConfigEntry<bool> FlameAgile;

		public static ConfigEntry<float> FlameAirThrust;

		public static ConfigEntry<float> FlameMaxThrustSpeed;

		public static ConfigEntry<float> EmberTickInterval;

		public static ConfigEntry<float> EmberTickDamage;

		public static ConfigEntry<float> EmberExplosionDamage;

		public static ConfigEntry<float> EmberExplosionRadius;

		public static ConfigEntry<float> EmberExplosionProc;

		public static ConfigEntry<bool> EmberExplosionSpreadsEmber;

		public static ConfigEntry<bool> EmberVisual;

		public static ConfigEntry<bool> IonEnabled;

		public static ConfigEntry<float> IonLaunchSpeed;

		public static ConfigEntry<float> IonMinLaunchUpward;

		public static ConfigEntry<float> IonBlastDamage;

		public static ConfigEntry<float> IonBlastRadius;

		public static ConfigEntry<bool> IonBlastStuns;

		public static ConfigEntry<float> IonGlideMaxTime;

		public static ConfigEntry<float> IonGravityScale;

		public static ConfigEntry<float> IonDrag;

		public static ConfigEntry<float> IonDiveAccel;

		public static ConfigEntry<float> IonClimbPenalty;

		public static ConfigEntry<float> IonMaxSpeed;

		public static ConfigEntry<float> IonMinSpeed;

		public static ConfigEntry<float> IonSteerRate;

		public static ConfigEntry<bool> IonJumpCancels;

		public static ConfigEntry<bool> IonSpecialCancels;

		public static ConfigEntry<bool> IonIgnoreFallDamage;

		public static ConfigEntry<float> IonTiltAngle;

		public static void Init(ConfigFile c)
		{
			Mode = c.Bind<ReworkMode>("0. General", "ReworkMode", ReworkMode.Replace, "Replace = cambia las habilidades vanilla (Plasma Bolt, Tectonic Blast, Snapfreeze, Ion Surge) en su lugar.\nAddVariant = deja las vanilla y agrega las versiones rework como variantes extra para poder compararlas.");
			UseVanillaStates = c.Bind<bool>("0. General", "UseVanillaAnimationStates", true, "true = las habilidades heredan de los estados vanilla (animaciones/sonidos/VFX exactos del juego).\nfalse = usa los estados propios del mod (respaldo por si tu versión del juego no es compatible con el truco anterior).");
			FadeOutTime = c.Bind<float>("0. General", "FadeOutSeconds", 1f, "Segundos de desvanecido antes de que desaparezcan zonas, pilares y brasas (0 = de golpe).");
			ChainEnabled = c.Bind<bool>("1. Primary - Chain Bolt", "Enabled", true, "Activa el rework de Plasma Bolt (ya no explota; el impacto hace daño y desde el enemigo golpeado saltan rayos a los de alrededor).");
			ChainDamage = c.Bind<float>("1. Primary - Chain Bolt", "Damage", 2.8f, "Daño del impacto directo (vanilla 2.8 = 280%).");
			ChainRange = c.Bind<float>("1. Primary - Chain Bolt", "ChainRange", 13f, "Rango (m) de cada salto del rayo desde el enemigo golpeado, a nivel 1.");
			ChainRangePerLevels = c.Bind<float>("1. Primary - Chain Bolt", "ChainRangePerLevelStep", 2f, "Metros extra de rango de salto por cada LevelsPerExtraBounce niveles (por defecto +2 m cada 10 niveles).");
			ChainArcs = c.Bind<int>("1. Primary - Chain Bolt", "ArcsFromImpact", 3, "Cuántos enemigos distintos reciben un rayo desde el enemigo impactado (el impactado nunca se incluye).");
			ChainLevelsPerBounce = c.Bind<int>("1. Primary - Chain Bolt", "LevelsPerExtraBounce", 10, "Cada cuántos niveles cada rayo puede seguir rebotando a 1 enemigo más (nivel 1-9: no rebotan; 10-19: 1 rebote; ...).");
			ChainMaxBounces = c.Bind<int>("1. Primary - Chain Bolt", "MaxBounces", 6, "Tope de rebotes por rayo.");
			ChainArcDamageMult = c.Bind<float>("1. Primary - Chain Bolt", "ArcDamageMultiplier", 1f, "Daño de cada rayo respecto al impacto directo (1.0 = igual).");
			ChainBounceDamageMult = c.Bind<float>("1. Primary - Chain Bolt", "BounceDamageMultiplier", 1f, "Multiplicador de daño de cada rebote respecto al rayo anterior.");
			ChainOnWorldHit = c.Bind<bool>("1. Primary - Chain Bolt", "ArcsOnWorldHit", false, "Si el proyectil pega en el piso/pared sin tocar a nadie con el splash, ¿lanza igual los rayos a los enemigos cercanos?");
			ChainSplashRadius = c.Bind<float>("1. Primary - Chain Bolt", "SplashRadius", 3f, "Radio (m) del splash pequeño del impacto (facilita acertar). Todos los alcanzados reciben el daño del impacto; los rayos salen del más cercano al punto de impacto. 0 = sin splash.");
			ChainCastDuration = c.Bind<float>("1. Primary - Chain Bolt", "CastDuration", 0.35f, "(Solo estados propios) duración de la animación de disparo.");
			FireballEnabled = c.Bind<bool>("2. Secondary - Fireball", "Enabled", true, "Agrega Fireball como nueva secundaria (no reemplaza nada).");
			FireballCooldown = c.Bind<float>("2. Secondary - Fireball", "Cooldown", 5f, "Cooldown (s). Nano-Bomb/Nano-Spear usan 5.");
			FireballChargeTime = c.Bind<float>("2. Secondary - Fireball", "ChargeTime", 2f, "Segundos para carga completa (se divide entre attack speed).");
			FireballMaxHoldTime = c.Bind<float>("2. Secondary - Fireball", "MaxHoldTime", 6f, "Si la mantienes cargada más de esto, se dispara sola.");
			FireballMinDamage = c.Bind<float>("2. Secondary - Fireball", "MinDamage", 3.5f, "Daño sin carga (3.5 = 350%).");
			FireballMaxDamage = c.Bind<float>("2. Secondary - Fireball", "MaxDamage", 16f, "Daño con carga completa (16.0 = 1600%).");
			FireballBlastRadius = c.Bind<float>("2. Secondary - Fireball", "BlastRadius", 7f, "Radio (m) de la explosión de impacto.");
			FireballSpeed = c.Bind<float>("2. Secondary - Fireball", "ProjectileSpeed", 90f, "Velocidad del proyectil (m/s). Sin gravedad.");
			FireballLifetime = c.Bind<float>("2. Secondary - Fireball", "ProjectileLifetime", 4f, "Vida máxima del proyectil (s).");
			FireballBaseProjectile = c.Bind<string>("2. Secondary - Fireball", "BaseProjectile", "ElderLemurian", "Proyectil base para el visual: ElderLemurian (bola de fuego grande), Lemurian (bola pequeña) o FlameBolt (el de Artificer).");
			FireballVisualScale = c.Bind<float>("2. Secondary - Fireball", "VisualScale", 1.4f, "Escala visual del proyectil respecto al proyectil base (con FlameBolt se multiplica x3 automáticamente).");
			FireballGravity = c.Bind<float>("2. Secondary - Fireball", "GravityScale", 0.25f, "Caída del proyectil como fracción de la gravedad normal (0 = recta; 0.25 = arco leve; 0.5 = mortero).");
			FireballMinChargeScale = c.Bind<float>("2. Secondary - Fireball", "MinChargeSizeMultiplier", 0.6f, "Tamaño de la bola sin carga (multiplica a VisualScale).");
			FireballMaxChargeScale = c.Bind<float>("2. Secondary - Fireball", "MaxChargeSizeMultiplier", 1.3f, "Tamaño de la bola con carga completa (multiplica a VisualScale).");
			FireballRecoil = c.Bind<float>("2. Secondary - Fireball", "RecoilSpeed", 9f, "Velocidad (m/s) con la que te empuja hacia atrás al lanzar con carga completa (escala con la carga).");
			FireballScreenShake = c.Bind<bool>("2. Secondary - Fireball", "ScreenShake", true, "Temblor de pantalla al lanzar y al impactar.");
			FirePatchVisualScale = c.Bind<float>("2. Secondary - Fireball", "FirePatchVisualScale", 1f, "Multiplicador del tamaño del visual del charco de fuego.");
			FirePatchEnabled = c.Bind<bool>("2. Secondary - Fireball", "FirePatchEnabled", true, "Deja una zona ardiendo donde impacta.");
			FirePatchRadius = c.Bind<float>("2. Secondary - Fireball", "FirePatchRadius", 6f, "Radio (m) de la zona de fuego.");
			FirePatchDuration = c.Bind<float>("2. Secondary - Fireball", "FirePatchDuration", 5f, "Duración (s) de la zona de fuego.");
			FirePatchTickInterval = c.Bind<float>("2. Secondary - Fireball", "FirePatchTickInterval", 0.5f, "Cada cuántos segundos hace daño la zona.");
			FirePatchTickDamage = c.Bind<float>("2. Secondary - Fireball", "FirePatchTickDamage", 0.5f, "Daño por tick de la zona con carga completa (0.5 = 50% daño base; con carga mínima hace la mitad). Cada tick aplica Ignite.");
			FirePatchProcCoefficient = c.Bind<float>("2. Secondary - Fireball", "FirePatchProcCoefficient", 0.3f, "Proc coefficient de cada tick de la zona.");
			TectonicEnabled = c.Bind<bool>("3. Utility - Tectonic Blast", "Enabled", true, "Reimplementa Tectonic Blast con carga: tap = vanilla; cargado = más alcance y más impulso hacia atrás (solo en el aire).");
			TectonicChargeTime = c.Bind<float>("3. Utility - Tectonic Blast", "ChargeTime", 1f, "Segundos para carga completa.");
			TectonicAutoFire = c.Bind<bool>("3. Utility - Tectonic Blast", "AutoFireAtFullCharge", true, "Dispara sola al llegar a carga completa.");
			TectonicShardCount = c.Bind<int>("3. Utility - Tectonic Blast", "ShardCount", 8, "Número de fragmentos (vanilla 8).");
			TectonicShardDamage = c.Bind<float>("3. Utility - Tectonic Blast", "ShardDamage", 1f, "Daño por fragmento (vanilla 1.0 = 100%).");
			TectonicSpreadAngle = c.Bind<float>("3. Utility - Tectonic Blast", "SpreadAngle", 18f, "Medio ángulo horizontal del abanico (grados). Cada fragmento además recibe un jitter aleatorio.");
			TectonicVerticalSpread = c.Bind<float>("3. Utility - Tectonic Blast", "VerticalSpread", 7f, "Medio ángulo vertical aleatorio (grados).");
			TectonicUseVanillaShard = c.Bind<bool>("3. Utility - Tectonic Blast", "UseVanillaShardPrefab", true, "Usa el proyectil de fragmento del Tectonic Blast vanilla (leído de tu juego). Si no se encuentra, usa un respaldo.");
			TectonicShardSpeed = c.Bind<float>("3. Utility - Tectonic Blast", "ShardSpeed", 70f, "Velocidad base de los fragmentos (m/s).");
			TectonicBaseRange = c.Bind<float>("3. Utility - Tectonic Blast", "BaseRange", 30f, "Alcance (m) sin carga.");
			TectonicMaxRangeMult = c.Bind<float>("3. Utility - Tectonic Blast", "MaxRangeMultiplier", 2f, "Multiplicador de alcance con carga completa.");
			TectonicShardBlastRadius = c.Bind<float>("3. Utility - Tectonic Blast", "ShardBlastRadius", 1.5f, "Radio (m) de la mini-explosión de cada fragmento.");
			TectonicShardForce = c.Bind<float>("3. Utility - Tectonic Blast", "ShardKnockback", 300f, "Fuerza de empuje a enemigos por fragmento.");
			TectonicBaseSelfForce = c.Bind<float>("3. Utility - Tectonic Blast", "BaseSelfKnockback", 18f, "Velocidad (m/s) con la que te empuja hacia atrás sin carga (en tierra y aire).");
			TectonicChargedSelfForce = c.Bind<float>("3. Utility - Tectonic Blast", "ChargedBonusSelfKnockback", 26f, "Velocidad extra (m/s) con carga completa. SOLO se aplica si estás en el aire.");
			TectonicGroundedMinUpward = c.Bind<float>("3. Utility - Tectonic Blast", "GroundedMinUpwardSpeed", 7f, "Si estás en el piso, mínimo de velocidad vertical para despegar.");
			OilDuration = c.Bind<float>("3. Utility - Tectonic Blast", "OilDuration", 6f, "Duración (s) del debuff Oil aplicado por los fragmentos.");
			OilBuffName = c.Bind<string>("3. Utility - Tectonic Blast", "OilBuffInternalName", "bdOiled", "Nombre interno del BuffDef de Oil de CHEF. Si no se encuentra, el mod busca cualquier buff cuyo nombre contenga 'oil'.");
			TectonicFallbackCooldown = c.Bind<float>("3. Utility - Tectonic Blast", "FallbackCooldown", 12f, "Cooldown usado SOLO si el mod no encuentra la Tectonic Blast vanilla y tiene que crear la skill desde cero.");
			PillarEnabled = c.Bind<bool>("4. Utility - Frost Pillar", "Enabled", true, "Rework de Snapfreeze: un solo pilar grande que explota al salir y deja una zona de nieve.");
			PillarRange = c.Bind<float>("4. Utility - Frost Pillar", "Range", 45f, "Alcance máximo (m) para colocar el pilar donde apuntas.");
			PillarCastDelay = c.Bind<float>("4. Utility - Frost Pillar", "CastDelay", 0.2f, "Retardo (s) desde que presionas hasta que sale el pilar.");
			PillarCastDuration = c.Bind<float>("4. Utility - Frost Pillar", "CastDuration", 0.6f, "Duración total de la animación (s).");
			PillarChargeTime = c.Bind<float>("4. Utility - Frost Pillar", "ChargeTime", 1.5f, "Segundos para carga completa (se divide entre attack speed). Tap = pilar y tormenta mínimos.");
			PillarMaxHoldTime = c.Bind<float>("4. Utility - Frost Pillar", "MaxHoldTime", 5f, "Si mantienes más de esto, se dispara sola.");
			PillarScaleMin = c.Bind<float>("4. Utility - Frost Pillar", "PillarScaleMin", 3.5f, "Escala del pilar central sin carga (respecto a un pilar normal de Snapfreeze).");
			PillarScaleMax = c.Bind<float>("4. Utility - Frost Pillar", "PillarScaleMax", 6f, "Escala del pilar central con carga completa.");
			PillarDuration = c.Bind<float>("4. Utility - Frost Pillar", "PillarDuration", 8f, "Segundos que vive el pilar (es sólido: bloquea).");
			PillarBurstDamage = c.Bind<float>("4. Utility - Frost Pillar", "BurstDamage", 3f, "Daño de la explosión al emerger sin carga (3.0 = 300%). Congela como Snapfreeze.");
			PillarBurstDamageMax = c.Bind<float>("4. Utility - Frost Pillar", "BurstDamageMax", 5f, "Daño de la explosión al emerger con carga completa (5.0 = 500%).");
			PillarBurstRadius = c.Bind<float>("4. Utility - Frost Pillar", "BurstRadius", 7f, "Radio (m) de la explosión al emerger sin carga; con carga completa usa el radio de la tormenta.");
			PillarBurstEffectScale = c.Bind<float>("4. Utility - Frost Pillar", "BurstEffectScale", 2.5f, "Tamaño fijo del efecto visual de la explosión (antes escalaba con el radio y tapaba todo).");
			SnowRingPillars = c.Bind<int>("4. Utility - Frost Pillar", "RingPillars", 6, "Pilares de hielo (sin daño, sólidos) alrededor del borde de la zona (0 = ninguno).");
			SnowRingPillarScale = c.Bind<float>("4. Utility - Frost Pillar", "RingPillarScale", 0.6f, "Escala de los pilares del anillo respecto a un pilar normal de Snapfreeze.");
			SnowVisualScale = c.Bind<float>("4. Utility - Frost Pillar", "AuraVisualScale", 1f, "Multiplicador del tamaño de la esfera de escarcha respecto al radio real de la zona (1.0 = coincide exactamente).");
			PillarEffectZUp = c.Bind<bool>("4. Utility - Frost Pillar", "PillarEffectZUp", true, "Orientación del efecto de explosión del pilar. true = eje Z hacia arriba.");
			SnowRadius = c.Bind<float>("4. Utility - Frost Pillar", "SnowRadius", 8f, "Radio (m) de la tormenta sin carga.");
			SnowRadiusMax = c.Bind<float>("4. Utility - Frost Pillar", "SnowRadiusMax", 14f, "Radio (m) de la tormenta con carga completa.");
			SnowDuration = c.Bind<float>("4. Utility - Frost Pillar", "SnowDuration", 8f, "Duración (s) de la zona de nieve.");
			SnowTickInterval = c.Bind<float>("4. Utility - Frost Pillar", "SnowTickInterval", 0.5f, "Cada cuántos segundos hace daño la zona.");
			SnowTickDamage = c.Bind<float>("4. Utility - Frost Pillar", "SnowTickDamage", 0.25f, "Daño por tick (0.25 = 25% daño base; poco, como pediste).");
			SnowSlowAfter = c.Bind<float>("4. Utility - Frost Pillar", "SlowAfterSeconds", 1f, "Tras estar este tiempo dentro, el enemigo se ralentiza (Slow 60%).");
			SnowFreezeAfter = c.Bind<float>("4. Utility - Frost Pillar", "FreezeAfterSeconds", 2.5f, "Tras estar este tiempo dentro, el enemigo se congela.");
			SnowFreezeDuration = c.Bind<float>("4. Utility - Frost Pillar", "FreezeDuration", 2f, "Duración (s) del congelamiento.");
			SnowRefreezeCooldown = c.Bind<float>("4. Utility - Frost Pillar", "RefreezeCooldown", 3f, "Tiempo (s) tras descongelarse antes de poder volver a congelarse en la zona.");
			FlameEnabled = c.Bind<bool>("5. Special - Flamethrower", "Enabled", true, "Más alcance, 1800% total y aplica Ember (fuego permanente que explota al morir).");
			FlameRange = c.Bind<float>("5. Special - Flamethrower", "Range", 32f, "Alcance (m). Vanilla ≈ 20.");
			FlameTotalDamage = c.Bind<float>("5. Special - Flamethrower", "TotalDamage", 18f, "Daño total del canal (vanilla 20 = 2000%).");
			FlameRadius = c.Bind<float>("5. Special - Flamethrower", "Radius", 0f, "Grosor del cono. 0 = dejar el vanilla.");
			FlameAgile = c.Bind<bool>("5. Special - Flamethrower", "Agile", true, "Se puede correr (sprint) mientras lanzas fuego.");
			FlameAirThrust = c.Bind<float>("5. Special - Flamethrower", "AirThrust", 12f, "Empuje (m/s² a attack speed 1.0) en dirección contraria a donde apuntas mientras lanzas fuego EN EL AIRE. Escala con attack speed: con mucho attack speed, apuntar al piso te hace volar. 0 = desactivado.");
			FlameMaxThrustSpeed = c.Bind<float>("5. Special - Flamethrower", "AirThrustMaxSpeed", 35f, "Velocidad máxima (m/s) que puede darte el empuje.");
			EmberTickInterval = c.Bind<float>("5. Special - Flamethrower", "EmberTickInterval", 0.5f, "Cada cuántos segundos hace daño Ember.");
			EmberTickDamage = c.Bind<float>("5. Special - Flamethrower", "EmberTickDamage", 0.06f, "Daño por tick de Ember (0.06 cada 0.5s = 12% daño base/s, parecido a un stack normal de Ignite del lanzallamas). No stackea, no expira.");
			EmberExplosionDamage = c.Bind<float>("5. Special - Flamethrower", "DeathExplosionDamage", 1.5f, "Daño de la explosión tipo Gasolina al morir un enemigo con Ember (1.5 = 150%).");
			EmberExplosionRadius = c.Bind<float>("5. Special - Flamethrower", "DeathExplosionRadius", 12f, "Radio (m) de la explosión (Gasolina = 12m). Aplica Ignite a los alcanzados.");
			EmberExplosionProc = c.Bind<float>("5. Special - Flamethrower", "DeathExplosionProcCoefficient", 0.5f, "Proc coefficient de la explosión.");
			EmberExplosionSpreadsEmber = c.Bind<bool>("5. Special - Flamethrower", "DeathExplosionSpreadsEmber", false, "Si true, la explosión también contagia Ember (reacción en cadena infinita; muy fuerte).");
			EmberVisual = c.Bind<bool>("5. Special - Flamethrower", "EmberVisual", true, "Muestra partículas de brasas en los enemigos con Ember.");
			IonEnabled = c.Bind<bool>("6. Special - Ion Glide", "Enabled", false, "Rework de Ion Surge (experimental): te lanza hacia donde miras y planeas tipo élitros; explosión al despegar y al aterrizar. Desactivado por defecto: deja Ion Surge vanilla.");
			IonLaunchSpeed = c.Bind<float>("6. Special - Ion Glide", "LaunchSpeed", 42f, "Velocidad inicial (m/s) hacia donde apuntas.");
			IonMinLaunchUpward = c.Bind<float>("6. Special - Ion Glide", "MinLaunchUpward", 0.25f, "Componente vertical mínima de la dirección de lanzamiento (0 = puedes lanzarte horizontal; 1 = siempre vertical).");
			IonBlastDamage = c.Bind<float>("6. Special - Ion Glide", "BlastDamage", 4.5f, "Daño de CADA explosión (despegue y aterrizaje). 4.5 = 450%.");
			IonBlastRadius = c.Bind<float>("6. Special - Ion Glide", "BlastRadius", 8f, "Radio (m) de las explosiones.");
			IonBlastStuns = c.Bind<bool>("6. Special - Ion Glide", "BlastStuns", true, "Las explosiones aturden (como Ion Surge vanilla).");
			IonGlideMaxTime = c.Bind<float>("6. Special - Ion Glide", "MaxGlideTime", 5f, "Tiempo máximo (s) planeando; después caes.");
			IonGravityScale = c.Bind<float>("6. Special - Ion Glide", "GravityScale", 0.35f, "Fracción de la gravedad que te afecta mientras planeas (0 = vuelo libre; 1 = caes como siempre). Picar la compensa.");
			IonDrag = c.Bind<float>("6. Special - Ion Glide", "Drag", 1.5f, "Pérdida de velocidad por segundo (m/s²) mientras planeas en horizontal.");
			IonDiveAccel = c.Bind<float>("6. Special - Ion Glide", "DiveAcceleration", 10f, "Aceleración (m/s²) al mirar hacia abajo (picar).");
			IonClimbPenalty = c.Bind<float>("6. Special - Ion Glide", "ClimbPenalty", 5f, "Pérdida extra de velocidad (m/s²) al mirar hacia arriba (subir).");
			IonMaxSpeed = c.Bind<float>("6. Special - Ion Glide", "MaxSpeed", 75f, "Velocidad máxima planeando.");
			IonMinSpeed = c.Bind<float>("6. Special - Ion Glide", "MinSpeed", 6f, "Si bajas de esta velocidad pierdes el impulso y caes (conservando la velocidad que llevabas).");
			IonSteerRate = c.Bind<float>("6. Special - Ion Glide", "SteerRate", 3.5f, "Qué tan rápido gira la trayectoria hacia donde miras (mayor = más ágil).");
			IonJumpCancels = c.Bind<bool>("6. Special - Ion Glide", "JumpCancelsGlide", false, "Presionar salto durante el planeo corta el impulso. OJO: si juegas Artificer manteniendo salto para flotar, déjalo en false.");
			IonSpecialCancels = c.Bind<bool>("6. Special - Ion Glide", "SpecialKeyCancelsGlide", true, "Volver a presionar la tecla de especial durante el planeo corta el impulso y caes.");
			IonIgnoreFallDamage = c.Bind<bool>("6. Special - Ion Glide", "IgnoreFallDamage", true, "Sin daño de caída al aterrizar del planeo (Ion Surge vanilla sí te lo hace).");
			IonTiltAngle = c.Bind<float>("6. Special - Ion Glide", "TiltAngle", 65f, "Grados que se inclina el modelo hacia adelante mientras planea (0 = sin inclinar; negativo si te sale al revés).");
		}
	}
	internal static class Content
	{
		public static BuffDef EmberBuff;

		public static void Init()
		{
			RegisterStates();
			RegisterBuffs();
			if (Cfg.ChainEnabled.Value)
			{
				ChainBoltContent.Build();
			}
			if (Cfg.FireballEnabled.Value)
			{
				FireballContent.Build();
			}
			if (Cfg.TectonicEnabled.Value)
			{
				TectonicContent.Build();
			}
			if (Cfg.PillarEnabled.Value)
			{
				FrostPillarContent.Build();
			}
			if (Cfg.IonEnabled.Value)
			{
				IonGlideContent.Build();
			}
		}

		private static void RegisterStates()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0062: 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_0072: 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)
			bool flag = default(bool);
			ContentAddition.AddEntityState<FireChainBolt>(ref flag);
			ContentAddition.AddEntityState<ChargeFireball>(ref flag);
			ContentAddition.AddEntityState<ThrowFireball>(ref flag);
			ContentAddition.AddEntityState<ChargeTectonicBlast>(ref flag);
			ContentAddition.AddEntityState<FireTectonicBlast>(ref flag);
			ContentAddition.AddEntityState<FireFrostPillar>(ref flag);
			ContentAddition.AddEntityState<IonGlideState>(ref flag);
			ContentAddition.AddEntityState<IonLandingBlast>(ref flag);
			ContentAddition.AddEntityState<FireChainBoltVanilla>(ref flag);
			ContentAddition.AddEntityState<ChargeFireballVanilla>(ref flag);
			ContentAddition.AddEntityState<ThrowFireballVanilla>(ref flag);
			ContentAddition.AddEntityState<ChargeTectonicVanilla>(ref flag);
			ContentAddition.AddEntityState<FireTectonicVanilla>(ref flag);
			ContentAddition.AddEntityState<ChargeFrostPillarVanilla>(ref flag);
			ContentAddition.AddEntityState<FireFrostPillarThrow>(ref flag);
			ContentAddition.AddEntityState<IonGlideVanilla>(ref flag);
		}

		private static void RegisterBuffs()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			EmberBuff = ScriptableObject.CreateInstance<BuffDef>();
			((Object)EmberBuff).name = "bdArtiReworkEmber";
			EmberBuff.buffColor = new Color(0.95f, 0.12f, 0.05f);
			EmberBuff.canStack = false;
			EmberBuff.isDebuff = true;
			EmberBuff.isHidden = false;
			EmberBuff.isCooldown = false;
			EmberBuff.iconSprite = Assets.OnFireIcon;
			ContentAddition.AddBuffDef(EmberBuff);
		}

		public static void OnGameLoaded()
		{
			if (Object.op_Implicit((Object)(object)EmberBuff) && !Object.op_Implicit((Object)(object)EmberBuff.iconSprite) && Object.op_Implicit((Object)(object)Buffs.OnFire))
			{
				EmberBuff.iconSprite = Buffs.OnFire.iconSprite;
			}
		}
	}
	internal static class DamageEvents
	{
		public static void Init()
		{
			GlobalEventManager.onServerDamageDealt += OnServerDamageDealt;
			GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath;
			CharacterBody.onBodyStartGlobal += OnBodyStart;
		}

		private static void OnBodyStart(CharacterBody body)
		{
			if (Object.op_Implicit((Object)(object)body))
			{
				if (Cfg.FlameEnabled.Value && Cfg.EmberVisual.Value)
				{
					((Component)body).gameObject.AddComponent<EmberVisual>();
				}
				if (Cfg.FlameEnabled.Value && Cfg.FlameAirThrust.Value > 0f && ((Object)body).name.StartsWith("MageBody", StringComparison.Ordinal))
				{
					((Component)body).gameObject.AddComponent<FlamethrowerThrust>();
				}
			}
		}

		private static void OnServerDamageDealt(DamageReport report)
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Invalid comparison between Unknown and I4
			if (!NetworkServer.active || report == null)
			{
				return;
			}
			try
			{
				DamageInfo damageInfo = report.damageInfo;
				CharacterBody victimBody = report.victimBody;
				if (damageInfo == null || !Object.op_Implicit((Object)(object)victimBody))
				{
					return;
				}
				if (Cfg.TectonicEnabled.Value && Object.op_Implicit((Object)(object)damageInfo.inflictor) && Object.op_Implicit((Object)(object)damageInfo.inflictor.GetComponent<OilOnHitMarker>()))
				{
					OilBuff.Apply(victimBody, Cfg.OilDuration.Value);
				}
				if (Cfg.FlameEnabled.Value && Object.op_Implicit((Object)(object)report.attacker) && Object.op_Implicit((Object)(object)report.attackerBody) && damageInfo.procCoefficient > 0f)
				{
					bool num = (Object)(object)damageInfo.inflictor == (Object)(object)report.attacker || (Object)(object)damageInfo.inflictor == (Object)null;
					bool flag = (int)damageInfo.damageType.damageSource == 8;
					if ((num || flag) && IsFlamethrowing(report.attacker))
					{
						Ember.Apply(victimBody, report.attacker, report.attackerBody.damage);
					}
				}
			}
			catch (Exception ex)
			{
				Log.Error("OnServerDamageDealt: " + ex);
			}
		}

		private static bool IsFlamethrowing(GameObject attacker)
		{
			EntityStateMachine val = EntityStateMachine.FindByCustomName(attacker, "Weapon");
			if (Object.op_Implicit((Object)(object)val))
			{
				return val.state is Flamethrower;
			}
			return false;
		}

		private static void OnCharacterDeath(DamageReport report)
		{
			if (!NetworkServer.active || report == null)
			{
				return;
			}
			try
			{
				CharacterBody victimBody = report.victimBody;
				if (Object.op_Implicit((Object)(object)victimBody) && Object.op_Implicit((Object)(object)Content.EmberBuff) && victimBody.HasBuff(Content.EmberBuff))
				{
					Ember.Detonate(victimBody, report);
				}
			}
			catch (Exception ex)
			{
				Log.Error("OnCharacterDeath: " + ex);
			}
		}
	}
	internal static class Dmg
	{
		public static DamageTypeCombo Combo(DamageType type, DamageSource source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			DamageTypeCombo result = DamageTypeCombo.op_Implicit(type);
			result.damageSource = source;
			return result;
		}

		public static void Hit(CharacterBody victim, GameObject attacker, GameObject inflictor, float damage, bool crit, float procCoefficient, DamageTypeCombo damageType, DamageColorIndex color, bool triggerOnHit = true)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0029: 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)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_005f: 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)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)victim.healthComponent))
			{
				DamageInfo val = new DamageInfo
				{
					attacker = attacker,
					inflictor = inflictor,
					damage = damage,
					crit = crit,
					position = victim.corePosition,
					force = Vector3.zero,
					procCoefficient = procCoefficient,
					damageType = damageType,
					damageColorIndex = color
				};
				victim.healthComponent.TakeDamage(val);
				if (triggerOnHit && Object.op_Implicit((Object)(object)GlobalEventManager.instance))
				{
					GlobalEventManager.instance.OnHitEnemy(val, ((Component)victim).gameObject);
					GlobalEventManager.instance.OnHitAll(val, ((Component)victim).gameObject);
				}
			}
		}

		public static void Effect(GameObject prefab, Vector3 position, float scale, Vector3? normal = null)
		{
			//IL_0009: 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_000f: 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_001d: Expected O, but got Unknown
			//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)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)prefab))
			{
				EffectData val = new EffectData
				{
					origin = position,
					scale = scale
				};
				if (normal.HasValue)
				{
					val.rotation = Util.QuaternionSafeLookRotation(normal.Value);
				}
				EffectManager.SpawnEffect(prefab, val, true);
			}
		}
	}
	internal static class EscUtil
	{
		public static EntityStateConfiguration Load(string key)
		{
			return Assets.Load<EntityStateConfiguration>(key);
		}

		public static string FindKeyForType(Type stateType)
		{
			if (stateType == null)
			{
				return null;
			}
			string value = stateType.FullName + ".asset";
			try
			{
				foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
				{
					if (((resourceLocator != null) ? resourceLocator.Keys : null) == null)
					{
						continue;
					}
					foreach (object key in resourceLocator.Keys)
					{
						if (key is string text && text.EndsWith(value, StringComparison.Ordinal))
						{
							return text;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.Warn("FindKeyForType falló: " + ex.Message);
			}
			return null;
		}

		public static bool HasField(EntityStateConfiguration esc, string fieldName)
		{
			if (!Object.op_Implicit((Object)(object)esc))
			{
				return false;
			}
			SerializedField[] serializedFields = esc.serializedFieldsCollection.serializedFields;
			if (serializedFields == null)
			{
				return false;
			}
			for (int i = 0; i < serializedFields.Length; i++)
			{
				if (serializedFields[i].fieldName == fieldName)
				{
					return true;
				}
			}
			return false;
		}

		public static Object GetObject(EntityStateConfiguration esc, string fieldName)
		{
			if (!Object.op_Implicit((Object)(object)esc))
			{
				return null;
			}
			SerializedField[] serializedFields = esc.serializedFieldsCollection.serializedFields;
			if (serializedFields == null)
			{
				return null;
			}
			for (int i = 0; i < serializedFields.Length; i++)
			{
				if (serializedFields[i].fieldName == fieldName)
				{
					return serializedFields[i].fieldValue.objectValue;
				}
			}
			return null;
		}

		public static string GetString(EntityStateConfiguration esc, string fieldName)
		{
			if (!Object.op_Implicit((Object)(object)esc))
			{
				return null;
			}
			SerializedField[] serializedFields = esc.serializedFieldsCollection.serializedFields;
			if (serializedFields == null)
			{
				return null;
			}
			for (int i = 0; i < serializedFields.Length; i++)
			{
				if (serializedFields[i].fieldName == fieldName)
				{
					return serializedFields[i].fieldValue.stringValue;
				}
			}
			return null;
		}

		public static GameObject FindGameObjectField(EntityStateConfiguration esc, params string[] nameHints)
		{
			if (!Object.op_Implicit((Object)(object)esc))
			{
				return null;
			}
			SerializedField[] serializedFields = esc.serializedFieldsCollection.serializedFields;
			if (serializedFields == null)
			{
				return null;
			}
			for (int i = 0; i < nameHints.Length; i++)
			{
				for (int j = 0; j < serializedFields.Length; j++)
				{
					Object objectValue = serializedFields[j].fieldValue.objectValue;
					GameObject val = (GameObject)(object)((objectValue is GameObject) ? objectValue : null);
					if (val != null && serializedFields[j].fieldName.IndexOf(nameHints[i], StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return val;
					}
				}
			}
			return null;
		}

		public static EntityStateConfiguration CloneFor(EntityStateConfiguration vanilla, Type newType, string name)
		{
			if (!Object.op_Implicit((Object)(object)vanilla))
			{
				return null;
			}
			EntityStateConfiguration val = Object.Instantiate<EntityStateConfiguration>(vanilla);
			((Object)val).name = name;
			if (!SetTargetType(val, newType))
			{
				Log.Warn("ESC " + name + ": no pude fijar el targetType; se descarta.");
				return null;
			}
			return val;
		}

		public static void Register(EntityStateConfiguration esc)
		{
			if (Object.op_Implicit((Object)(object)esc))
			{
				ContentAddition.AddEntityStateConfiguration(esc);
			}
		}

		public static void Set(EntityStateConfiguration esc, string fieldName, Object value)
		{
			SetRaw(esc, fieldName, null, value);
		}

		public static void Set(EntityStateConfiguration esc, string fieldName, float value)
		{
			SetRaw(esc, fieldName, value.ToString(CultureInfo.InvariantCulture), null);
		}

		public static void Set(EntityStateConfiguration esc, string fieldName, int value)
		{
			SetRaw(esc, fieldName, value.ToString(CultureInfo.InvariantCulture), null);
		}

		public static void Set(EntityStateConfiguration esc, string fieldName, string value)
		{
			SetRaw(esc, fieldName, value, null);
		}

		private static void SetRaw(EntityStateConfiguration esc, string fieldName, string stringValue, Object objectValue)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)esc))
			{
				return;
			}
			SerializedField[] serializedFields = esc.serializedFieldsCollection.serializedFields;
			if (serializedFields != null)
			{
				for (int i = 0; i < serializedFields.Length; i++)
				{
					if (!(serializedFields[i].fieldName != fieldName))
					{
						serializedFields[i].fieldValue.stringValue = stringValue;
						serializedFields[i].fieldValue.objectValue = objectValue;
						return;
					}
				}
			}
			SerializedField val = new SerializedField
			{
				fieldName = fieldName,
				fieldValue = new SerializedValue
				{
					stringValue = stringValue,
					objectValue = objectValue
				}
			};
			ArrayUtils.ArrayAppend<SerializedField>(ref esc.serializedFieldsCollection.serializedFields, ref val);
		}

		public static string Describe(EntityStateConfiguration esc)
		{
			if (!Object.op_Implicit((Object)(object)esc))
			{
				return "(null)";
			}
			SerializedField[] serializedFields = esc.serializedFieldsCollection.serializedFields;
			if (serializedFields == null)
			{
				return "(sin campos)";
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < serializedFields.Length; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(serializedFields[i].fieldName).Append('=');
				if (Object.op_Implicit(serializedFields[i].fieldValue.objectValue))
				{
					stringBuilder.Append('[').Append(serializedFields[i].fieldValue.objectValue.name).Append(']');
				}
				else
				{
					stringBuilder.Append(serializedFields[i].fieldValue.stringValue);
				}
			}
			return stringBuilder.ToString();
		}

		public static Type GetTargetType(EntityStateConfiguration esc)
		{
			if (!Object.op_Implicit((Object)(object)esc))
			{
				return null;
			}
			try
			{
				FieldInfo field = typeof(EntityStateConfiguration).GetField("targetType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				PropertyInfo propertyInfo = ((field == null) ? typeof(EntityStateConfiguration).GetProperty("targetType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : null);
				object value;
				if (field != null)
				{
					value = field.GetValue(esc);
				}
				else
				{
					if (!(propertyInfo != null))
					{
						return null;
					}
					value = propertyInfo.GetValue(esc);
				}
				if (value == null)
				{
					return null;
				}
				Type type = value.GetType();
				FieldInfo fieldInfo = type.GetField("_typeName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (fieldInfo == null)
				{
					FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo2 in fields)
					{
						if (fieldInfo2.FieldType == typeof(string))
						{
							fieldInfo = fieldInfo2;
							break;
						}
					}
				}
				string text = fieldInfo?.GetValue(value) as string;
				return string.IsNullOrEmpty(text) ? null : Type.GetType(text);
			}
			catch (Exception ex)
			{
				Log.Warn("GetTargetType falló: " + ex.Message);
				return null;
			}
		}

		private static bool SetTargetType(EntityStateConfiguration esc, Type type)
		{
			try
			{
				FieldInfo field = typeof(EntityStateConfiguration).GetField("targetType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				PropertyInfo propertyInfo = ((field == null) ? typeof(EntityStateConfiguration).GetProperty("targetType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : null);
				object value;
				if (field != null)
				{
					value = field.GetValue(esc);
				}
				else
				{
					if (!(propertyInfo != null))
					{
						return false;
					}
					value = propertyInfo.GetValue(esc);
				}
				Type type2 = value.GetType();
				FieldInfo fieldInfo = type2.GetField("_typeName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (fieldInfo == null)
				{
					FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo2 in fields)
					{
						if (fieldInfo2.FieldType == typeof(string))
						{
							fieldInfo = fieldInfo2;
							break;
						}
					}
				}
				if (fieldInfo == null)
				{
					return false;
				}
				fieldInfo.SetValue(value, type.AssemblyQualifiedName);
				if (field != null)
				{
					field.SetValue(esc, value);
				}
				else
				{
					propertyInfo.SetValue(esc, value);
				}
				return true;
			}
			catch (Exception ex)
			{
				Log.Warn("SetTargetType falló: " + ex);
				return false;
			}
		}
	}
	internal sealed class FieldOverride
	{
		private readonly FieldInfo field;

		private readonly object target;

		private readonly object original;

		private readonly bool applied;

		public FieldOverride(object instance, string fieldName, object value)
		{
			Type type = instance.GetType();
			while (type != null && field == null)
			{
				field = type.GetField(fieldName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				type = type.BaseType;
			}
			if (field == null)
			{
				Log.Warn("FieldOverride: '" + fieldName + "' no existe en " + instance.GetType().Name + "; no se aplicó.");
				return;
			}
			try
			{
				target = (field.IsStatic ? null : instance);
				original = field.GetValue(target);
				object value2 = value;
				if (value != null && !field.FieldType.IsInstanceOfType(value))
				{
					value2 = Convert.ChangeType(value, field.FieldType);
				}
				field.SetValue(target, value2);
				applied = true;
			}
			catch (Exception ex)
			{
				Log.Warn("FieldOverride: no pude escribir '" + fieldName + "': " + ex.Message);
			}
		}

		public void Restore()
		{
			if (!applied)
			{
				return;
			}
			try
			{
				field.SetValue(target, original);
			}
			catch (Exception ex)
			{
				Log.Warn("FieldOverride: no pude restaurar '" + field.Name + "': " + ex.Message);
			}
		}
	}
	internal static class OilBuff
	{
		public static BuffDef Def;

		private static bool isFallback;

		public static string DisplayName
		{
			get
			{
				if (!isFallback)
				{
					return "Oil";
				}
				return "Slow";
			}
		}

		public static void Resolve()
		{
			Def = null;
			string value = Cfg.OilBuffName.Value;
			BuffDef val = null;
			int buffCount = BuffCatalog.buffCount;
			for (int i = 0; i < buffCount; i++)
			{
				BuffDef buffDef = BuffCatalog.GetBuffDef((BuffIndex)i);
				if (Object.op_Implicit((Object)(object)buffDef) && !string.IsNullOrEmpty(((Object)buffDef).name))
				{
					if (string.Equals(((Object)buffDef).name, value, StringComparison.OrdinalIgnoreCase))
					{
						Def = buffDef;
						break;
					}
					if ((Object)(object)val == (Object)null && ((Object)buffDef).name.IndexOf("oil", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						val = buffDef;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)Def))
			{
				Def = val;
			}
			if (Object.op_Implicit((Object)(object)Def))
			{
				isFallback = false;
				Log.Info("Oil: usando buff '" + ((Object)Def).name + "'.");
			}
			else
			{
				isFallback = true;
				Def = Buffs.Slow60;
				Log.Warn("Oil: no se encontró ningún buff con 'oil' en el nombre (¿no tienes el DLC Seekers of the Storm?). Los fragmentos aplicarán Slow60 en su lugar. Puedes poner el nombre correcto en la config (OilBuffInternalName).");
			}
		}

		public static void Apply(CharacterBody victim, float duration)
		{
			if (Object.op_Implicit((Object)(object)victim) && Object.op_Implicit((Object)(object)Def))
			{
				victim.AddTimedBuff(Def, duration);
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.ror2.artificer.rework", "ArtificerRework", "1.1.3")]
	public sealed class ArtificerReworkPlugin : BaseUnityPlugin
	{
		public const string Guid = "com.ror2.artificer.rework";

		public const string Name = "ArtificerRework";

		public const string Version = "1.1.3";

		internal static ManualLogSource LogSource;

		private void Awake()
		{
			LogSource = ((BaseUnityPlugin)this).Logger;
			Log.Info("ArtificerRework 1.1.3 cargando...");
			try
			{
				Cfg.Init(((BaseUnityPlugin)this).Config);
				Assets.Init();
				Content.Init();
				SkillSetup.Init();
				DamageEvents.Init();
				Tokens.Init();
				FlamethrowerTweaks.ApplyToEsc();
				RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnGameLoaded));
				Log.Info("Listo. Los cambios de Flamethrower y el buff Oil se aplican cuando termine de cargar el juego.");
			}
			catch (Exception ex)
			{
				Log.Error("Error fatal inicializando el mod: " + ex);
			}
		}

		private static void OnGameLoaded()
		{
			try
			{
				Content.OnGameLoaded();
				FlamethrowerTweaks.ApplyStatics();
				OilBuff.Resolve();
				TectonicContent.OnGameLoaded();
			}
			catch (Exception ex)
			{
				Log.Error("Error en onLoad: " + ex);
			}
		}
	}
	internal static class Log
	{
		public static void Info(string msg)
		{
			ManualLogSource logSource = ArtificerReworkPlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogInfo((object)msg);
			}
		}

		public static void Warn(string msg)
		{
			ManualLogSource logSource = ArtificerReworkPlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogWarning((object)msg);
			}
		}

		public static void Error(string msg)
		{
			ManualLogSource logSource = ArtificerReworkPlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogError((object)msg);
			}
		}
	}
	internal static class RuntimeVfx
	{
		public struct EmitterSpec
		{
			public Material material;

			public Color colorA;

			public Color colorB;

			public float radius;

			public float rate;

			public float size;

			public float lifetime;

			public float speed;

			public bool falling;

			public float height;
		}

		private static Material _fire;

		private static Material _ice;

		public static Material FireMaterial
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)_fire))
				{
					Material obj = FindParticleMaterial(Assets.FxFireExplosion) ?? FindParticleMaterial(Assets.FxGasolineExplosion);
					_fire = obj;
					return obj;
				}
				return _fire;
			}
		}

		public static Material IceMaterial
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)_ice))
				{
					Material obj = FindParticleMaterial(Assets.FxIceExplosion) ?? FindParticleMaterial(Assets.FxIceRing);
					_ice = obj;
					return obj;
				}
				return _ice;
			}
		}

		public static Material FindParticleMaterial(GameObject prefab)
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			ParticleSystemRenderer[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystemRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[i]) && Object.op_Implicit((Object)(object)((Renderer)componentsInChildren[i]).sharedMaterial))
				{
					return ((Renderer)componentsInChildren[i]).sharedMaterial;
				}
			}
			return null;
		}

		public static GameObject AddEmitter(Transform parent, string name, EmitterSpec spec)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: 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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: 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)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: 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_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			val.transform.localPosition = (spec.falling ? (Vector3.up * spec.height) : Vector3.zero);
			val.transform.localRotation = Quaternion.Euler(spec.falling ? 90f : (-90f), 0f, 0f);
			ParticleSystem obj = val.AddComponent<ParticleSystem>();
			MainModule main = obj.main;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).playOnAwake = true;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(spec.lifetime * 0.7f, spec.lifetime * 1.3f);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(spec.speed * 0.6f, spec.speed * 1.4f);
			((MainModule)(ref main)).startSize = new MinMaxCurve(spec.size * 0.6f, spec.size * 1.4f);
			((MainModule)(ref main)).startColor = new MinMaxGradient(spec.colorA, spec.colorB);
			((MainModule)(ref main)).startRotation = new MinMaxCurve(0f, MathF.PI * 2f);
			((MainModule)(ref main)).maxParticles = 600;
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(spec.falling ? 0.15f : (-0.05f));
			EmissionModule emission = obj.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(spec.rate);
			ShapeModule shape = obj.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4;
			((ShapeModule)(ref shape)).angle = 0f;
			((ShapeModule)(ref shape)).radius = Mathf.Max(0.1f, spec.radius);
			((ShapeModule)(ref shape)).radiusThickness = 1f;
			ColorOverLifetimeModule colorOverLifetime = obj.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val2 = new Gradient();
			val2.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(Color.white, 0f),
				new GradientColorKey(Color.white, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(0f, 0f),
				new GradientAlphaKey(1f, 0.15f),
				new GradientAlphaKey(1f, 0.6f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val2);
			ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
			component.renderMode = (ParticleSystemRenderMode)0;
			if (Object.op_Implicit((Object)(object)spec.material))
			{
				((Renderer)component).material = spec.material;
			}
			else
			{
				Log.Warn("RuntimeVfx: sin material para '" + name + "', el emisor queda apagado.");
				((Renderer)component).enabled = false;
			}
			return val;
		}

		public static GameObject BuildZoneGhost(string name, EmitterSpec spec)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			GameObject val = new GameObject(name + "Tmp");
			val.SetActive(false);
			val.AddComponent<ProjectileGhostController>();
			AddEmitter(val.transform, "Emitter", spec);
			GameObject obj = PrefabAPI.InstantiateClone(val, name, false);
			obj.SetActive(true);
			Object.Destroy((Object)(object)val);
			return obj;
		}

		public static EmitterSpec FirePatchSpec(float radius)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			return new EmitterSpec
			{
				material = FireMaterial,
				colorA = new Color(1f, 0.55f, 0.1f, 0.9f),
				colorB = new Color(1f, 0.15f, 0.02f, 0.9f),
				radius = radius * 0.9f,
				rate = 18f * radius,
				size = 1.6f,
				lifetime = 0.9f,
				speed = 2.5f,
				falling = false
			};
		}

		public static EmitterSpec SnowSpec(float radius)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			return new EmitterSpec
			{
				material = IceMaterial,
				colorA = new Color(0.85f, 0.95f, 1f, 0.9f),
				colorB = new Color(0.55f, 0.8f, 1f, 0.9f),
				radius = radius,
				rate = 10f * radius,
				size = 0.7f,
				lifetime = 2.2f,
				speed = 3f,
				falling = true,
				height = 7f
			};
		}

		public static EmitterSpec EmberSpec(float radius)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			return new EmitterSpec
			{
				material = FireMaterial,
				colorA = new Color(1f, 0.6f, 0.1f, 0.8f),
				colorB = new Color(1f, 0.2f, 0.05f, 0.8f),
				radius = radius,
				rate = 10f + 6f * radius,
				size = 0.7f,
				lifetime = 0.7f,
				speed = 1.5f,
				falling = false
			};
		}
	}
	internal static class SkillSetup
	{
		public static bool tectonicApplied;

		public static void Init()
		{
			ReworkMode value = Cfg.Mode.Value;
			if (Cfg.ChainEnabled.Value && Object.op_Implicit((Object)(object)ChainBoltContent.projectilePrefab))
			{
				Type chainState = (Object.op_Implicit((Object)(object)ChainBoltContent.vanillaEsc) ? typeof(FireChainBoltVanilla) : typeof(FireChainBolt));
				Log.Info("Chain Bolt usa estado: " + chainState.Name);
				Rework(Assets.PrimaryFamily, Assets.SdPlasmaBolt, value, "ArtiRework_ChainBolt", delegate(SkillDef def)
				{
					//IL_0007: 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)
					def.activationState = new SerializableEntityStateType(chainState);
					def.activationStateMachineName = "Weapon";
					def.skillNameToken = "ARTIREWORK_CHAINBOLT_NAME";
					def.skillDescriptionToken = "ARTIREWORK_CHAINBOLT_DESC";
					def.keywordTokens = Array.Empty<string>();
				});
			}
			if (Cfg.FireballEnabled.Value && Object.op_Implicit((Object)(object)FireballContent.projectilePrefab))
			{
				Type fireballState = ((Object.op_Implicit((Object)(object)FireballContent.chargeEsc) && Object.op_Implicit((Object)(object)FireballContent.throwEsc)) ? typeof(ChargeFireballVanilla) : typeof(ChargeFireball));
				Log.Info("Fireball usa estado: " + fireballState.Name);
				Rework(Assets.SecondaryFamily, Assets.SdNanoBomb, ReworkMode.AddVariant, "ArtiRework_Fireball", delegate(SkillDef def)
				{
					//IL_0007: 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)
					def.activationState = new SerializableEntityStateType(fireballState);
					def.activationStateMachineName = "Weapon";
					def.skillNameToken = "ARTIREWORK_FIREBALL_NAME";
					def.skillDescriptionToken = "ARTIREWORK_FIREBALL_DESC";
					def.keywordTokens = new string[1] { "KEYWORD_IGNITE" };
					def.baseRechargeInterval = Cfg.FireballCooldown.Value;
					def.baseMaxStock = 1;
					def.rechargeStock = 1;
					def.requiredStock = 1;
					def.stockToConsume = 1;
					def.mustKeyPress = true;
					def.beginSkillCooldownOnSkillEnd = true;
					if (Object.op_Implicit((Object)(object)Assets.SdFireBolt) && Object.op_Implicit((Object)(object)Assets.SdFireBolt.icon))
					{
						def.icon = Assets.SdFireBolt.icon;
					}
				});
			}
			if (Cfg.TectonicEnabled.Value && Object.op_Implicit((Object)(object)TectonicContent.shardPrefab))
			{
				Type tectonicState = TectonicState();
				Log.Info("Tectonic Blast usa estado: " + tectonicState.Name);
				SkillDef vanillaSkill = TectonicContent.vanillaSkill;
				if (Object.op_Implicit((Object)(object)vanillaSkill))
				{
					ApplyTectonicInPlace(vanillaSkill);
				}
				else
				{
					Log.Warn("Tectonic Blast vanilla todavía no localizada; creo una variante propia y reintento al terminar la carga.");
					Rework(Assets.UtilityFamily, Assets.SdSnapfreeze, ReworkMode.AddVariant, "ArtiRework_TectonicBlast", delegate(SkillDef def)
					{
						//IL_0007: 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)
						def.activationState = new SerializableEntityStateType(tectonicState);
						def.activationStateMachineName = "Weapon";
						def.skillNameToken = "ARTIREWORK_TECTONIC_NAME";
						def.skillDescriptionToken = "ARTIREWORK_TECTONIC_DESC";
						def.keywordTokens = Array.Empty<string>();
						def.baseRechargeInterval = Cfg.TectonicFallbackCooldown.Value;
						def.baseMaxStock = 1;
						def.rechargeStock = 1;
						def.requiredStock = 1;
						def.stockToConsume = 1;
						def.mustKeyPress = true;
						def.beginSkillCooldownOnSkillEnd = true;
						def.cancelSprintingOnActivation = false;
						def.canceledFromSprinting = false;
					});
				}
			}
			if (Cfg.PillarEnabled.Value && Object.op_Implicit((Object)(object)FrostPillarContent.pillarPrefab))
			{
				Type pillarState = ((Object.op_Implicit((Object)(object)FrostPillarContent.chargeEsc) && Object.op_Implicit((Object)(object)FrostPillarContent.throwEsc)) ? typeof(ChargeFrostPillarVanilla) : typeof(FireFrostPillar));
				Log.Info("Pilar Glacial usa estado: " + pillarState.Name);
				Rework(Assets.UtilityFamily, Assets.SdSnapfreeze, value, "ArtiRework_GlacialPillar", delegate(SkillDef def)
				{
					//IL_0007: 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)
					def.activationState = new SerializableEntityStateType(pillarState);
					def.activationStateMachineName = "Weapon";
					def.skillNameToken = "ARTIREWORK_PILLAR_NAME";
					def.skillDescriptionToken = "ARTIREWORK_PILLAR_DESC";
					def.keywordTokens = new string[1] { "KEYWORD_FREEZING" };
					def.mustKeyPress = true;
				});
			}
			if (Cfg.FlameEnabled.Value && Object.op_Implicit((Object)(object)Assets.SdFlamethrower))
			{
				Assets.SdFlamethrower.skillDescriptionToken = "ARTIREWORK_FLAMETHROWER_DESC";
				Assets.SdFlamethrower.keywordTokens = ((!Cfg.FlameAgile.Value) ? new string[2] { "KEYWORD_IGNITE", "KEYWORD_ARTIREWORK_EMBER" } : new string[3] { "KEYWORD_AGILE", "KEYWORD_IGNITE", "KEYWORD_ARTIREWORK_EMBER" });
				if (Cfg.FlameAgile.Value)
				{
					Assets.SdFlamethrower.canceledFromSprinting = false;
					Assets.SdFlamethrower.cancelSprintingOnActivation = false;
				}
			}
			if (Cfg.IonEnabled.Value)
			{
				Type ionState = (Object.op_Implicit((Object)(object)IonGlideContent.vanillaEsc) ? typeof(IonGlideVanilla) : typeof(IonGlideState));
				Log.Info("Ion Glide usa estado: " + ionState.Name);
				Rework(Assets.SpecialFamily, Assets.SdIonSurge, value, "ArtiRework_IonGlide", delegate(SkillDef def)
				{
					//IL_0007: 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_005b: Unknown result type (might be due to invalid IL or missing references)
					def.activationState = new SerializableEntityStateType(ionState);
					def.activationStateMachineName = "Body";
					def.skillNameToken = "ARTIREWORK_IONGLIDE_NAME";
					def.skillDescriptionToken = "ARTIREWORK_IONGLIDE_DESC";
					def.keywordTokens = ((!Cfg.IonBlastStuns.Value) ? Array.Empty<string>() : new string[1] { "KEYWORD_STUNNING" });
					def.interruptPriority = (InterruptPriority)1;
					def.mustKeyPress = true;
					def.canceledFromSprinting = false;
					def.cancelSprintingOnActivation = false;
					def.forceSprintDuringState = false;
					def.beginSkillCooldownOnSkillEnd = true;
				});
			}
		}

		private static Type TectonicState()
		{
			if (!Object.op_Implicit((Object)(object)TectonicContent.chargeEsc) || !Object.op_Implicit((Object)(object)TectonicContent.fireEsc))
			{
				return typeof(ChargeTectonicBlast);
			}
			return typeof(ChargeTectonicVanilla);
		}

		public static void ApplyTectonicInPlace(SkillDef vanilla)
		{
			//IL_001e: 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 (Object.op_Implicit((Object)(object)vanilla) && !tectonicApplied)
			{
				tectonicApplied = true;
				Type type = TectonicState();
				vanilla.activationState = new SerializableEntityStateType(type);
				vanilla.activationStateMachineName = "Weapon";
				vanilla.skillDescriptionToken = "ARTIREWORK_TECTONIC_DESC";
				vanilla.mustKeyPress = true;
				vanilla.beginSkillCooldownOnSkillEnd = true;
				Log.Info($"Tectonic Blast: rework aplicado a '{vanilla.skillName}' (estado {type.Name}, cooldown {vanilla.baseRechargeInterval}s).");
			}
		}

		private static void Rework(SkillFamily family, SkillDef vanilla, ReworkMode mode, string newName, Action<SkillDef> edit)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)family) || !Object.op_Implicit((Object)(object)vanilla))
			{
				Log.Warn(newName + ": falta la familia o el SkillDef vanilla; se omite.");
				return;
			}
			if (mode == ReworkMode.Replace)
			{
				edit(vanilla);
				Log.Info(newName + ": reemplazada en su lugar (vanilla: " + vanilla.skillName + ").");
				return;
			}
			SkillDef val = Object.Instantiate<SkillDef>(vanilla);
			((Object)val).name = newName;
			val.skillName = newName;
			edit(val);
			ContentAddition.AddSkillDef(val);
			ref Variant[] variants = ref family.variants;
			Variant val2 = new Variant
			{
				skillDef = val,
				unlockableDef = null
			};
			((Variant)(ref val2)).viewableNode = new Node(val.skillNameToken, false, (Node)null);
			ArrayUtils.ArrayAppend<Variant>(ref variants, ref val2);
			Log.Info(newName + ": agregada como variante nueva.");
		}
	}
	internal static class Tokens
	{
		public const string ChainName = "ARTIREWORK_CHAINBOLT_NAME";

		public const string ChainDesc = "ARTIREWORK_CHAINBOLT_DESC";

		public const string FireballName = "ARTIREWORK_FIREBALL_NAME";

		public const string FireballDesc = "ARTIREWORK_FIREBALL_DESC";

		public const string TectonicName = "ARTIREWORK_TECTONIC_NAME";

		public const string TectonicDesc = "ARTIREWORK_TECTONIC_DESC";

		public const string PillarName = "ARTIREWORK_PILLAR_NAME";

		public const string PillarDesc = "ARTIREWORK_PILLAR_DESC";

		public const string FlameDesc = "ARTIREWORK_FLAMETHROWER_DESC";

		public const string IonName = "ARTIREWORK_IONGLIDE_NAME";

		public const string IonDesc = "ARTIREWORK_IONGLIDE_DESC";

		public const string EmberKeyword = "KEYWORD_ARTIREWORK_EMBER";

		private static string P(float coef)
		{
			return $"{coef * 100f:0}%";
		}

		public static void Init()
		{
			Add("ARTIREWORK_CHAINBOLT_NAME", "Chain Bolt", "Rayo Encadenado");
			Add("ARTIREWORK_CHAINBOLT_DESC", $"Fire a plasma bolt that bursts for <style=cIsDamage>{P(Cfg.ChainDamage.Value)} damage</style>. Lightning then <style=cIsDamage>arcs to up to {Cfg.ChainArcs.Value} other enemies</style> within {Cfg.ChainRange.Value:0}m for {P(Cfg.ChainDamage.Value * Cfg.ChainArcDamageMult.Value)} damage each. <style=cIsUtility>Every {Cfg.ChainLevelsPerBounce.Value} levels: +1 bounce per arc and +{Cfg.ChainRangePerLevels.Value:0}m arc range.</style> No enemy is struck twice. Hold up to 4 charges.", $"Dispara un rayo de plasma que estalla por <style=cIsDamage>{P(Cfg.ChainDamage.Value)} de daño</style>. Después, relámpagos <style=cIsDamage>saltan hasta a {Cfg.ChainArcs.Value} enemigos distintos</style> en {Cfg.ChainRange.Value:0}m por {P(Cfg.ChainDamage.Value * Cfg.ChainArcDamageMult.Value)} de daño cada uno. <style=cIsUtility>Cada {Cfg.ChainLevelsPerBounce.Value} niveles: +1 rebote por rayo y +{Cfg.ChainRangePerLevels.Value:0}m de alcance de salto.</style> Ningún enemigo recibe dos rayos. Hasta 4 cargas.");
			Add("ARTIREWORK_FIREBALL_NAME", "Fireball", "Bola de Fuego");
			Add("ARTIREWORK_FIREBALL_DESC", $"<style=cIsDamage>Ignite</style>. Charge up a fireball that flies straight and explodes for <style=cIsDamage>{P(Cfg.FireballMinDamage.Value)}-{P(Cfg.FireballMaxDamage.Value)} damage</style>, leaving the area <style=cIsDamage>burning</style> for {Cfg.FirePatchDuration.Value:0}s.", $"<style=cIsDamage>Ignite</style>. Carga una bola de fuego que vuela recto y explota por <style=cIsDamage>{P(Cfg.FireballMinDamage.Value)}-{P(Cfg.FireballMaxDamage.Value)} de daño</style>, dejando la zona <style=cIsDamage>ardiendo</style> durante {Cfg.FirePatchDuration.Value:0}s.");
			Add("ARTIREWORK_TECTONIC_NAME", "Tectonic Blast", "Explosión Tectónica");
			Add("ARTIREWORK_TECTONIC_DESC", $"Fire a spread of {Cfg.TectonicShardCount.Value} shards that deal <style=cIsDamage>{Cfg.TectonicShardCount.Value}x{P(Cfg.TectonicShardDamage.Value)} damage</style> and <style=cIsUtility>Oil</style> enemies, pushing you back. <style=cIsUtility>Hold to charge</style>: up to {Cfg.TectonicMaxRangeMult.Value:0.#}x range, and a much stronger push if you are airborne.", $"Dispara un abanico de {Cfg.TectonicShardCount.Value} fragmentos que hacen <style=cIsDamage>{Cfg.TectonicShardCount.Value}x{P(Cfg.TectonicShardDamage.Value)} de daño</style> y aplican <style=cIsUtility>Oil</style>, empujándote hacia atrás. <style=cIsUtility>Mantén para cargar</style>: hasta {Cfg.TectonicMaxRangeMult.Value:0.#}x de alcance y un empuje mucho mayor si estás en el aire.");
			Add("ARTIREWORK_PILLAR_NAME", "Glacial Storm", "Tormenta Glacial");
			Add("ARTIREWORK_PILLAR_DESC", $"<style=cIsUtility>Freezing</style>. <style=cIsUtility>Charge</style> to summon a <style=cIsUtility>snowstorm</style> of {Cfg.SnowRadius.Value:0}-{Cfg.SnowRadiusMax.Value:0}m where you aim: a massive ice pillar erupts at its center for <style=cIsDamage>{P(Cfg.PillarBurstDamage.Value)}-{P(Cfg.PillarBurstDamageMax.Value)} damage</style>, ringed by ice pillars. For {Cfg.SnowDuration.Value:0}s the storm deals {P(Cfg.SnowTickDamage.Value)} damage per tick, <style=cIsUtility>slows</style> enemies after {Cfg.SnowSlowAfter.Value:0.#}s inside and <style=cIsUtility>freezes</style> them after {Cfg.SnowFreezeAfter.Value:0.#}s.", $"<style=cIsUtility>Congelante</style>. <style=cIsUtility>Carga</style> para invocar una <style=cIsUtility>tormenta de nieve</style> de {Cfg.SnowRadius.Value:0}-{Cfg.SnowRadiusMax.Value:0}m donde apuntas: en el centro emerge un pilar de hielo gigante que causa <style=cIsDamage>{P(Cfg.PillarBurstDamage.Value)}-{P(Cfg.PillarBurstDamageMax.Value)} de daño</style>, rodeado de pilares de hielo. Durante {Cfg.SnowDuration.Value:0}s la tormenta hace {P(Cfg.SnowTickDamage.Value)} de daño por tick, <style=cIsUtility>ralentiza</style> a los enemigos tras {Cfg.SnowSlowAfter.Value:0.#}s dentro y los <style=cIsUtility>congela</style> tras {Cfg.SnowFreezeAfter.Value:0.#}s.");
			string text = (Cfg.FlameAgile.Value ? "<style=cIsUtility>Agile</style>. " : "");
			string text2 = (Cfg.FlameAgile.Value ? "<style=cIsUtility>Ágil</style>. " : "");
			string text3 = ((Cfg.FlameAirThrust.Value > 0f) ? " While airborne, the flames <style=cIsUtility>push you back</style>; the push grows with attack speed." : "");
			string text4 = ((Cfg.FlameAirThrust.Value > 0f) ? " En el aire, las llamas <style=cIsUtility>te empujan hacia atrás</style>; el empuje crece con attack speed." : "");
			Add("ARTIREWORK_FLAMETHROWER_DESC", text + "<style=cIsDamage>Ignite</style>. Burn all enemies in front of you for <style=cIsDamage>" + P(Cfg.FlameTotalDamage.Value) + " damage</style> at long range, applying <style=cIsDamage>Ember</style>." + text3, text2 + "<style=cIsDamage>Ignite</style>. Quema a todos los enemigos frente a ti por <style=cIsDamage>" + P(Cfg.FlameTotalDamage.Value) + " de daño</style> a largo alcance, aplicando <style=cIsDamage>Ember</style>." + text4);
			Add("KEYWORD_ARTIREWORK_EMBER", $"<style=cKeywordName>Ember</style><style=cSub>Permanent, non-stacking burn that deals {P(Cfg.EmberTickDamage.Value / Cfg.EmberTickInterval.Value)} base damage per second. When the victim dies it explodes for <style=cIsDamage>{P(Cfg.EmberExplosionDamage.Value)} damage</style> in {Cfg.EmberExplosionRadius.Value:0}m, igniting nearby enemies.</style>", $"<style=cKeywordName>Ember</style><style=cSub>Quemadura permanente que no stackea y hace {P(Cfg.EmberTickDamage.Value / Cfg.EmberTickInterval.Value)} de daño base por segundo. Cuando la víctima muere, explota por <style=cIsDamage>{P(Cfg.EmberExplosionDamage.Value)} de daño</style> en {Cfg.EmberExplosionRadius.Value:0}m, prendiendo fuego a los enemigos cercanos.</style>");
			Add("ARTIREWORK_IONGLIDE_NAME", "Ion Glide", "Planeo Iónico");
			Add("ARTIREWORK_IONGLIDE_DESC", "<style=cIsDamage>Stunning</style>. Blast off <style=cIsUtility>toward where you aim</style> for <style=cIsDamage>" + P(Cfg.IonBlastDamage.Value) + " damage</style>, then <style=cIsUtility>glide</style>, steering with your aim. Lose your momentum and you fall, exploding on landing for another <style=cIsDamage>" + P(Cfg.IonBlastDamage.Value) + " damage</style>.", "<style=cIsDamage>Aturde</style>. Sal disparada <style=cIsUtility>hacia donde apuntas</style> causando <style=cIsDamage>" + P(Cfg.IonBlastDamage.Value) + " de daño</style> y luego <style=cIsUtility>planea</style> controlando la dirección con la mira. Si pierdes el impulso caes y explotas al aterrizar por otro <style=cIsDamage>" + P(Cfg.IonBlastDamage.Value) + " de daño</style>.");
		}

		private static void Add(string token, string en, string es)
		{
			LanguageAPI.Add(token, en);
			LanguageAPI.Add(token, es, "es-419");
			LanguageAPI.Add(token, es, "es-ES");
		}
	}
	internal static class Visuals
	{
		public static void ScaleHierarchy(GameObject root, float scale)
		{
			//IL_001d: 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)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)root) && !Mathf.Approximately(scale, 1f))
			{
				Transform transform = root.transform;
				transform.localScale *= scale;
				ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					MainModule main = componentsInChildren[i].main;
					((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
				}
				TrailRenderer[] componentsInChildren2 = root.GetComponentsInChildren<TrailRenderer>(true);
				foreach (TrailRenderer obj in componentsInChildren2)
				{
					obj.widthMultiplier *= scale;
				}
				Light[] componentsInChildren3 = root.GetComponentsInChildren<Light>(true);
				foreach (Light obj2 in componentsInChildren3)
				{
					obj2.range *= scale;
				}
			}
		}

		public static void StripLogic(GameObject go)
		{
			MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[i]))
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
			}
			Animator[] componentsInChildren2 = go.GetComponentsInChildren<Animator>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren2[j]))
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren2[j]);
				}
			}
			Collider[] componentsInChildren3 = go.GetComponentsInChildren<Collider>(true);
			for (int k = 0; k < componentsInChildren3.Length; k++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren3[k]))
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren3[k]);
				}
			}
			Rigidbody[] componentsInChildren4 = go.GetComponentsInChildren<Rigidbody>(true);
			for (int l = 0; l < componentsInChildren4.Length; l++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren4[l]))
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren4[l]);
				}
			}
		}

		public static GameObject AttachPrefabVisual(Transform parent, float scale, params string[] keys)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < keys.Length; i++)
			{
				if (!Assets.Exists(keys[i]))
				{
					continue;
				}
				GameObject val = Assets.Load<GameObject>(keys[i]);
				if (Object.op_Implicit((Object)(object)val))
				{
					GameObject val2 = Object.Instantiate<GameObject>(val, parent);
					((Object)val2).name = "Visual_" + ((Object)val).name;
					StripLogic(val2);
					val2.transform.localPosition = Vector3.zero;
					val2.transform.localRotation = Quaternion.identity;
					val2.transform.localScale = Vector3.one;
					ScaleHierarchy(val2, scale);
					ParticleSystem[] componentsInChildren = val2.GetComponentsInChildren<ParticleSystem>(true);
					for (int j = 0; j < componentsInChildren.Length; j++)
					{
						MainModule main = componentsInChildren[j].main;
						((MainModule)(ref main)).loop = true;
						((MainModule)(ref main)).playOnAwake = true;
					}
					val2.SetActive(true);
					Log.Info($"Visual: usando '{((Object)val).name}' (escala {scale:0.##}).");
					return val2;
				}
			}
			Log.Warn("Visual: ninguna de estas llaves existe: " + string.Join(" | ", keys));
			return null;
		}
	}
	internal static class AuraSphere
	{
		private static Material material;

		private static bool searched;

		public static Material Material
		{
			get
			{
				if (searched)
				{
					return material;
				}
				searched = true;
				material = FindMaterial();
				return material;
			}
		}

		private static Material FindMaterial()
		{
			//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)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0053: Expected O, but got Unknown
			Material val = FirstMeshMaterial(Assets.Exists("RoR2/Base/NearbyDamageBonus/NearbyDamageBonusIndicator.prefab") ? Assets.Load<GameObject>("RoR2/Base/NearbyDamageBonus/NearbyDamageBonusIndicator.prefab") : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				Material val2 = new Material(val);
				Fx.TintMaterial(val2, new Color(0.55f, 0.85f, 1f));
				Log.Info("Esfera de escarcha: usando el material de NearbyDamageBonusIndicator teñido.");
				return val2;
			}
			val = FirstMeshMaterial(Assets.Exists("RoR2/Base/Icicle/IcicleAura.prefab") ? Assets.Load<GameObject>("RoR2/Base/Icicle/IcicleAura.prefab") : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				Log.Info("Esfera de escarcha: usando el material de IcicleAura.");
				return val;
			}
			Log.Warn("Esfera de escarcha: sin material; la esfera no se dibujará.");
			return null;
		}

		private static Material FirstMeshMaterial(GameObject prefab)
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[i]) && Object.op_Implicit((Object)(object)((Renderer)componentsInChildren[i]).sharedMaterial))
				{
					return ((Renderer)componentsInChildren[i]).sharedMaterial;
				}
			}
			return null;
		}

		public static GameObject Create(Transform parent, string name)
		{
			//IL_0035: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)obj).name = name;
			Collider component = obj.GetComponent<Collider>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			obj.transform.SetParent(parent, false);
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = Vector3.one;
			MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)component2).receiveShadows = false;
				if (Object.op_Implicit((Object)(object)Material))
				{
					((Renderer)component2).sharedMaterial = Material;
					return obj;
				}
				((Renderer)component2).enabled = false;
			}
			return obj;
		}
	}
	internal static class Fx
	{
		private static readonly string[] ColorProps = new string[5] { "_TintColor", "_Color", "_EmissionColor", "_MainColor", "_BaseColor" };

		public static void TintMaterial(M