Decompiled source of Timpanist v0.3.2

BepInEx/plugins/Rodanius-Timpanist/Rodanius.Timpanist.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using EntityStates;
using HG;
using HG.BlendableTypes;
using KinematicCharacterController;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.CharacterAI;
using RoR2.ContentManagement;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Timpanist;

public static class Combat
{
	private static readonly Collider[] overlaps = (Collider[])(object)new Collider[512];

	public static Ray Aim(CharacterBody body)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//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)
		//IL_0033: 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_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: 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_0095: 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_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		Ray val = default(Ray);
		((Ray)(ref val))..ctor(body.inputBank.aimOrigin, body.inputBank.aimDirection);
		float num = default(float);
		val = CameraRigController.ModifyAimRayIfApplicable(val, ((Component)body).gameObject, ref num);
		Vector3 point = ((Ray)(ref val)).GetPoint(1000f);
		GameObject gameObject = ((Component)body).gameObject;
		Ray val2 = val;
		LayerIndex val3 = LayerIndex.world;
		int num2 = LayerMask.op_Implicit(((LayerIndex)(ref val3)).mask);
		val3 = LayerIndex.entityPrecise;
		RaycastHit val4 = default(RaycastHit);
		if (Util.CharacterRaycast(gameObject, val2, ref val4, 1000f, LayerMask.op_Implicit(num2 | LayerMask.op_Implicit(((LayerIndex)(ref val3)).mask)), (QueryTriggerInteraction)1))
		{
			point = ((RaycastHit)(ref val4)).point;
		}
		Vector3 aimOrigin = body.aimOrigin;
		Vector3 val5 = point - body.aimOrigin;
		return new Ray(aimOrigin, ((Vector3)(ref val5)).normalized);
	}

	public static DamageTypeCombo Type(DamageSource source, bool stun = false)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		return new DamageTypeCombo(DamageTypeCombo.op_Implicit((DamageType)(stun ? 32 : 0)), (DamageTypeExtended)0, source);
	}

	public unsafe static bool Hit(CharacterBody body, HealthComponent health, Vector3 point, float coefficient, float proc, DamageSource source, bool crit, bool stun, Vector3 force, ProcChainMask mask, GameObject inflictor = null, HurtBox hurtBox = null)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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_0051: 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_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Invalid comparison between Unknown and I4
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Invalid comparison between Unknown and I4
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)health) || (Object)(object)health == (Object)(object)body.healthComponent || !health.alive)
		{
			return false;
		}
		DamageInfo val = new DamageInfo
		{
			attacker = ((Component)body).gameObject,
			inflictor = (Object.op_Implicit((Object)(object)inflictor) ? inflictor : ((Component)body).gameObject),
			damage = body.damage * coefficient,
			crit = crit,
			position = point,
			force = force,
			procCoefficient = proc,
			procChainMask = mask,
			damageType = Type(source, stun),
			damageColorIndex = (DamageColorIndex)0
		};
		if (Object.op_Implicit((Object)(object)hurtBox))
		{
			val.inflictedHurtbox = hurtBox;
			if (hurtBox.AttackHitRejectsHurtbox(new HurtBoxAttackHitProcessorArgs(val, body.aimOrigin)))
			{
				return false;
			}
			val.ModifyDamageInfo(hurtBox.damageModifier);
		}
		health.TakeDamage(val);
		GlobalEventManager.instance.OnHitEnemy(val, ((Component)health).gameObject);
		GlobalEventManager.instance.OnHitAll(val, ((Component)health).gameObject);
		TimpanistController component = ((Component)body).GetComponent<TimpanistController>();
		if (Object.op_Implicit((Object)(object)component))
		{
			component.Trace("direct-hit", ((object)(*(DamageSource*)(&source))/*cast due to .constrained prefix*/).ToString(), ((int)source == 1) ? body.skillLocator.primary : (((int)source == 4) ? body.skillLocator.utility : body.skillLocator.secondary), 0f, coefficient, proc, crit, ((Object)health).GetInstanceID());
		}
		return true;
	}

	public unsafe static void Area(CharacterBody body, Vector3 origin, Vector3 aim, float radius, float halfAngle, float coefficient, float proc, DamageSource source, bool crit, bool stun, HashSet<HealthComponent> seen, float knockback = 10f)
	{
		//IL_0000: 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)
		//IL_000c: 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_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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: 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)
		float num = radius;
		Collider[] array = overlaps;
		LayerIndex val = LayerIndex.entityPrecise;
		int num2 = Physics.OverlapSphereNonAlloc(origin, num, array, LayerMask.op_Implicit(((LayerIndex)(ref val)).mask), (QueryTriggerInteraction)2);
		int count = seen.Count;
		Collider[] array2 = overlaps;
		if (num2 == overlaps.Length)
		{
			float num3 = radius;
			val = LayerIndex.entityPrecise;
			array2 = Physics.OverlapSphere(origin, num3, LayerMask.op_Implicit(((LayerIndex)(ref val)).mask), (QueryTriggerInteraction)2);
			num2 = array2.Length;
		}
		for (int i = 0; i < num2; i++)
		{
			HurtBox component = ((Component)array2[i]).GetComponent<HurtBox>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.healthComponent))
			{
				continue;
			}
			HealthComponent healthComponent = component.healthComponent;
			if (seen.Contains(healthComponent) || (Object)(object)healthComponent == (Object)(object)body.healthComponent || !FriendlyFireManager.ShouldSplashHitProceed(healthComponent, body.teamComponent.teamIndex))
			{
				continue;
			}
			Vector3 val2 = array2[i].ClosestPoint(origin);
			Vector3 val3 = val2 - origin;
			if (halfAngle < 180f && Vector3.Angle(aim, val3) > halfAngle)
			{
				continue;
			}
			val = LayerIndex.world;
			if (!Physics.Linecast(origin, val2, LayerMask.op_Implicit(((LayerIndex)(ref val)).mask), (QueryTriggerInteraction)1))
			{
				Vector3 force = (stun ? (((Vector3)(ref val3)).normalized * 800f + Vector3.up * 250f) : (((Vector3)(ref val3)).normalized * knockback));
				if (Hit(body, healthComponent, val2, coefficient, proc, source, crit, stun, force, default(ProcChainMask), null, component))
				{
					seen.Add(healthComponent);
				}
			}
		}
		if (Plugin.Diagnostics.Value && proc >= 1f)
		{
			Plugin.Log("strike-query source=" + ((object)(*(DamageSource*)(&source))/*cast due to .constrained prefix*/).ToString() + " candidates=" + num2 + " selected=" + (seen.Count - count) + " radius=" + radius + " angle=" + halfAngle);
		}
	}

	public static void Sweep(CharacterBody body, Vector3 from, Vector3 to, float radius, float coefficient, float proc, bool crit, HashSet<HealthComponent> seen, HashSet<HealthComponent> afterbeatHits)
	{
		//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_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)
		//IL_0028: 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_002f: 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_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: 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_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: 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_0076: 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_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: 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_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: 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_01db: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = to - from;
		int num = Mathf.Max(1, Mathf.CeilToInt(((Vector3)(ref val)).magnitude / 0.4f));
		for (int i = 0; i <= num; i++)
		{
			Vector3 val2 = Vector3.Lerp(from, to, (float)i / (float)num);
			Vector3 val3 = val2 - Vector3.up * 0.45f;
			Vector3 val4 = val2 + Vector3.up * 0.45f;
			Collider[] array = overlaps;
			LayerIndex val5 = LayerIndex.entityPrecise;
			int num2 = Physics.OverlapCapsuleNonAlloc(val3, val4, radius, array, LayerMask.op_Implicit(((LayerIndex)(ref val5)).mask), (QueryTriggerInteraction)2);
			Collider[] array2 = overlaps;
			if (num2 == overlaps.Length)
			{
				val5 = LayerIndex.entityPrecise;
				array2 = Physics.OverlapCapsule(val3, val4, radius, LayerMask.op_Implicit(((LayerIndex)(ref val5)).mask), (QueryTriggerInteraction)2);
				num2 = array2.Length;
			}
			for (int j = 0; j < num2; j++)
			{
				HurtBox component = ((Component)array2[j]).GetComponent<HurtBox>();
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.healthComponent) || seen.Contains(component.healthComponent) || (Object)(object)component.healthComponent == (Object)(object)body.healthComponent || !FriendlyFireManager.ShouldSplashHitProceed(component.healthComponent, body.teamComponent.teamIndex))
				{
					continue;
				}
				Vector3 val6 = array2[j].ClosestPoint(val2);
				val5 = LayerIndex.world;
				if (!Physics.Linecast(val2, val6, LayerMask.op_Implicit(((LayerIndex)(ref val5)).mask), (QueryTriggerInteraction)1))
				{
					Vector3 corePosition = body.corePosition;
					val5 = LayerIndex.world;
					if (!Physics.Linecast(corePosition, val6, LayerMask.op_Implicit(((LayerIndex)(ref val5)).mask), (QueryTriggerInteraction)1) && Hit(body, component.healthComponent, val6, coefficient, proc, (DamageSource)4, crit, stun: false, ((Vector3)(ref val)).normalized * 150f, default(ProcChainMask), null, component))
					{
						seen.Add(component.healthComponent);
						((Component)body).GetComponent<TimpanistController>().QueueAfterbeat(component.healthComponent, val6, crit, afterbeatHits);
					}
				}
			}
		}
	}

	public static void Strike(CharacterBody body, Tuning mode, bool right)
	{
		//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_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		Ray val = Aim(body);
		HashSet<HealthComponent> hashSet = new HashSet<HealthComponent>();
		Area(body, ((Ray)(ref val)).origin, ((Ray)(ref val)).direction, 22f, 38f, 4f, 1f, (DamageSource)1, body.RollCrit(), stun: false, hashSet, 100f);
		int num = 0;
		foreach (HealthComponent item in hashSet)
		{
			if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.body) && num++ < 12)
			{
				ImpactVisual.Emit(body, item.body.corePosition, ((Ray)(ref val)).direction, 0.8f, ImpactKind.HeavyContact);
			}
		}
	}

	public static void Roll(CharacterBody body)
	{
		//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_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		Ray val = Aim(body);
		HashSet<HealthComponent> hashSet = new HashSet<HealthComponent>();
		Area(body, ((Ray)(ref val)).origin, ((Ray)(ref val)).direction, 14f, 50f, CavalryRules.RollDamage(body.attackSpeed), 0.12f, (DamageSource)2, body.RollCrit(), stun: false, hashSet, 130f);
		foreach (HealthComponent item in hashSet)
		{
			if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.body))
			{
				item.body.AddTimedBuff(Content.MidFull, 0.35f);
			}
		}
	}
}
public static class Content
{
	public static DrumSkillDef Left;

	public static RollSkillDef Right;

	public static SkillDef Charge;

	public static SkillDef Retune;

	public static BuffDef Poise;

	public static BuffDef LowFull;

	public static BuffDef LowHalf;

	public static BuffDef MidFull;

	public static BuffDef MidHalf;

	public static BuffDef LowResonant;

	public static BuffDef MidResonant;

	private static void Field(object target, string name, object value)
	{
		FieldInfo? field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			throw new MissingFieldException(target.GetType().FullName, name);
		}
		field.SetValue(target, value);
	}

	public static void Build(ContentPack pack)
	{
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0310: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_035f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0361: Unknown result type (might be due to invalid IL or missing references)
		//IL_0455: Unknown result type (might be due to invalid IL or missing references)
		//IL_045a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0463: Unknown result type (might be due to invalid IL or missing references)
		//IL_0468: Unknown result type (might be due to invalid IL or missing references)
		//IL_0489: Unknown result type (might be due to invalid IL or missing references)
		//IL_048e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0493: Unknown result type (might be due to invalid IL or missing references)
		//IL_049d: Unknown result type (might be due to invalid IL or missing references)
		//IL_049f: Unknown result type (might be due to invalid IL or missing references)
		//IL_054b: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_064f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0654: Unknown result type (might be due to invalid IL or missing references)
		//IL_065e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0682: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0712: Unknown result type (might be due to invalid IL or missing references)
		//IL_0736: Unknown result type (might be due to invalid IL or missing references)
		//IL_074a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0751: Expected O, but got Unknown
		//IL_07f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f7: Unknown result type (might be due to invalid IL or missing references)
		SurvivorIdentity.RegisterLanguage();
		LanguageAPI.Add("TIMPANIST_NAME", "The Timpanist");
		LanguageAPI.Add("TIMPANIST_SUBTITLE", "Cavalry Percussionist");
		LanguageAPI.Add("TIMPANIST_DESCRIPTION", "A mounted percussionist who breaks enemy lines with heavy sound waves. Strike hard, control crowds with a roll, and charge through them for a delayed Afterbeat.");
		LanguageAPI.Add("TIMPANIST_OUTRO", "...and so they left, the last note still ringing.");
		LanguageAPI.Add("TIMPANIST_FAILURE", "...and so they vanished, an unfinished cadence.");
		LanguageAPI.Add("TIMPANIST_DEFAULT", "Cavalry Percussionist");
		GameObject obj = LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterBodies/CommandoBody");
		if (!Object.op_Implicit((Object)(object)obj))
		{
			throw new InvalidOperationException("CommandoBody runtime reference unavailable");
		}
		GameObject val = PrefabAPI.InstantiateClone(obj, "RodaniusTimpanistBody", true);
		CharacterBody component = val.GetComponent<CharacterBody>();
		component.baseNameToken = "TIMPANIST_NAME";
		component.subtitleNameToken = "TIMPANIST_SUBTITLE";
		component.baseMaxHealth = 130f;
		component.levelMaxHealth = 39f;
		component.baseRegen = 1f;
		component.levelRegen = 0.2f;
		component.baseDamage = 12f;
		component.levelDamage = 2.4f;
		component.baseCrit = 1f;
		component.levelCrit = 0f;
		component.baseArmor = 0f;
		component.levelArmor = 0f;
		component.baseMoveSpeed = 8.5f;
		component.levelMoveSpeed = 0f;
		component.baseAcceleration = 110f;
		component.baseJumpPower = 15f;
		component.levelJumpPower = 0f;
		component.baseJumpCount = 1;
		component.sprintingSpeedMultiplier = 1.6f;
		component.baseAttackSpeed = 1f;
		component.levelAttackSpeed = 0f;
		component.autoCalculateLevelStats = false;
		component.bodyColor = Graybox.Green;
		val.GetComponent<CharacterMotor>().mass = 100f;
		Rigidbody component2 = val.GetComponent<Rigidbody>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			component2.mass = 100f;
		}
		KinematicCharacterMotor component3 = val.GetComponent<KinematicCharacterMotor>();
		component3.Capsule = val.GetComponent<CapsuleCollider>();
		component3.SetCapsuleDimensions(0.48f, 2.2f, 0f);
		val.GetComponent<ModelLocator>().modelTransform.parent.localPosition = new Vector3(0f, -1.1f, 0f);
		component.aimOriginTransform = Anchor(val.transform, "TimpanistAim", new Vector3(0f, 0.65f, 0f));
		component.overrideCoreTransform = Anchor(val.transform, "TimpanistCore", Vector3.zero);
		List<EntityStateMachine> list = new List<EntityStateMachine>(val.GetComponents<EntityStateMachine>());
		EntityStateMachine val2 = null;
		EntityStateMachine bodyMachine = null;
		foreach (EntityStateMachine item in list)
		{
			if (item.customName == "Body")
			{
				item.mainStateType = new SerializableEntityStateType(typeof(TimpanistMain));
				bodyMachine = item;
			}
			if (item.customName == "Weapon")
			{
				val2 = item;
			}
		}
		if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)bodyMachine))
		{
			throw new InvalidOperationException("Template state-machine contract changed");
		}
		val2.initialStateType = (val2.mainStateType = new SerializableEntityStateType(typeof(Idle)));
		string[] array = new string[1] { "Cavalry" };
		foreach (string customName in array)
		{
			EntityStateMachine val3 = val.AddComponent<EntityStateMachine>();
			val3.customName = customName;
			val3.initialStateType = (val3.mainStateType = new SerializableEntityStateType(typeof(Idle)));
			list.Add(val3);
		}
		Field(val.GetComponent<NetworkStateMachine>(), "stateMachines", list.ToArray());
		SetStateOnHurt component4 = val.GetComponent<SetStateOnHurt>();
		if (Object.op_Implicit((Object)(object)component4))
		{
			component4.idleStateMachine = list.FindAll((EntityStateMachine x) => (Object)(object)x != (Object)(object)bodyMachine && x.customName != "Tuning").ToArray();
		}
		CharacterDeathBehavior component5 = val.GetComponent<CharacterDeathBehavior>();
		if (Object.op_Implicit((Object)(object)component5))
		{
			component5.idleStateMachine = list.FindAll((EntityStateMachine x) => (Object)(object)x != (Object)(object)bodyMachine).ToArray();
		}
		Transform modelTransform = val.GetComponent<ModelLocator>().modelTransform;
		Material template = (PressureVisual.Template = ((Component)modelTransform).GetComponent<CharacterModel>().baseRendererInfos[0].defaultMaterial);
		ImpactVisual.Build(pack);
		Graybox.BuildModel(val, modelTransform, template);
		val.AddComponent<TimpanistController>();
		CameraTargetParams component6 = val.GetComponent<CameraTargetParams>();
		component6.cameraParams = Object.Instantiate<CharacterCameraParams>(component6.cameraParams);
		CharacterCameraParamsData data = component6.cameraParams.data;
		data.pivotVerticalOffset = BlendableFloat.op_Implicit(1.65f);
		data.idealLocalCameraPos = BlendableVector3.op_Implicit(new Vector3(Plugin.CameraOffset.Value, 0f, 0f - Plugin.CameraDistance.Value));
		component6.cameraParams.data = data;
		SkillLocator component7 = val.GetComponent<SkillLocator>();
		GenericSkill[] components = val.GetComponents<GenericSkill>();
		for (int i = 0; i < components.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)components[i]);
		}
		Left = Make<DrumSkillDef>("LEFT", "Hammerstroke", "Strike a broad sound wave for <style=cIsDamage>400% damage</style>. Hold to repeat.", "Weapon", typeof(StrokeState), 0f, 0, end: false);
		Right = Make<RollSkillDef>("RIGHT", "Pressure Roll", "Hold for up to <style=cIsUtility>2s</style>: deal <style=cIsDamage>120% damage per second</style>, slow enemies by <style=cIsUtility>30%</style>, and push them back.", "Weapon", typeof(RollState), 6f, 1, end: true);
		((SkillDef)Right).mustKeyPress = true;
		((SkillDef)Right).autoHandleLuminousShot = true;
		((SkillDef)Right).interruptPriority = (InterruptPriority)2;
		Charge = Make<SkillDef>("CHARGE", "Thunderous Charge", "Charge forward for <style=cIsDamage>350% damage</style>. Hits erupt in an <style=cIsDamage>180% Afterbeat</style>. Primary ends the charge early.", "Cavalry", typeof(ChargeState), 7f, 1, end: false);
		Charge.mustKeyPress = true;
		Retune = Make<SkillDef>("RETUNE", "Grand Accent", "Strike both drums for a staggering <style=cIsDamage>900% damage</style> wave.", "Weapon", typeof(GrandAccentState), 10f, 1, end: false);
		Retune.mustKeyPress = true;
		Retune.interruptPriority = (InterruptPriority)2;
		component7.primary = Slot(val, (SkillDef)(object)Left, pack);
		component7.secondary = Slot(val, (SkillDef)(object)Right, pack);
		component7.utility = Slot(val, Charge, pack);
		component7.special = Slot(val, Retune, pack);
		Poise = ScriptableObject.CreateInstance<BuffDef>();
		((Object)Poise).name = "RodaniusMountedPoise";
		Poise.canStack = false;
		Poise.isDebuff = false;
		Poise.buffColor = Graybox.Green;
		Poise.iconSprite = Graybox.Icon(Graybox.Green);
		LowFull = Buff("TimpanistLowFull", debuff: false, new Color(0.35f, 0.95f, 0.85f));
		LowResonant = Buff("TimpanistLowResonant", debuff: false, new Color(0.3f, 1f, 1f));
		MidResonant = Buff("TimpanistMidResonant", debuff: true, new Color(1f, 0.9f, 0.4f));
		LowHalf = Buff("TimpanistLowHalf", debuff: false, new Color(0.35f, 0.7f, 0.65f));
		MidFull = Buff("TimpanistMidFull", debuff: true, new Color(1f, 0.75f, 0.25f));
		MidHalf = Buff("TimpanistMidHalf", debuff: true, new Color(0.8f, 0.6f, 0.25f));
		GameObject val4 = new GameObject("RodaniusTimpanistDisplay");
		val4.SetActive(false);
		if (!Presentation.TryBuild(val4.transform, template))
		{
			Graybox.BuildVisual(val4.transform, template);
		}
		Object.DontDestroyOnLoad((Object)(object)val4);
		GameObject val5 = PrefabAPI.InstantiateClone(val4, "RodaniusTimpanistDisplayPrefab", false);
		val5.SetActive(true);
		Object.Destroy((Object)(object)val4);
		SurvivorDef val6 = ScriptableObject.CreateInstance<SurvivorDef>();
		((Object)val6).name = "RodaniusTimpanist";
		val6.bodyPrefab = val;
		val6.displayPrefab = val5;
		val6.displayNameToken = "TIMPANIST_NAME";
		val6.descriptionToken = "TIMPANIST_DESCRIPTION";
		val6.outroFlavorToken = "TIMPANIST_OUTRO";
		val6.mainEndingEscapeFailureFlavorToken = "TIMPANIST_FAILURE";
		val6.primaryColor = Graybox.Green;
		val6.desiredSortPosition = 100f;
		val6.hidden = false;
		component.portraitIcon = (Texture)(object)SurvivorIdentity.LoadPortrait();
		GameObject val7 = PrefabAPI.InstantiateClone(LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/CommandoMonsterMaster"), "RodaniusTimpanistMonsterMaster", true);
		val7.GetComponent<CharacterMaster>().bodyPrefab = val;
		AISkillDriver[] components2 = val7.GetComponents<AISkillDriver>();
		for (int i = 0; i < components2.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)components2[i]);
		}
		Driver(val7, "Crowd control", (SkillSlot)1, 0f, 10f);
		Driver(val7, "Hammerstroke", (SkillSlot)0, 0f, 22f);
		Driver(val7, "Charge", (SkillSlot)2, 22f, 40f);
		Driver(val7, "Approach", (SkillSlot)(-1), 22f, float.PositiveInfinity);
		pack.bodyPrefabs.Add((GameObject[])(object)new GameObject[1] { val });
		pack.masterPrefabs.Add((GameObject[])(object)new GameObject[1] { val7 });
		pack.survivorDefs.Add((SurvivorDef[])(object)new SurvivorDef[1] { val6 });
		pack.buffDefs.Add((BuffDef[])(object)new BuffDef[7] { Poise, LowFull, LowHalf, MidFull, MidHalf, LowResonant, MidResonant });
		pack.skillDefs.Add((SkillDef[])(object)new SkillDef[4] { Left, Right, Charge, Retune });
		pack.entityStateTypes.Add(new Type[5]
		{
			typeof(TimpanistMain),
			typeof(StrokeState),
			typeof(RollState),
			typeof(ChargeState),
			typeof(GrandAccentState)
		});
		Plugin.Log("Registered Timpanist content; runtime acceptance NOT yet established.");
	}

	private static T Make<T>(string id, string title, string description, string machine, Type state, float recharge, int consume, bool end) where T : SkillDef
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		T val = ScriptableObject.CreateInstance<T>();
		((Object)(object)val).name = "RodaniusTimpanist" + id;
		((SkillDef)val).skillName = "TIMPANIST_" + id;
		((SkillDef)val).skillNameToken = ((SkillDef)val).skillName + "_NAME";
		((SkillDef)val).skillDescriptionToken = ((SkillDef)val).skillName + "_DESCRIPTION";
		LanguageAPI.Add(((SkillDef)val).skillNameToken, title);
		LanguageAPI.Add(((SkillDef)val).skillDescriptionToken, description);
		((SkillDef)val).activationStateMachineName = machine;
		((SkillDef)val).activationState = new SerializableEntityStateType(state);
		((SkillDef)val).baseMaxStock = 1;
		((SkillDef)val).baseRechargeInterval = recharge;
		((SkillDef)val).rechargeStock = 1;
		((SkillDef)val).requiredStock = consume;
		((SkillDef)val).stockToConsume = consume;
		((SkillDef)val).fullRestockOnAssign = true;
		((SkillDef)val).resetCooldownTimerOnUse = false;
		((SkillDef)val).beginSkillCooldownOnSkillEnd = end;
		((SkillDef)val).isCombatSkill = true;
		((SkillDef)val).cancelSprintingOnActivation = false;
		((SkillDef)val).canceledFromSprinting = false;
		((SkillDef)val).interruptPriority = (InterruptPriority)1;
		((SkillDef)val).icon = SkillIcons.Load(id);
		return val;
	}

	private static GenericSkill Slot(GameObject body, SkillDef def, ContentPack pack)
	{
		//IL_003a: 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_005c: Expected O, but got Unknown
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		GenericSkill val = body.AddComponent<GenericSkill>();
		val.skillName = def.skillName;
		SkillFamily val2 = ScriptableObject.CreateInstance<SkillFamily>();
		((Object)val2).name = def.skillName + "Family";
		Variant[] array = new Variant[1];
		Variant val3 = new Variant
		{
			skillDef = def
		};
		((Variant)(ref val3)).viewableNode = new Node(def.skillNameToken, false, (Node)null);
		array[0] = val3;
		val2.variants = (Variant[])(object)array;
		Field(val, "_skillFamily", val2);
		pack.skillFamilies.Add((SkillFamily[])(object)new SkillFamily[1] { val2 });
		return val;
	}

	private static void Driver(GameObject master, string name, SkillSlot slot, float min, float max)
	{
		//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_0017: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		AISkillDriver obj = master.AddComponent<AISkillDriver>();
		obj.customName = name;
		obj.skillSlot = slot;
		obj.requireSkillReady = (int)slot != -1;
		obj.minDistance = min;
		obj.maxDistance = max;
		obj.selectionRequiresTargetLoS = true;
		obj.activationRequiresTargetLoS = true;
		obj.moveTargetType = (TargetType)0;
		obj.movementType = (MovementType)1;
		obj.aimType = (AimType)2;
		obj.shouldSprint = true;
		obj.moveInputScale = 1f;
		obj.driverUpdateTimerOverride = 0.2f;
	}

	public static Transform Anchor(Transform parent, string name, Vector3 position)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = new GameObject(name).transform;
		transform.SetParent(parent, false);
		transform.localPosition = position;
		return transform;
	}

	private static BuffDef Buff(string name, bool debuff, Color color)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: 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)
		BuffDef obj = ScriptableObject.CreateInstance<BuffDef>();
		((Object)obj).name = name;
		obj.isDebuff = debuff;
		obj.canStack = false;
		obj.buffColor = color;
		obj.iconSprite = Graybox.Icon(color);
		return obj;
	}
}
public sealed class TimpanistController : MonoBehaviour
{
	private sealed class PendingBeat
	{
		public HealthComponent target;

		public Vector3 point;

		public float at;

		public bool crit;

		public HashSet<HealthComponent> hit;
	}

	public CharacterBody Body;

	public EntityStateMachine Weapon;

	public EntityStateMachine Cavalry;

	public EntityStateMachine BodyMachine;

	public Tuning LeftMode = Tuning.Mid;

	public Tuning RightMode = Tuning.Mid;

	public byte VisualMask;

	public float LeftFlash = -100f;

	public float RightFlash = -100f;

	public float TuneFlash = -100f;

	public float StrokeSpeed = 1f;

	public float ImpactSoundAt = -100f;

	public float RollClock;

	public float NextEffectTick;

	public float ChargeFlash = -100f;

	public float GrandFlash = -100f;

	public bool LastTuneRight;

	public bool NextRight;

	public bool PrimaryPressed;

	public int Cast;

	public string LastCancellation = "";

	private bool oldPrimary;

	private bool focus = true;

	private float chargeUntil;

	private readonly List<PendingBeat> pending = new List<PendingBeat>();

	public bool VisualRolling => VisualMask != 0;

	private void Awake()
	{
		Body = ((Component)this).GetComponent<CharacterBody>();
		EntityStateMachine[] components = ((Component)this).GetComponents<EntityStateMachine>();
		foreach (EntityStateMachine val in components)
		{
			if (val.customName == "Weapon")
			{
				Weapon = val;
			}
			if (val.customName == "Cavalry")
			{
				Cavalry = val;
			}
			if (val.customName == "Body")
			{
				BodyMachine = val;
			}
		}
	}

	private void Start()
	{
		CharacterBody body = Body;
		body.OnBodyDeath = (Action<CharacterBody>)Delegate.Combine(body.OnBodyDeath, new Action<CharacterBody>(Died));
		if (Plugin.Diagnostics.Value)
		{
			((Component)this).gameObject.AddComponent<DevelopmentHarness>();
		}
	}

	public Tuning Pitch(bool right)
	{
		if (!right)
		{
			return LeftMode;
		}
		return RightMode;
	}

	private void Died(CharacterBody b)
	{
		PresentationRagdoll.Release(b);
		pending.Clear();
		CancelRoll("death");
		CancelCharge();
	}

	public int NextCast()
	{
		return ++Cast;
	}

	public bool InputAllowed()
	{
		if (!Object.op_Implicit((Object)(object)Body) || Body.allSkillsDisabled || !Object.op_Implicit((Object)(object)Body.healthComponent) || !Body.healthComponent.alive || !Object.op_Implicit((Object)(object)BodyMachine) || !(BodyMachine.state is TimpanistMain))
		{
			return false;
		}
		if (Body.isPlayerControlled)
		{
			foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList)
			{
				if ((Object)(object)readOnlyLocalUsers.cachedBody == (Object)(object)Body)
				{
					return focus && !readOnlyLocalUsers.isUIFocused;
				}
			}
		}
		return true;
	}

	private void OnApplicationFocus(bool value)
	{
		focus = value;
		if (!value && Object.op_Implicit((Object)(object)Body) && Body.hasEffectiveAuthority)
		{
			CancelRoll("application focus");
			CancelCharge();
		}
	}

	private void Update()
	{
		if (Object.op_Implicit((Object)(object)Body) && Body.hasEffectiveAuthority && Object.op_Implicit((Object)(object)Body.inputBank))
		{
			bool down = Body.inputBank.skill1.down;
			PrimaryPressed |= down && !oldPrimary;
			oldPrimary = down;
			if (!InputAllowed())
			{
				PrimaryPressed = false;
			}
		}
	}

	private void FixedUpdate()
	{
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)Body) || !Object.op_Implicit((Object)(object)Body.skillLocator))
		{
			return;
		}
		if (NetworkServer.active && chargeUntil > 0f && Time.fixedTime >= chargeUntil)
		{
			EndChargePoise();
		}
		if (!InputAllowed())
		{
			CancelRoll("body interruption");
			CancelCharge();
		}
		if ((Object)(object)Body.skillLocator.utility.skillDef != (Object)(object)Content.Charge)
		{
			CancelCharge();
		}
		if (!NetworkServer.active)
		{
			return;
		}
		if (!Body.healthComponent.alive)
		{
			pending.Clear();
			return;
		}
		for (int num = pending.Count - 1; num >= 0; num--)
		{
			PendingBeat pendingBeat = pending[num];
			if (!(Time.fixedTime < pendingBeat.at))
			{
				pending.RemoveAt(num);
				Vector3 origin = ((Object.op_Implicit((Object)(object)pendingBeat.target) && Object.op_Implicit((Object)(object)pendingBeat.target.body)) ? pendingBeat.target.body.corePosition : pendingBeat.point);
				Combat.Area(Body, origin, Vector3.forward, 5f, 180f, 1.8f, 0.35f, (DamageSource)4, pendingBeat.crit, stun: false, pendingBeat.hit, 100f);
				ImpactVisual.Emit(Body, origin, Vector3.forward, 5f, ImpactKind.Afterbeat);
			}
		}
	}

	public void QueueAfterbeat(HealthComponent target, Vector3 point, bool crit, HashSet<HealthComponent> shared)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkServer.active && pending.Count < 64)
		{
			pending.Add(new PendingBeat
			{
				target = target,
				point = point,
				crit = crit,
				at = Time.fixedTime + 0.32f,
				hit = shared
			});
			ImpactVisual.Emit(Body, point, Vector3.forward, 1.5f, ImpactKind.ChargeContact);
		}
	}

	public void GrantPoise(float duration, bool charge = false)
	{
		if (NetworkServer.active)
		{
			chargeUntil = Time.fixedTime + duration;
			if (!Body.HasBuff(Content.Poise))
			{
				Body.AddBuff(Content.Poise);
			}
		}
	}

	public void EndChargePoise()
	{
		if (NetworkServer.active && Object.op_Implicit((Object)(object)Body) && Object.op_Implicit((Object)(object)Content.Poise) && Body.HasBuff(Content.Poise))
		{
			Body.RemoveBuff(Content.Poise);
		}
		chargeUntil = 0f;
	}

	public void CancelCharge()
	{
		if (Object.op_Implicit((Object)(object)Cavalry) && Cavalry.state is ChargeState && Body.hasEffectiveAuthority)
		{
			Cavalry.SetNextStateToMain();
		}
	}

	public void CancelRoll(string why)
	{
		LastCancellation = why;
		if (Object.op_Implicit((Object)(object)Body) && Body.hasEffectiveAuthority && Object.op_Implicit((Object)(object)Weapon) && Weapon.state is RollState)
		{
			Weapon.SetNextStateToMain();
		}
		VisualMask = 0;
	}

	public void Trace(string evt, string action, GenericSkill slot, float q, float coefficient, float proc, bool crit, int target = 0)
	{
		if (Plugin.Diagnostics.Value)
		{
			Plugin.Log($"TIMP event={evt} action={action} damage={coefficient:R} proc={proc:R} target={target}");
		}
	}

	private void OnDestroy()
	{
		if (Object.op_Implicit((Object)(object)Body))
		{
			CharacterBody body = Body;
			body.OnBodyDeath = (Action<CharacterBody>)Delegate.Remove(body.OnBodyDeath, new Action<CharacterBody>(Died));
		}
		pending.Clear();
		EndChargePoise();
	}
}
public enum Tuning : byte
{
	Low,
	Mid,
	High
}
public enum ActionKind : byte
{
	None,
	Left,
	Right,
	Roll,
	Stop,
	TuneLeft,
	TuneRight
}
public static class Rules
{
	public static float Speed(float a)
	{
		return Math.Max(0.1f, a);
	}

	public static float StrokeTime(float a)
	{
		return Math.Max(0.1f, 0.42f / Speed(a));
	}

	public static Tuning Next(Tuning value)
	{
		return (Tuning)((int)(value + 1) % 3);
	}

	public static float Range(Tuning value)
	{
		return value switch
		{
			Tuning.Mid => 22, 
			Tuning.Low => 10, 
			_ => 40, 
		};
	}

	public static float Angle(Tuning value)
	{
		return value switch
		{
			Tuning.Mid => 40, 
			Tuning.Low => 100, 
			_ => 12, 
		};
	}

	public static float Damage(Tuning value)
	{
		return value switch
		{
			Tuning.Mid => 2.4f, 
			Tuning.Low => 1.8f, 
			_ => 3.2f, 
		};
	}

	public static bool Resonant(Tuning left, Tuning right)
	{
		if (left != Tuning.Mid || right != Tuning.Low)
		{
			if (left == Tuning.High)
			{
				return right == Tuning.Mid;
			}
			return false;
		}
		return true;
	}

	public static float RollBonus(byte mask, Tuning left, Tuning right)
	{
		if (mask != 3 || !Resonant(left, right))
		{
			return 1f;
		}
		return 1.2f;
	}

	public static string Note(bool right, Tuning pitch)
	{
		if (!right)
		{
			return pitch switch
			{
				Tuning.Mid => "B", 
				Tuning.Low => "G", 
				_ => "D", 
			};
		}
		return pitch switch
		{
			Tuning.Mid => "D", 
			Tuning.Low => "B", 
			_ => "F", 
		};
	}

	public static float Contribution(byte mask, int side)
	{
		if ((mask & (1 << side)) != 0)
		{
			if (mask != 3)
			{
				return 1f;
			}
			return 0.5f;
		}
		return 0f;
	}
}
public static class CavalryRules
{
	public const float StrikeDamage = 4f;

	public const float StrikeRange = 22f;

	public const float StrikeAngle = 38f;

	public const float RollDuration = 2f;

	public const float RollTick = 0.2f;

	public const float RollRange = 14f;

	public const float RollAngle = 50f;

	public const float ChargeDuration = 1f;

	public const float ChargeDamage = 3.5f;

	public const float AfterbeatDamage = 1.8f;

	public const float AfterbeatDelay = 0.32f;

	public const float AfterbeatRadius = 5f;

	public const float GrandDamage = 9f;

	public const float GrandRange = 25f;

	public const float GrandAngle = 55f;

	public static float StrikeDuration(float speed)
	{
		return Math.Max(0.16f, 0.62f / Rules.Speed(speed));
	}

	public static float ContactTime(float speed)
	{
		return 0.12f / Rules.Speed(speed);
	}

	public static float ChargeSpeed(float walk, float age)
	{
		return Math.Max(1f, walk) * (2.5f + 0.5f * Math.Min(1f, Math.Max(0f, age) / 0.15f));
	}

	public static float RollDamage(float speed)
	{
		return 0.24f * Rules.Speed(speed);
	}

	public static bool ChargeCancel(bool pressed, float age)
	{
		if (pressed)
		{
			return age >= 0.1f;
		}
		return false;
	}
}
public sealed class CustomPcmOutput : IDisposable
{
	private sealed class LoopVoice
	{
		public Sample Sample;

		public Sample Wanted;

		public int Position;

		public float Envelope;

		public float Level;
	}

	private sealed class ClientState
	{
		public bool Active = true;

		public bool Audible;

		public bool PairWarning;

		public float TargetL;

		public float TargetR;

		public float CurrentL;

		public float CurrentR;

		public readonly int[,] Variant = new int[2, 3];

		public readonly LoopVoice[] Loops = new LoopVoice[3]
		{
			new LoopVoice(),
			new LoopVoice(),
			new LoopVoice()
		};
	}

	private sealed class StrikeVoice
	{
		public ClientState Owner;

		public Sample Sample;

		public int Position;

		public float Envelope;

		public float Level;

		public bool Stopping;
	}

	private sealed class Sample
	{
		public readonly float[] Data;

		public Sample(float[] data)
		{
			Data = data;
		}
	}

	private sealed class StrikeSet
	{
		public readonly Sample[] Variants;

		public StrikeSet(Sample[] variants)
		{
			Variants = variants;
		}
	}

	private sealed class Library
	{
		public readonly StrikeSet[,] Strikes = new StrikeSet[2, 3];

		public readonly Sample[,] Rolls = new Sample[2, 3];

		public readonly Sample[,] Pairs = new Sample[3, 3];

		public long SourceBytes;

		public int DecodedSourceFrames;

		public int StrikeCount;

		public int IndividualRollCount;

		public int PairCount;

		private static readonly string[] tuning = new string[3] { "low", "mid", "high" };

		public static Library Load(string directory)
		{
			Library library = new Library();
			long sourceBytes = 0L;
			int decodedFrames = 0;
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < 2; i++)
			{
				for (int j = 0; j < 3; j++)
				{
					string text = ((i == 0) ? "left" : "right") + "-" + tuning[j];
					library.Strikes[i, j] = new StrikeSet(new Sample[1] { Read(Path.Combine(directory, text + "-strike.wav"), loop: false, ref sourceBytes, ref decodedFrames) });
					library.Rolls[i, j] = Read(Path.Combine(directory, text + "-roll.wav"), loop: true, ref sourceBytes, ref decodedFrames);
				}
			}
			for (int k = 0; k < 2; k++)
			{
				for (int l = 0; l < 3; l++)
				{
					string text2 = ((k == 0) ? "left" : "right") + "-" + tuning[l];
					List<Sample> list = new List<Sample>(library.Strikes[k, l].Variants);
					for (int m = 2; m <= 6; m++)
					{
						Sample sample = Optional(Path.Combine(directory, text2 + "-strike-" + m.ToString("00") + ".wav"), loop: false, ref sourceBytes, ref decodedFrames);
						if (sample != null)
						{
							list.Add(sample);
						}
					}
					library.Strikes[k, l] = new StrikeSet(list.ToArray());
					num2 += list.Count;
				}
			}
			for (int n = 0; n < 3; n++)
			{
				for (int num3 = 0; num3 < 3; num3++)
				{
					library.Pairs[n, num3] = Optional(Path.Combine(directory, "split-" + n + "-" + num3 + "-roll.wav"), loop: true, ref sourceBytes, ref decodedFrames);
					if (library.Pairs[n, num3] != null)
					{
						num++;
					}
				}
			}
			library.SourceBytes = sourceBytes;
			library.DecodedSourceFrames = decodedFrames;
			library.StrikeCount = num2;
			library.IndividualRollCount = 6;
			library.PairCount = num;
			Message("Loaded timpani PCM library once: " + num2 + " strike takes, 6 individual rolls, " + num + " paired rolls; " + sourceBytes + " WAV bytes.");
			return library;
		}

		private static Sample Optional(string path, bool loop, ref long sourceBytes, ref int decodedFrames)
		{
			if (!File.Exists(path))
			{
				return null;
			}
			long num = sourceBytes;
			int num2 = decodedFrames;
			try
			{
				return Read(path, loop, ref sourceBytes, ref decodedFrames);
			}
			catch (Exception ex)
			{
				sourceBytes = num;
				decodedFrames = num2;
				Message("Optional timpani WAV skipped: " + Path.GetFileName(path) + ": " + ex.Message);
				return null;
			}
		}

		private static Sample Read(string path, bool loop, ref long sourceBytes, ref int decodedFrames)
		{
			FileInfo fileInfo = new FileInfo(path);
			if (!fileInfo.Exists)
			{
				throw new FileNotFoundException("Required timpani WAV missing", path);
			}
			if (fileInfo.Length < 44 || fileInfo.Length > 5242880 || (sourceBytes += fileInfo.Length) > 100663296)
			{
				throw new InvalidDataException("Audio library/file byte limit");
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			byte[] array = null;
			using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(path)))
			{
				if (new string(binaryReader.ReadChars(4)) != "RIFF")
				{
					throw new InvalidDataException("Expected RIFF WAV: " + path);
				}
				uint num5 = binaryReader.ReadUInt32();
				if (new string(binaryReader.ReadChars(4)) != "WAVE" || (long)num5 + 8L > binaryReader.BaseStream.Length)
				{
					throw new InvalidDataException("Invalid WAVE length");
				}
				long num6 = (long)num5 + 8L;
				while (binaryReader.BaseStream.Position + 8 <= num6)
				{
					string text = new string(binaryReader.ReadChars(4));
					uint num7 = binaryReader.ReadUInt32();
					long num8 = binaryReader.BaseStream.Position + num7;
					if (num8 > num6 || num7 > 5242880)
					{
						throw new InvalidDataException("Invalid WAVE chunk");
					}
					if (text == "fmt ")
					{
						if (num7 < 16)
						{
							throw new InvalidDataException("Short WAVE format");
						}
						num4 = binaryReader.ReadUInt16();
						num2 = binaryReader.ReadUInt16();
						num = binaryReader.ReadInt32();
						binaryReader.ReadInt32();
						ushort num9 = binaryReader.ReadUInt16();
						num3 = binaryReader.ReadUInt16();
						if (num9 != num2 * 2)
						{
							throw new InvalidDataException("WAVE PCM block alignment");
						}
					}
					else if (text == "data")
					{
						if (array != null)
						{
							throw new InvalidDataException("Multiple WAVE data chunks unsupported");
						}
						array = binaryReader.ReadBytes((int)num7);
						if (array.Length != (int)num7)
						{
							throw new EndOfStreamException();
						}
					}
					binaryReader.BaseStream.Position = num8 + (num7 & 1);
				}
			}
			if (num4 != 1 || (num2 != 1 && num2 != 2) || num3 != 16 || num < 8000 || num > 96000 || array == null || array.Length % (num2 * 2) != 0)
			{
				throw new InvalidDataException("Expected mono/stereo PCM16 WAV, 8-96kHz: " + path);
			}
			int num10 = array.Length / (num2 * 2);
			int num11 = (int)Math.Round((double)num10 * 48000.0 / (double)num);
			if (num11 < 2400 || num11 > 1152000 || (decodedFrames += num11) > 24000000)
			{
				throw new InvalidDataException("Audio duration/decoded-memory limit");
			}
			float[] array2 = new float[num11];
			for (int i = 0; i < num11; i++)
			{
				double num12 = (double)i * (double)num / 48000.0;
				int num13 = Math.Min(num10 - 1, (int)num12);
				int num14 = Math.Min(num10 - 1, num13 + 1);
				float num15 = (float)(num12 - (double)num13);
				float num16 = 0f;
				float num17 = 0f;
				for (int j = 0; j < num2; j++)
				{
					num16 += (float)BitConverter.ToInt16(array, (num13 * num2 + j) * 2) / 32768f;
					num17 += (float)BitConverter.ToInt16(array, (num14 * num2 + j) * 2) / 32768f;
				}
				array2[i] = (num16 + (num17 - num16) * num15) / (float)num2;
			}
			if (loop)
			{
				int num18 = Math.Min(240, num11 / 8);
				float[] array3 = new float[num11 - num18];
				for (int k = 0; k < array3.Length; k++)
				{
					float num19 = ((k < num18) ? ((float)(0.5 - 0.5 * Math.Cos(Math.PI * (double)(k + 1) / (double)num18))) : 1f);
					array3[k] = ((k < num18) ? (array2[num11 - num18 + k] * (1f - num19) + array2[k] * num19) : array2[k]);
				}
				array2 = array3;
			}
			return new Sample(array2);
		}
	}

	private sealed class Engine
	{
		public readonly object Gate = new object();

		public readonly Library Bank;

		public readonly StrikeVoice[] Strikes = new StrikeVoice[16];

		private readonly ClientState[] clients = new ClientState[8];

		private readonly NativeBuffer[] buffers = new NativeBuffer[3];

		private readonly short[] output = new short[960];

		public volatile bool Ready;

		public volatile bool Failed;

		public volatile bool Closing;

		public int ClientCount;

		public int CloseAfter;

		private Thread worker;

		private IntPtr device;

		public Engine(Library bank)
		{
			Bank = bank;
			for (int i = 0; i < Strikes.Length; i++)
			{
				Strikes[i] = new StrikeVoice();
			}
		}

		public ClientState Add()
		{
			lock (Gate)
			{
				if (Closing || Failed)
				{
					return null;
				}
				for (int i = 0; i < clients.Length; i++)
				{
					if (clients[i] == null)
					{
						ClientState clientState = new ClientState();
						clients[i] = clientState;
						ClientCount++;
						return clientState;
					}
				}
				return null;
			}
		}

		public void Start()
		{
			worker = new Thread(Work)
			{
				IsBackground = true,
				Name = "Timpanist PCM output"
			};
			worker.Start();
		}

		private void Work()
		{
			try
			{
				WaveFormat format = new WaveFormat
				{
					Format = 1,
					Channels = 2,
					SamplesPerSecond = 48000u,
					BytesPerSecond = 192000u,
					BlockAlign = 4,
					Bits = 16,
					ExtraSize = 0
				};
				Check(Native.waveOutOpen(out var intPtr, uint.MaxValue, ref format, UIntPtr.Zero, UIntPtr.Zero, 0u), "open");
				device = intPtr;
				for (int i = 0; i < buffers.Length; i++)
				{
					buffers[i] = new NativeBuffer();
					buffers[i].Prepare(device);
				}
				Ready = true;
				Message("Custom timpani WinMM PCM ready: 48 kHz stereo, three 10 ms buffers; owned volume/pan, independent of Wwise SFX bus.");
				int num = 0;
				while (true)
				{
					lock (Gate)
					{
						if (ClientCount == 0 && Environment.TickCount - CloseAfter >= 60)
						{
							Closing = true;
							break;
						}
					}
					NativeBuffer nativeBuffer = buffers[num];
					if (!nativeBuffer.Submitted || nativeBuffer.Done)
					{
						lock (Gate)
						{
							Render();
						}
						Marshal.Copy(output, 0, nativeBuffer.Data, output.Length);
						Check(Native.waveOutWrite(device, nativeBuffer.Header, (uint)NativeBuffer.HeaderSize), "write");
						nativeBuffer.Submitted = true;
						num = (num + 1) % buffers.Length;
					}
					else
					{
						Thread.Sleep(2);
					}
				}
			}
			catch (Exception ex)
			{
				Failed = true;
				Closing = true;
				Message("Custom timpani PCM stopped: " + ex.GetType().Name + ": " + ex.Message);
			}
			finally
			{
				Ready = false;
				Closing = true;
				int num2 = 0;
				while (!Cleanup())
				{
					if (num2 == 0)
					{
						Message("PCM cleanup retained native resources for retry; new output waits for successful cleanup.");
					}
					num2 = Math.Min(19, num2 + 1);
					Thread.Sleep(100 + num2 * 100);
				}
				lock (global)
				{
					if (shared == this)
					{
						shared = null;
					}
				}
				Message("Custom timpani PCM device and all native buffers closed.");
			}
		}

		private bool Cleanup()
		{
			NativeBuffer[] array;
			if (device != IntPtr.Zero)
			{
				uint num;
				try
				{
					num = Native.waveOutReset(device);
				}
				catch
				{
					return false;
				}
				if (num != 0)
				{
					return false;
				}
				array = buffers;
				foreach (NativeBuffer nativeBuffer in array)
				{
					if (nativeBuffer != null && !nativeBuffer.Unprepare(device))
					{
						return false;
					}
				}
				try
				{
					if (Native.waveOutClose(device) != 0)
					{
						return false;
					}
				}
				catch
				{
					return false;
				}
				device = IntPtr.Zero;
			}
			array = buffers;
			for (int i = 0; i < array.Length; i++)
			{
				array[i]?.Free();
			}
			return true;
		}

		private static float Move(float x, float target, float step)
		{
			if (!(x < target))
			{
				return Math.Max(target, x - step);
			}
			return Math.Min(target, x + step);
		}

		private void Render()
		{
			for (int i = 0; i < 480; i++)
			{
				float num = 0f;
				float num2 = 0f;
				ClientState[] array = clients;
				foreach (ClientState clientState in array)
				{
					if (clientState == null)
					{
						continue;
					}
					clientState.CurrentL = Move(clientState.CurrentL, clientState.TargetL, 0.0013888889f);
					clientState.CurrentR = Move(clientState.CurrentR, clientState.TargetR, 0.0013888889f);
					LoopVoice[] loops = clientState.Loops;
					foreach (LoopVoice loopVoice in loops)
					{
						if (loopVoice.Sample == null && loopVoice.Wanted != null)
						{
							loopVoice.Sample = loopVoice.Wanted;
							loopVoice.Position = 0;
						}
						loopVoice.Envelope = Move(loopVoice.Envelope, (loopVoice.Sample != null && loopVoice.Sample == loopVoice.Wanted) ? loopVoice.Level : 0f, 0.0010416667f);
						if (loopVoice.Sample != null)
						{
							float num3 = loopVoice.Sample.Data[loopVoice.Position++] * loopVoice.Envelope;
							if (loopVoice.Position >= loopVoice.Sample.Data.Length)
							{
								loopVoice.Position = 0;
							}
							num += num3 * clientState.CurrentL;
							num2 += num3 * clientState.CurrentR;
							if (loopVoice.Envelope <= 0f && loopVoice.Sample != loopVoice.Wanted)
							{
								loopVoice.Sample = null;
								loopVoice.Position = 0;
							}
						}
					}
				}
				StrikeVoice[] strikes = Strikes;
				foreach (StrikeVoice strikeVoice in strikes)
				{
					ClientState owner = strikeVoice.Owner;
					if (owner != null)
					{
						strikeVoice.Envelope = Move(strikeVoice.Envelope, (!strikeVoice.Stopping) ? 1 : 0, 1f / (48000f * (strikeVoice.Stopping ? 0.01f : 0.002f)));
						int num4 = strikeVoice.Sample.Data.Length - strikeVoice.Position;
						float num5 = Math.Min(1f, (float)num4 / 240f);
						float num6 = strikeVoice.Sample.Data[strikeVoice.Position++] * strikeVoice.Level * strikeVoice.Envelope * num5;
						num += num6 * owner.CurrentL;
						num2 += num6 * owner.CurrentR;
						if (strikeVoice.Position >= strikeVoice.Sample.Data.Length || (strikeVoice.Stopping && strikeVoice.Envelope <= 0f))
						{
							strikeVoice.Owner = null;
							strikeVoice.Sample = null;
						}
					}
				}
				output[i * 2] = (short)(Math.Tanh(num * 0.75f) * 32760.0);
				output[i * 2 + 1] = (short)(Math.Tanh(num2 * 0.75f) * 32760.0);
			}
			for (int l = 0; l < clients.Length; l++)
			{
				ClientState clientState2 = clients[l];
				if (clientState2 == null || clientState2.Active || clientState2.CurrentL > 0f || clientState2.CurrentR > 0f)
				{
					continue;
				}
				bool flag = false;
				LoopVoice[] loops = clientState2.Loops;
				for (int j = 0; j < loops.Length; j++)
				{
					if (loops[j].Sample != null)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					clients[l] = null;
				}
			}
		}

		private static void Check(uint result, string operation)
		{
			if (result != 0)
			{
				throw new InvalidOperationException("waveOut " + operation + " MMRESULT=" + result);
			}
		}
	}

	private struct WaveHeader
	{
		public IntPtr Data;

		public uint Length;

		public uint Recorded;

		public UIntPtr User;

		public uint Flags;

		public uint Loops;

		public IntPtr Next;

		public UIntPtr Reserved;
	}

	[StructLayout(LayoutKind.Sequential, Pack = 2)]
	private struct WaveFormat
	{
		public ushort Format;

		public ushort Channels;

		public uint SamplesPerSecond;

		public uint BytesPerSecond;

		public ushort BlockAlign;

		public ushort Bits;

		public ushort ExtraSize;
	}

	private sealed class NativeBuffer
	{
		public static readonly int HeaderSize = Marshal.SizeOf(typeof(WaveHeader));

		private static readonly int FlagsOffset = (int)Marshal.OffsetOf(typeof(WaveHeader), "Flags");

		public IntPtr Header;

		public IntPtr Data;

		public bool Submitted;

		private bool prepared;

		public bool Done => (Marshal.ReadInt32(Header, FlagsOffset) & 1) != 0;

		public void Prepare(IntPtr device)
		{
			Data = Marshal.AllocHGlobal(1920);
			Header = Marshal.AllocHGlobal(HeaderSize);
			Marshal.StructureToPtr(new WaveHeader
			{
				Data = Data,
				Length = 1920u
			}, Header, fDeleteOld: false);
			uint num = Native.waveOutPrepareHeader(device, Header, (uint)HeaderSize);
			if (num != 0)
			{
				throw new InvalidOperationException("waveOut prepare MMRESULT=" + num);
			}
			prepared = true;
		}

		public bool Unprepare(IntPtr device)
		{
			if (!prepared)
			{
				return true;
			}
			uint num;
			try
			{
				num = Native.waveOutUnprepareHeader(device, Header, (uint)HeaderSize);
			}
			catch
			{
				return false;
			}
			if (num != 0)
			{
				return false;
			}
			prepared = false;
			return true;
		}

		public void Free()
		{
			if (Header != IntPtr.Zero)
			{
				Marshal.FreeHGlobal(Header);
				Header = IntPtr.Zero;
			}
			if (Data != IntPtr.Zero)
			{
				Marshal.FreeHGlobal(Data);
				Data = IntPtr.Zero;
			}
		}
	}

	private static class Native
	{
		[DllImport("winmm.dll", ExactSpelling = true)]
		internal static extern uint waveOutOpen(out IntPtr output, uint device, ref WaveFormat format, UIntPtr callback, UIntPtr instance, uint flags);

		[DllImport("winmm.dll", ExactSpelling = true)]
		internal static extern uint waveOutPrepareHeader(IntPtr output, IntPtr header, uint bytes);

		[DllImport("winmm.dll", ExactSpelling = true)]
		internal static extern uint waveOutWrite(IntPtr output, IntPtr header, uint bytes);

		[DllImport("winmm.dll", ExactSpelling = true)]
		internal static extern uint waveOutReset(IntPtr output);

		[DllImport("winmm.dll", ExactSpelling = true)]
		internal static extern uint waveOutUnprepareHeader(IntPtr output, IntPtr header, uint bytes);

		[DllImport("winmm.dll", ExactSpelling = true)]
		internal static extern uint waveOutClose(IntPtr output);
	}

	private const int Rate = 48000;

	private const int Frames = 480;

	private const int BufferCount = 3;

	private const int MaxClients = 8;

	private const int MaxStrikes = 16;

	private const int MaxFileBytes = 5242880;

	private const int MaxLibraryBytes = 100663296;

	private const int MaxDecodedFrames = 24000000;

	private const int MaxSampleFrames = 1152000;

	private static readonly object global = new object();

	private static readonly object messageGate = new object();

	private static readonly Queue<string> messages = new Queue<string>();

	private static Library library;

	private static Engine shared;

	private static bool unsupportedReported;

	private static long nextLibraryTry;

	private static string lastLibraryError;

	private readonly Engine engine;

	private readonly ClientState state;

	private readonly Action<string> logger;

	private bool disposed;

	public bool Available
	{
		get
		{
			if (!disposed && engine.Ready)
			{
				return !engine.Failed;
			}
			return false;
		}
	}

	private CustomPcmOutput(Engine e, ClientState s, Action<string> log)
	{
		engine = e;
		state = s;
		logger = log;
	}

	public static CustomPcmOutput TryCreate(string directory, Action<string> logger)
	{
		PumpMessages(logger);
		if (Environment.OSVersion.Platform != PlatformID.Win32NT)
		{
			if (!unsupportedReported)
			{
				unsupportedReported = true;
				Message("Custom timpani PCM requires Windows; no native explosion fallback.");
				PumpMessages(logger);
			}
			return null;
		}
		lock (global)
		{
			try
			{
				if (library == null)
				{
					if (DateTime.UtcNow.Ticks < nextLibraryTry)
					{
						return null;
					}
					try
					{
						library = Library.Load(directory);
						lastLibraryError = null;
					}
					catch (Exception ex)
					{
						nextLibraryTry = DateTime.UtcNow.AddSeconds(5.0).Ticks;
						string text = ex.GetType().Name + ": " + ex.Message;
						if (text != lastLibraryError)
						{
							Message("Custom timpani WAV library unavailable: " + text);
							lastLibraryError = text;
						}
						return null;
					}
				}
				if (shared != null && (shared.Closing || shared.Failed))
				{
					return null;
				}
				bool flag = shared == null;
				if (flag)
				{
					shared = new Engine(library);
				}
				ClientState clientState = shared.Add();
				if (clientState == null)
				{
					Message("Custom timpani client limit reached (8); this body remains silent.");
					return null;
				}
				CustomPcmOutput result = new CustomPcmOutput(shared, clientState, logger);
				if (flag)
				{
					try
					{
						shared.Start();
					}
					catch
					{
						shared = null;
						throw;
					}
				}
				return result;
			}
			catch (Exception ex2)
			{
				Message("Custom timpani audio unavailable: " + ex2.GetType().Name + ": " + ex2.Message);
				return null;
			}
		}
	}

	public void PumpLogs()
	{
		PumpMessages(logger);
	}

	public static void PumpMessages(Action<string> logger)
	{
		if (logger == null)
		{
			return;
		}
		for (int i = 0; i < 16; i++)
		{
			string obj;
			lock (messageGate)
			{
				if (messages.Count == 0)
				{
					break;
				}
				obj = messages.Dequeue();
			}
			try
			{
				logger(obj);
			}
			catch
			{
			}
		}
	}

	private static void Message(string text)
	{
		lock (messageGate)
		{
			if (messages.Count < 32)
			{
				messages.Enqueue(text);
			}
		}
	}

	private static float Clamp(float x, float a, float b)
	{
		if (!float.IsNaN(x) && !float.IsInfinity(x))
		{
			return Math.Max(a, Math.Min(b, x));
		}
		return a;
	}

	public void SetMix(float gain, float pan, bool audible, bool leftRoll, int leftTuning, bool rightRoll, int rightTuning, float rollGain)
	{
		if (disposed)
		{
			return;
		}
		lock (engine.Gate)
		{
			if (!state.Active)
			{
				return;
			}
			state.Audible = audible;
			gain = (audible ? Clamp(gain, 0f, 1f) : 0f);
			pan = Clamp(pan, -1f, 1f);
			state.TargetL = gain * (float)Math.Sqrt((double)(1f - pan) * 0.5);
			state.TargetR = gain * (float)Math.Sqrt((double)(1f + pan) * 0.5);
			int num = Math.Max(0, Math.Min(2, leftTuning));
			int num2 = Math.Max(0, Math.Min(2, rightTuning));
			Sample sample = ((leftRoll && rightRoll) ? engine.Bank.Pairs[num, num2] : null);
			if (audible && leftRoll && rightRoll && sample == null && !state.PairWarning)
			{
				state.PairWarning = true;
				Message("Paired roll WAV missing; mixing the two individual continuous roll recordings.");
			}
			state.Loops[0].Wanted = ((audible && leftRoll && sample == null) ? engine.Bank.Rolls[0, num] : null);
			state.Loops[1].Wanted = ((audible && rightRoll && sample == null) ? engine.Bank.Rolls[1, num2] : null);
			state.Loops[2].Wanted = (audible ? sample : null);
			LoopVoice[] loops = state.Loops;
			for (int i = 0; i < loops.Length; i++)
			{
				loops[i].Level = Clamp(rollGain, 0f, 1f);
			}
			if (audible)
			{
				return;
			}
			StrikeVoice[] strikes = engine.Strikes;
			foreach (StrikeVoice strikeVoice in strikes)
			{
				if (strikeVoice.Owner == state)
				{
					strikeVoice.Stopping = true;
				}
			}
		}
	}

	public void Strike(bool right, int tuning, float gain)
	{
		if (disposed)
		{
			return;
		}
		lock (engine.Gate)
		{
			if (!state.Active || !state.Audible || engine.Failed || engine.Closing)
			{
				return;
			}
			StrikeVoice strikeVoice = null;
			StrikeVoice[] strikes = engine.Strikes;
			foreach (StrikeVoice strikeVoice2 in strikes)
			{
				if (strikeVoice2.Owner == null)
				{
					strikeVoice = strikeVoice2;
					break;
				}
			}
			if (strikeVoice != null)
			{
				int num = (right ? 1 : 0);
				int num2 = Math.Max(0, Math.Min(2, tuning));
				Sample[] variants = engine.Bank.Strikes[num, num2].Variants;
				int num3 = state.Variant[num, num2];
				state.Variant[num, num2] = (num3 + 1) % variants.Length;
				strikeVoice.Owner = state;
				strikeVoice.Sample = variants[num3];
				strikeVoice.Position = 0;
				strikeVoice.Level = Clamp(gain, 0f, 1f);
				strikeVoice.Envelope = 0f;
				strikeVoice.Stopping = false;
			}
		}
	}

	public void Dispose()
	{
		if (disposed)
		{
			return;
		}
		disposed = true;
		lock (engine.Gate)
		{
			if (!state.Active)
			{
				return;
			}
			state.Active = false;
			state.Audible = false;
			state.TargetL = (state.TargetR = 0f);
			LoopVoice[] loops = state.Loops;
			for (int i = 0; i < loops.Length; i++)
			{
				loops[i].Wanted = null;
			}
			StrikeVoice[] strikes = engine.Strikes;
			foreach (StrikeVoice strikeVoice in strikes)
			{
				if (strikeVoice.Owner == state)
				{
					strikeVoice.Stopping = true;
				}
			}
			engine.ClientCount--;
			if (engine.ClientCount == 0)
			{
				engine.CloseAfter = Environment.TickCount;
			}
		}
	}
}
public sealed class DevelopmentHarness : MonoBehaviour
{
	[ConCommand(/*Could not decode attribute arguments.*/)]
	private static void Probe(ConCommandArgs args)
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		CharacterBody senderBody = ((ConCommandArgs)(ref args)).senderBody;
		TimpanistController timpanistController = (Object.op_Implicit((Object)(object)senderBody) ? ((Component)senderBody).GetComponent<TimpanistController>() : null);
		if (!Object.op_Implicit((Object)(object)timpanistController))
		{
			Plugin.Log("No Timpanist sender body");
			return;
		}
		Plugin.Log($"TIMP 0.3.2 authority={senderBody.hasEffectiveAuthority} secondaryStock={senderBody.skillLocator.secondary.stock} rollMask={timpanistController.VisualMask} bodyState={((object)timpanistController.BodyMachine.state).GetType().Name} grounded={senderBody.characterMotor.isGrounded} position={((Component)senderBody).transform.position} foot={senderBody.footPosition}");
	}
}
public static class DisplayRules
{
	public static ItemDisplayRuleSet Mounted(ItemDisplayRuleSet source)
	{
		//IL_004d: 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_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		ItemDisplayRuleSet val = ScriptableObject.CreateInstance<ItemDisplayRuleSet>();
		((Object)val).name = "TimpanistMountedDisplayRules";
		if (!Object.op_Implicit((Object)(object)source) || source.keyAssetRuleGroups == null)
		{
			val.keyAssetRuleGroups = Array.Empty<KeyAssetRuleGroup>();
			return val;
		}
		KeyAssetRuleGroup[] array = (KeyAssetRuleGroup[])source.keyAssetRuleGroups.Clone();
		for (int i = 0; i < array.Length; i++)
		{
			DisplayRuleGroup displayRuleGroup = array[i].displayRuleGroup;
			if (displayRuleGroup.rules != null)
			{
				ItemDisplayRule[] array2 = (ItemDisplayRule[])displayRuleGroup.rules.Clone();
				for (int j = 0; j < array2.Length; j++)
				{
					string text = (array2[j].childName ?? "").ToLowerInvariant();
					bool flag = text.EndsWith("l") || text.Contains("left");
					array2[j].childName = (text.Contains("head") ? "Head" : (text.Contains("chest") ? "Chest" : (text.Contains("neck") ? "Neck" : ((!text.Contains("upperarm") && !text.Contains("shoulder")) ? ((!text.Contains("arm") && !text.Contains("hand")) ? ((!text.Contains("thigh") && !text.Contains("calf") && !text.Contains("foot")) ? (text.Contains("pelvis") ? (flag ? "HipL" : "HipR") : "SaddleBack") : (flag ? "HorseFlankL" : "HorseFlankR")) : (flag ? "ForearmL" : "ForearmR")) : (flag ? "ShoulderL" : "ShoulderR")))));
					array2[j].localPos = Vector3.ClampMagnitude(array2[j].localPos, 0.23f);
				}
				displayRuleGroup.rules = array2;
				array[i].displayRuleGroup = displayRuleGroup;
			}
		}
		val.keyAssetRuleGroups = array;
		return val;
	}
}
public sealed class DrumSurfaceVisual : MonoBehaviour
{
	private CharacterModel model;

	private TimpanistController c;

	private readonly Material[] materials = (Material[])(object)new Material[2];

	private readonly LineRenderer[] rings = (LineRenderer[])(object)new LineRenderer[2];

	private readonly TrailRenderer[] trails = (TrailRenderer[])(object)new TrailRenderer[2];

	private void Start()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		model = ((Component)this).GetComponentInParent<CharacterModel>();
		if (!Object.op_Implicit((Object)(object)PressureVisual.Template))
		{
			return;
		}
		Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>();
		for (int i = 0; i < 2; i++)
		{
			materials[i] = PressureVisual.CreateMaterial(PressureVisual.ColorFor((i != 0) ? Tuning.High : Tuning.Low));
			string text = ((i == 0) ? "L" : "R");
			Transform val = null;
			Transform val2 = null;
			Transform[] array = componentsInChildren;
			foreach (Transform val3 in array)
			{
				if (((Object)val3).name == "Drum" + text)
				{
					val = val3;
				}
				if (((Object)val3).name == "Hand" + text)
				{
					val2 = val3;
				}
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				GameObject val4 = new GameObject("PitchRing" + text);
				val4.transform.SetParent(val, false);
				val4.transform.localPosition = Vector3.up * 0.012f;
				LineRenderer val5 = val4.AddComponent<LineRenderer>();
				((Renderer)val5).sharedMaterial = materials[i];
				val5.useWorldSpace = false;
				val5.positionCount = 33;
				val5.widthMultiplier = 0.018f;
				float num = ((i == 0) ? 0.342f : 0.305f);
				for (int k = 0; k < 33; k++)
				{
					float num2 = (float)k * (float)Math.PI * 2f / 32f;
					val5.SetPosition(k, new Vector3(Mathf.Cos(num2) * num, 0f, Mathf.Sin(num2) * num));
				}
				rings[i] = val5;
			}
			if (Object.op_Implicit((Object)(object)val2))
			{
				GameObject val6 = new GameObject("MalletTrail" + text);
				val6.transform.SetParent(val2, false);
				val6.transform.localPosition = new Vector3((i == 0) ? (-0.04f) : 0.04f, -0.1f, 0.295f);
				TrailRenderer val7 = val6.AddComponent<TrailRenderer>();
				((Renderer)val7).sharedMaterial = materials[i];
				val7.time = 0.1f;
				val7.startWidth = 0.028f;
				val7.endWidth = 0f;
				val7.minVertexDistance = 0.025f;
				val7.emitting = false;
				trails[i] = val7;
			}
		}
	}

	private void LateUpdate()
	{
		//IL_006e: 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_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)model) && Object.op_Implicit((Object)(object)model.body))
		{
			c = ((Component)model.body).GetComponent<TimpanistController>();
		}
		for (int i = 0; i < 2; i++)
		{
			Color val = PressureVisual.ColorFor(Object.op_Implicit((Object)(object)c) ? c.Pitch(i == 1) : ((i != 0) ? Tuning.High : Tuning.Low));
			bool flag = Object.op_Implicit((Object)(object)c) && c.Body.healthComponent.alive;
			float num = (Object.op_Implicit((Object)(object)c) ? Mathf.Clamp01(1f - (Time.time - ((i == 0) ? c.LeftFlash : c.RightFlash)) / 0.35f) : 0f);
			float num2 = ((flag && (c.VisualMask & (1 << i)) != 0) ? (0.65f + 0.2f * Mathf.Sin(Time.time * 24f)) : (0.12f + num * 0.8f));
			val.a = (flag ? num2 : 0.12f);
			bool flag2 = Object.op_Implicit((Object)(object)c) && Time.time - c.GrandFlash < 0.55f;
			if (flag2)
			{
				val = Color.Lerp(val, Color.white, 0.35f + 0.2f * Mathf.Sin(Time.time * 7f));
			}
			Material val2 = materials[i];
			if (Object.op_Implicit((Object)(object)val2))
			{
				if (val2.HasProperty("_Color"))
				{
					val2.SetColor("_Color", val);
				}
				if (val2.HasProperty("_EmColor"))
				{
					val2.SetColor("_EmColor", val);
				}
				if (val2.HasProperty("_EmPower"))
				{
					val2.SetFloat("_EmPower", flag2 ? 3f : (1f + num * 3f));
				}
			}
			if (Object.op_Implicit((Object)(object)rings[i]))
			{
				LineRenderer obj = rings[i];
				Color startColor = (rings[i].endColor = val);
				obj.startColor = startColor;
				rings[i].widthMultiplier = 0.035f + num * 0.06f;
			}
			if (Object.op_Implicit((Object)(object)trails[i]))
			{
				trails[i].emitting = flag && (c.VisualRolling || num > 0.1f);
				val.a = 0.65f;
				trails[i].startColor = val;
				val.a = 0f;
				trails[i].endColor = val;
			}
		}
	}

	private void OnDestroy()
	{
		Material[] array = materials;
		foreach (Material val in array)
		{
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}
}
public static class Graybox
{
	public static readonly Color Green = Color32.op_Implicit(new Color32((byte)50, (byte)145, (byte)114, byte.MaxValue));

	public static readonly Color Copper = Color32.op_Implicit(new Color32((byte)232, (byte)157, (byte)88, byte.MaxValue));

	public static readonly Color Ivory = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)238, (byte)200, byte.MaxValue));

	public static readonly Color Metal = Color32.op_Implicit(new Color32((byte)142, (byte)173, (byte)186, byte.MaxValue));

	public static readonly Color Bay = Color32.op_Implicit(new Color32((byte)124, (byte)78, (byte)51, byte.MaxValue));

	public static readonly Color Black = Color32.op_Implicit(new Color32((byte)41, (byte)49, (byte)56, byte.MaxValue));

	public static Material Material(Material template, Color color)
	{
		//IL_001a: 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_0020: Expected O, but got Unknown
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		Material val = (Object.op_Implicit((Object)(object)template) ? new Material(template) : new Material(Shader.Find("Standard")));
		((Object)val).name = "TimpanistGraybox_" + ColorUtility.ToHtmlStringRGB(color);
		if (val.HasProperty("_Color"))
		{
			val.SetColor("_Color", color);
		}
		if (val.HasProperty("_MainTex"))
		{
			val.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
		}
		if (val.HasProperty("_NormalTex"))
		{
			val.SetTexture("_NormalTex", (Texture)null);
		}
		if (val.HasProperty("_EmColor"))
		{
			val.SetColor("_EmColor", color * 0.3f);
		}
		if (val.HasProperty("_EmTex"))
		{
			val.SetTexture("_EmTex", (Texture)(object)Texture2D.whiteTexture);
		}
		if (val.HasProperty("_EmPower"))
		{
			val.SetFloat("_EmPower", 0.4f);
		}
		if (val.HasProperty("_SpecularStrength"))
		{
			val.SetFloat("_SpecularStrength", 0.3f);
		}
		if (val.HasProperty("_NormalStrength"))
		{
			val.SetFloat("_NormalStrength", 0f);
		}
		return val;
	}

	public static Transform Part(Transform parent, string name, PrimitiveType type, Vector3 position, Vector3 scale, Material mat)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		GameObject obj = GameObject.CreatePrimitive(type);
		((Object)obj).name = name;
		obj.transform.SetParent(parent, false);
		obj.transform.localPosition = position;
		obj.transform.localScale = scale;
		Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>());
		obj.GetComponent<Renderer>().sharedMaterial = mat;
		return obj.transform;
	}

	public static Sprite Icon(Color color)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0086: 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_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: 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_004c: 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)
		Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				float num = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(31.5f, 31.5f));
				val.SetPixel(j, i, (num > 29f) ? Color.clear : ((num > 23f) ? color : Ivory));
			}
		}
		val.Apply();
		return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
	}

	public static void BuildModel(GameObject body, Transform model, Material template)
	{
		//IL_0080: 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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: 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_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		CharacterModel component = ((Component)model).GetComponent<CharacterModel>();
		Renderer[] componentsInChildren = ((Component)model).GetComponentsInChildren<Renderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
		}
		LODGroup[] componentsInChildren2 = ((Component)model).GetComponentsInChildren<LODGroup>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
		}
		HurtBox[] componentsInChildren3 = ((Component)model).GetComponentsInChildren<HurtBox>(true);
		for (int i = 0; i < componentsInChildren3.Length; i++)
		{
			((Component)componentsInChildren3[i]).gameObject.SetActive(false);
		}
		model.localPosition = Vector3.zero;
		model.localScale = Vector3.one;
		Transform val = Content.Anchor(model, "TimpanistGraybox", Vector3.zero);
		bool flag = Presentation.TryBuild(val, template);
		if (!flag)
		{
			BuildVisual(val, template);
		}
		Renderer[] componentsInChildren4 = ((Component)val).GetComponentsInChildren<Renderer>(true);
		RendererInfo[] array = (RendererInfo[])(object)new RendererInfo[componentsInChildren4.Length];
		for (int j = 0; j < array.Length; j++)
		{
			array[j] = new RendererInfo
			{
				renderer = componentsInChildren4[j],
				defaultMaterial = componentsInChildren4[j].sharedMaterial,
				defaultShadowCastingMode = (ShadowCastingMode)1,
				hideOnDeath = true
			};
		}
		component.baseRendererInfos = array;
		component.baseLightInfos = Array.Empty<LightInfo>();
		component.itemDisplayRuleSet = DisplayRules.Mounted(component.itemDisplayRuleSet);
		HurtBoxGroup component2 = ((Component)model).GetComponent<HurtBoxGroup>();
		Transform obj = Content.Anchor(model, "TimpanistHurtCapsule", new Vector3(0f, 1.1f, 0f));
		((Component)obj).gameObject.layer = LayerIndex.entityPrecise.intVal;
		CapsuleCollider obj2 = ((Component)obj).gameObject.AddComponent<CapsuleCollider>();
		obj2.radius = 0.48f;
		obj2.height = 2.2f;
		((Collider)obj2).isTrigger = false;
		HurtBox val2 = ((Component)obj).gameObject.AddComponent<HurtBox>();
		val2.healthComponent = body.GetComponent<HealthComponent>();
		val2.isBullseye = true;
		val2.hurtBoxGroup = component2;
		val2.indexInGroup = 0;
		component2.hurtBoxes = (HurtBox[])(object)new HurtBox[1] { val2 };
		component2.mainHurtBox = val2;
		component2.bullseyeCount = 1;
		SkinDef val3 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val3).name = "RodaniusTimpanistDefault";
		val3.nameToken = "TIMPANIST_DEFAULT";
		val3.rootObject = ((Component)model).gameObject;
		val3.icon = Icon(Copper);
		val3.baseSkins = Array.Empty<SkinDef>();
		SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val4).name = "RodaniusTimpanistDefaultParams";
		val4.rendererInfos = array;
		val4.gameObjectActivations = Array.Empty<GameObjectActivation>();
		val4.meshReplacements = Array.Empty<MeshReplacement>();
		val4.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
		val4.minionSkinReplacements = Array.Empty<MinionSkinReplacement>();
		val4.lightReplacements = Array.Empty<LightInfo>();
		val3.skinDefParams = val4;
		val3.optimizedSkinDefParams = val4;
		(((Component)model).GetComponent<ModelSkinController>() ?? ((Component)model).gameObject.AddComponent<ModelSkinController>()).skins = (SkinDef[])(object)new SkinDef[1] { val3 };
		if (!flag)
		{
			((Component)val).gameObject.AddComponent<GrayboxMotion>();
		}
		ChildLocator component3 = ((Component)model).GetComponent<ChildLocator>();
		List<NameTransformPair> list = new List<NameTransformPair>();
		Transform[] componentsInChildren5 = ((Component)val).GetComponentsInChildren<Transform>();
		foreach (Transform val5 in componentsInChildren5)
		{
			list.Add(new NameTransformPair
			{
				name = ((Object)val5).name,
				transform = val5
			});
		}
		typeof(ChildLocator).GetField("transformPairs", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(component3, list.ToArray());
	}

	public static void BuildVisual(Transform root, Material template)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: 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_01e9: 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_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0333: Unknown result type (might be due to invalid IL or missing references)
		//IL_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_0383: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0410: Unknown result type (might be due to invalid IL or missing references)
		//IL_0424: Unknown result type (might be due to invalid IL or missing references)
		//IL_0446: Unknown result type (might be due to invalid IL or missing references)
		//IL_045a: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0490: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_051f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0533: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_057b: Unknown result type (might be due to invalid IL or missing references)
		//IL_058f: Unknown result type (might be due to invalid IL or missing references)
		//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0616: Unknown result type (might be due to invalid IL or missing references)
		//IL_062a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0657: Unknown result type (might be due to invalid IL or missing references)
		//IL_066b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0698: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a82: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a6c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a56: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0705: Unknown result type (might be due to invalid IL or missing references)
		//IL_072e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0748: Unknown result type (might be due to invalid IL or missing references)
		//IL_0775: Unknown result type (might be due to invalid IL or missing references)
		//IL_0789: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_081a: Unknown result type (might be due to invalid IL or missing references)
		//IL_082e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0853: Unknown result type (might be due to invalid IL or missing references)
		//IL_0867: Unknown result type (might be due to invalid IL or missing references)
		//IL_0893: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_08f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_090f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0935: Unknown result type (might be due to invalid IL or missing references)
		//IL_093a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0944: Unknown result type (might be due to invalid IL or missing references)
		Material mat = Material(template, Bay);
		Material mat2 = Material(template, Black);
		Material mat3 = Material(template, Metal);
		Material mat4 = Material(template, Copper);
		Material mat5 = Material(template, Ivory);
		Material mat6 = Material(template, Green);
		Part(root, "HorseTorso", (PrimitiveT