Decompiled source of Camels v1.0.0

plugins/CamelMod.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

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

internal static class CamelAsset
{
	internal class BoneDef
	{
		public string Name;

		public int Parent;

		public Vector3 Pos;

		public Quaternion Rot;

		public string Path;
	}

	internal static BoneDef[] Bones;

	internal static Mesh Mesh;

	internal static Texture2D Texture;

	internal static readonly List<AnimationClip> Clips = new List<AnimationClip>();

	internal static bool Loaded;

	private static readonly string[] Props = new string[7] { "localPosition.x", "localPosition.y", "localPosition.z", "localRotation.x", "localRotation.y", "localRotation.z", "localRotation.w" };

	internal static void Load(string dir)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: 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_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Expected O, but got Unknown
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_0285: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Expected O, but got Unknown
		try
		{
			using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(Path.Combine(dir, "camel.bytes"))))
			{
				if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "CAML")
				{
					throw new Exception("camel.bytes: bad header");
				}
				binaryReader.ReadInt32();
				int num = binaryReader.ReadInt32();
				Bones = new BoneDef[num];
				for (int i = 0; i < num; i++)
				{
					BoneDef boneDef = new BoneDef
					{
						Name = ReadStr(binaryReader),
						Parent = binaryReader.ReadInt32(),
						Pos = ReadV3(binaryReader),
						Rot = ReadQ(binaryReader)
					};
					boneDef.Path = ((boneDef.Parent < 0) ? boneDef.Name : (Bones[boneDef.Parent].Path + "/" + boneDef.Name));
					Bones[i] = boneDef;
				}
				int num2 = binaryReader.ReadInt32();
				Vector3[] array = (Vector3[])(object)new Vector3[num2];
				Vector3[] array2 = (Vector3[])(object)new Vector3[num2];
				Vector2[] array3 = (Vector2[])(object)new Vector2[num2];
				BoneWeight[] array4 = (BoneWeight[])(object)new BoneWeight[num2];
				for (int j = 0; j < num2; j++)
				{
					array[j] = ReadV3(binaryReader);
					array2[j] = ReadV3(binaryReader);
					array3[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
					BoneWeight val = default(BoneWeight);
					((BoneWeight)(ref val)).boneIndex0 = binaryReader.ReadInt32();
					((BoneWeight)(ref val)).weight0 = binaryReader.ReadSingle();
					((BoneWeight)(ref val)).boneIndex1 = binaryReader.ReadInt32();
					((BoneWeight)(ref val)).weight1 = binaryReader.ReadSingle();
					((BoneWeight)(ref val)).boneIndex2 = binaryReader.ReadInt32();
					((BoneWeight)(ref val)).weight2 = binaryReader.ReadSingle();
					((BoneWeight)(ref val)).boneIndex3 = binaryReader.ReadInt32();
					((BoneWeight)(ref val)).weight3 = binaryReader.ReadSingle();
					array4[j] = val;
				}
				int num3 = binaryReader.ReadInt32();
				int[] array5 = new int[num3];
				for (int k = 0; k < num3; k++)
				{
					array5[k] = binaryReader.ReadInt32();
				}
				Mesh = new Mesh
				{
					name = "CamelMesh"
				};
				Mesh.vertices = array;
				Mesh.normals = array2;
				Mesh.uv = array3;
				Mesh.boneWeights = array4;
				Mesh.triangles = array5;
				Matrix4x4[] array6 = (Matrix4x4[])(object)new Matrix4x4[num];
				Matrix4x4[] array7 = (Matrix4x4[])(object)new Matrix4x4[num];
				for (int l = 0; l < num; l++)
				{
					Matrix4x4 val2 = Matrix4x4.TRS(Bones[l].Pos, Bones[l].Rot, Vector3.one);
					array6[l] = ((Bones[l].Parent < 0) ? val2 : (array6[Bones[l].Parent] * val2));
					array7[l] = ((Matrix4x4)(ref array6[l])).inverse;
				}
				Mesh.bindposes = array7;
				Mesh.RecalculateBounds();
				int num4 = binaryReader.ReadInt32();
				for (int m = 0; m < num4; m++)
				{
					string name = ReadStr(binaryReader);
					float fps = binaryReader.ReadSingle();
					bool loop = binaryReader.ReadInt32() != 0;
					int num5 = binaryReader.ReadInt32();
					float[,,] array8 = new float[num5, num, 7];
					for (int n = 0; n < num5; n++)
					{
						for (int num6 = 0; num6 < num; num6++)
						{
							for (int num7 = 0; num7 < 7; num7++)
							{
								array8[n, num6, num7] = binaryReader.ReadSingle();
							}
						}
					}
					Clips.Add(MakeClip(name, fps, loop, num5, num, array8));
				}
			}
			Texture = new Texture2D(2, 2, (TextureFormat)4, true)
			{
				name = "camel"
			};
			ImageConversion.LoadImage(Texture, File.ReadAllBytes(Path.Combine(dir, "camel.png")));
			((Texture)Texture).anisoLevel = 4;
			Loaded = true;
			CamelPlugin.Log.LogInfo((object)$"Camel asset: {Bones.Length} bones, {Mesh.vertexCount} verts, {Mesh.triangles.Length / 3} tris, {Clips.Count} clips, texture {((Texture)Texture).width}x{((Texture)Texture).height}");
		}
		catch (Exception ex)
		{
			CamelPlugin.Log.LogError((object)("Camel asset load failed: " + ex));
		}
	}

	private static AnimationClip MakeClip(string name, float fps, bool loop, int frames, int nb, float[,,] data)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Expected O, but got Unknown
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		AnimationClip val = new AnimationClip
		{
			name = name,
			legacy = true,
			frameRate = fps
		};
		val.wrapMode = (WrapMode)(loop ? 2 : 8);
		for (int i = 0; i < nb; i++)
		{
			for (int j = 0; j < 7; j++)
			{
				Keyframe[] array = (Keyframe[])(object)new Keyframe[frames];
				for (int k = 0; k < frames; k++)
				{
					int num = k - 1;
					int num2 = k + 1;
					if (loop)
					{
						if (num < 0)
						{
							num = frames - 2;
						}
						if (num2 > frames - 1)
						{
							num2 = 1;
						}
					}
					else
					{
						if (num < 0)
						{
							num = 0;
						}
						if (num2 > frames - 1)
						{
							num2 = frames - 1;
						}
					}
					int num3 = num2 - num;
					if (num3 <= 0)
					{
						num3 += frames - 1;
					}
					float num4 = (data[num2, i, j] - data[num, i, j]) * fps / (float)num3;
					array[k] = new Keyframe((float)k / fps, data[k, i, j], num4, num4);
				}
				val.SetCurve(Bones[i].Path, typeof(Transform), Props[j], new AnimationCurve(array));
			}
		}
		val.EnsureQuaternionContinuity();
		return val;
	}

	internal static GameObject Build(Material mat, Transform parent, out SkinnedMeshRenderer smr, out Animation anim)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0039: 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_00a2: Expected O, but got Unknown
		//IL_0106: 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_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("CamelModel");
		val.transform.SetParent(parent, false);
		Transform[] array = (Transform[])(object)new Transform[Bones.Length];
		for (int i = 0; i < Bones.Length; i++)
		{
			BoneDef boneDef = Bones[i];
			Transform transform = new GameObject(boneDef.Name).transform;
			transform.SetParent((boneDef.Parent < 0) ? val.transform : array[boneDef.Parent], false);
			transform.localPosition = boneDef.Pos;
			transform.localRotation = boneDef.Rot;
			array[i] = transform;
		}
		GameObject val2 = new GameObject("CamelMesh");
		val2.transform.SetParent(val.transform, false);
		smr = val2.AddComponent<SkinnedMeshRenderer>();
		smr.sharedMesh = Mesh;
		smr.bones = array;
		smr.rootBone = val.transform;
		((Renderer)smr).sharedMaterial = mat;
		smr.quality = (SkinQuality)4;
		smr.updateWhenOffscreen = false;
		((Renderer)smr).localBounds = new Bounds(new Vector3(0f, 1.4f, 0f), new Vector3(6f, 3.6f, 6f));
		anim = val.AddComponent<Animation>();
		anim.playAutomatically = false;
		anim.cullingType = (AnimationCullingType)1;
		foreach (AnimationClip clip in Clips)
		{
			anim.AddClip(clip, ((Object)clip).name);
		}
		anim.clip = ((Clips.Count > 0) ? Clips[0] : null);
		return val;
	}

	internal static Transform FindDeep(Transform t, string name)
	{
		if (((Object)t).name == name)
		{
			return t;
		}
		for (int i = 0; i < t.childCount; i++)
		{
			Transform val = FindDeep(t.GetChild(i), name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		return null;
	}

	private static string ReadStr(BinaryReader br)
	{
		return Encoding.UTF8.GetString(br.ReadBytes(br.ReadInt32()));
	}

	private static Vector3 ReadV3(BinaryReader br)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
	}

	private static Quaternion ReadQ(BinaryReader br)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		return new Quaternion(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
	}
}
public class CamelBrain : MonoBehaviour
{
	private const float WalkClipSpeed = 1.21f;

	private const float RunClipSpeed = 5.55f;

	private static readonly int s_eatingHash = StringExtensionMethods.GetStableHashCode("camel_eating");

	private Character m_character;

	private BaseAI m_ai;

	private ZNetView m_nview;

	private Animation m_anim;

	private string m_current = "";

	private Vector3 m_lastPos;

	private float m_speed;

	private bool m_moving;

	private bool m_eating;

	private float m_stillTime;

	private float m_nextDecision;

	private float m_eatUntil;

	public bool WantsToStayPut
	{
		get
		{
			if (m_eating && (Object)(object)m_ai != (Object)null)
			{
				return !m_ai.IsAlerted();
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		m_character = ((Component)this).GetComponent<Character>();
		m_ai = ((Component)this).GetComponent<BaseAI>();
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_anim = ((Component)this).GetComponentInChildren<Animation>();
		m_lastPos = ((Component)this).transform.position;
		m_nextDecision = Time.time + Random.Range(2f, 5f);
	}

	private void Start()
	{
		if (!((Object)(object)m_anim == (Object)null))
		{
			m_anim.Play("idle");
			AnimationState val = m_anim["idle"];
			if ((TrackedReference)(object)val != (TrackedReference)null)
			{
				val.time = Random.Range(0f, val.length);
			}
			m_current = "idle";
		}
	}

	private void Update()
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_0060: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_anim == (Object)null || (Object)(object)m_character == (Object)null || m_character.IsDead())
		{
			return;
		}
		float deltaTime = Time.deltaTime;
		if (deltaTime <= 0f)
		{
			return;
		}
		Vector3 position = ((Component)this).transform.position;
		Vector3 val = position - m_lastPos;
		val.y = 0f;
		m_lastPos = position;
		float num = ((Vector3)(ref val)).magnitude / deltaTime;
		if (num > 30f)
		{
			num = 0f;
		}
		m_speed = Mathf.Lerp(m_speed, num, 1f - Mathf.Exp((0f - deltaTime) * 8f));
		if (m_moving)
		{
			if (m_speed < 0.15f)
			{
				m_moving = false;
			}
		}
		else if (m_speed > 0.3f)
		{
			m_moving = true;
		}
		bool flag = (Object)(object)m_nview != (Object)null && m_nview.IsValid();
		if (flag && m_nview.IsOwner())
		{
			bool flag2 = (Object)(object)m_ai != (Object)null && m_ai.IsAlerted();
			if (m_moving || flag2)
			{
				m_stillTime = 0f;
				if (m_eating)
				{
					m_eating = false;
					m_nextDecision = Time.time + Random.Range(4f, 8f);
				}
			}
			else
			{
				m_stillTime += deltaTime;
			}
			if (!m_eating && m_stillTime > 1f && Time.time > m_nextDecision)
			{
				m_nextDecision = Time.time + Random.Range(3f, 6f);
				if (Random.value < 0.65f)
				{
					m_eating = true;
					m_eatUntil = Time.time + Random.Range(7f, 16f);
				}
			}
			if (m_eating && Time.time > m_eatUntil)
			{
				m_eating = false;
				m_nextDecision = Time.time + Random.Range(4f, 9f);
			}
			ZDO zDO = m_nview.GetZDO();
			if (zDO.GetBool(s_eatingHash, false) != m_eating)
			{
				zDO.Set(s_eatingHash, m_eating);
			}
		}
		else if (flag)
		{
			m_eating = m_nview.GetZDO().GetBool(s_eatingHash, false);
		}
		float speed = 1f;
		string text;
		if (m_moving && m_speed > 3f)
		{
			text = "run";
			speed = Mathf.Clamp(m_speed / 5.55f, 0.7f, 1.6f);
		}
		else if (m_moving)
		{
			text = "walk";
			speed = Mathf.Clamp(m_speed / 1.21f, 0.6f, 2.2f);
		}
		else
		{
			text = (m_eating ? "eat" : "idle");
		}
		if (text != m_current)
		{
			float num2 = ((text == "eat" || m_current == "eat") ? 0.9f : ((text == "run" || m_current == "run") ? 0.25f : 0.35f));
			m_anim.CrossFade(text, num2);
			m_current = text;
		}
		AnimationState val2 = m_anim[text];
		if ((TrackedReference)(object)val2 != (TrackedReference)null)
		{
			val2.speed = speed;
		}
	}
}
public class CamelDeath : MonoBehaviour
{
	private void Start()
	{
		Animation componentInChildren = ((Component)this).GetComponentInChildren<Animation>();
		if ((Object)(object)componentInChildren != (Object)null)
		{
			componentInChildren.Play("die");
		}
	}
}
internal static class CamelDebug
{
	internal static void Dump(GameObject go)
	{
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine("=== PREFAB " + ((Object)go).name);
		Walk(go.transform, 0, stringBuilder);
		Character component = go.GetComponent<Character>();
		if ((Object)(object)component != (Object)null)
		{
			stringBuilder.AppendFormat("Character: hp={0} speed={1} walk={2} run={3} turn={4} runTurn={5} tilt={6} faction={7} group={8} eye={9}\n", component.m_health, component.m_speed, component.m_walkSpeed, component.m_runSpeed, component.m_turnSpeed, component.m_runTurnSpeed, component.m_groundTilt, component.m_faction, component.m_group, ((Object)(object)component.m_eye != (Object)null) ? ((Object)component.m_eye).name : "null");
		}
		if ((Object)(object)component != (Object)null && component.m_deathEffects != null)
		{
			EffectData[] effectPrefabs = component.m_deathEffects.m_effectPrefabs;
			foreach (EffectData val in effectPrefabs)
			{
				stringBuilder.AppendLine("  deathEffect " + (((Object)(object)val.m_prefab != (Object)null) ? ((Object)val.m_prefab).name : "null"));
			}
		}
		BaseAI component2 = go.GetComponent<BaseAI>();
		if ((Object)(object)component2 != (Object)null)
		{
			stringBuilder.AppendFormat("AI {0}: view={1} hear={2} agent={3} moveInterval={4} moveRange={5} fleeRange={6} idleSoundInterval={7}\n", ((object)component2).GetType().Name, component2.m_viewRange, component2.m_hearRange, component2.m_pathAgentType, component2.m_randomMoveInterval, component2.m_randomMoveRange, component2.m_fleeRange, component2.m_idleSoundInterval);
		}
		CapsuleCollider component3 = go.GetComponent<CapsuleCollider>();
		if ((Object)(object)component3 != (Object)null)
		{
			stringBuilder.AppendFormat("Capsule r={0} h={1} c={2} dir={3}\n", component3.radius, component3.height, component3.center, component3.direction);
		}
		Rigidbody component4 = go.GetComponent<Rigidbody>();
		if ((Object)(object)component4 != (Object)null)
		{
			stringBuilder.AppendFormat("Rigidbody mass={0} kinematic={1}\n", component4.mass, component4.isKinematic);
		}
		Ragdoll component5 = go.GetComponent<Ragdoll>();
		if ((Object)(object)component5 != (Object)null)
		{
			stringBuilder.AppendFormat("Ragdoll ttl={0} drop={1} float={2} mainModel={3} lootJoint={4}\n", component5.m_ttl, component5.m_dropItems, component5.m_float, ((Object)(object)component5.m_mainModel != (Object)null) ? ((Object)component5.m_mainModel).name : "null", ((Object)(object)component5.m_lootSpawnJoint != (Object)null) ? ((Object)component5.m_lootSpawnJoint).name : "null");
		}
		Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val2 in componentsInChildren)
		{
			Material sharedMaterial = val2.sharedMaterial;
			stringBuilder.Append("Renderer ").Append(((Object)val2).name).Append(" shader=")
				.Append(((Object)(object)sharedMaterial != (Object)null) ? ((Object)sharedMaterial.shader).name : "null");
			if ((Object)(object)sharedMaterial != (Object)null)
			{
				stringBuilder.Append(" props:");
				int propertyCount = sharedMaterial.shader.GetPropertyCount();
				for (int j = 0; j < propertyCount; j++)
				{
					stringBuilder.Append(' ').Append(sharedMaterial.shader.GetPropertyName(j));
				}
			}
			stringBuilder.AppendLine();
		}
		CamelPlugin.Log.LogInfo((object)stringBuilder.ToString());
	}

	private static void Walk(Transform t, int depth, StringBuilder sb)
	{
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: 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)
		sb.Append(' ', depth * 2).Append(((Object)t).name).Append(" [");
		Component[] components = ((Component)t).GetComponents<Component>();
		foreach (Component val in components)
		{
			if ((Object)(object)val != (Object)null && !(val is Transform))
			{
				sb.Append(((object)val).GetType().Name).Append(' ');
			}
		}
		sb.Append("] pos=").Append(t.localPosition).Append(" rot=")
			.Append(t.localEulerAngles)
			.Append(" scale=")
			.Append(t.localScale)
			.AppendLine();
		if (depth < 3)
		{
			for (int j = 0; j < t.childCount; j++)
			{
				Walk(t.GetChild(j), depth + 1, sb);
			}
		}
	}
}
[BepInPlugin("rombi.camelmod", "Camel", "1.0.0")]
public class CamelPlugin : BaseUnityPlugin
{
	public const string Guid = "rombi.camelmod";

	public const string Version = "1.0.0";

	internal static ManualLogSource Log;

	internal static string Dir;

	internal static ConfigEntry<float> Health;

	internal static ConfigEntry<bool> SpawnEnabled;

	internal static ConfigEntry<bool> DebugDump;

	internal static ConfigEntry<bool> EnableConsole;

	private void Awake()
	{
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		Dir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		Health = ((BaseUnityPlugin)this).Config.Bind<float>("Camel", "Health", 300f, "Max health of a camel (deer 10, lox 1000).");
		SpawnEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "Enabled", true, "Camels spawn on their own in the Plains, like lox.");
		DebugDump = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DumpPrefabs", false, "Write details of the deer / lox prefabs to the BepInEx log once per game start.");
		EnableConsole = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableConsole", false, "Turn on the F5 console (same as the -console launch option), e.g. for 'spawn Camel'.");
		CamelAsset.Load(Dir);
		CamelSounds.Load(Dir);
		new Harmony("rombi.camelmod").PatchAll(Assembly.GetExecutingAssembly());
		Log.LogInfo((object)("Camel mod 1.0.0 loaded from " + Dir));
	}
}
[HarmonyPatch(typeof(ZNetScene), "Awake")]
internal static class Patch_ZNetScene_Awake
{
	private static void Postfix(ZNetScene __instance)
	{
		CamelPrefabs.Register(__instance);
	}
}
[HarmonyPatch(typeof(SpawnSystem), "Awake")]
internal static class Patch_SpawnSystem_Awake
{
	private static void Postfix(SpawnSystem __instance)
	{
		CamelPrefabs.AddSpawns(__instance);
	}
}
[HarmonyPatch(typeof(Localization), "SetupLanguage")]
internal static class Patch_Localization_SetupLanguage
{
	private static void Postfix(Localization __instance, string language)
	{
		CamelPrefabs.AddWords(__instance, language);
	}
}
[HarmonyPatch(typeof(Console), "Awake")]
internal static class Patch_Console_Awake
{
	private static void Postfix()
	{
		if (CamelPlugin.EnableConsole.Value)
		{
			Console.SetConsoleEnabled(true);
		}
	}
}
[HarmonyPatch(typeof(BaseAI), "IdleMovement")]
internal static class Patch_BaseAI_IdleMovement
{
	private static bool Prefix(BaseAI __instance)
	{
		CamelBrain component = ((Component)__instance).GetComponent<CamelBrain>();
		if ((Object)(object)component != (Object)null && component.WantsToStayPut)
		{
			__instance.StopMoving();
			return false;
		}
		return true;
	}
}
internal static class CamelPrefabs
{
	internal static GameObject Camel;

	internal static GameObject CamelRagdoll;

	private const float ModelOffsetZ = 0.45f;

	private static GameObject s_holder;

	private static SpawnSystemList s_spawnList;

	private static bool s_spawnLogged;

	private static readonly MethodInfo s_addWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);

	private static readonly MethodInfo s_memberwiseClone = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null);

	internal static void Register(ZNetScene zs)
	{
		if (!CamelAsset.Loaded)
		{
			return;
		}
		try
		{
			if ((Object)(object)Camel == (Object)null)
			{
				Create(zs);
			}
			if ((Object)(object)Camel == (Object)null)
			{
				return;
			}
			if ((Object)(object)CamelRagdoll != (Object)null)
			{
				AddPrefab(zs, CamelRagdoll);
			}
			foreach (GameObject prefab in CamelSounds.Prefabs)
			{
				if ((Object)(object)prefab.GetComponent<ZNetView>() != (Object)null)
				{
					AddPrefab(zs, prefab);
				}
			}
			AddPrefab(zs, Camel);
			if (Localization.instance != null)
			{
				AddWords(Localization.instance, Localization.instance.GetSelectedLanguage());
			}
			CamelPlugin.Log.LogInfo((object)"Camel prefab registered (spawn with: spawn Camel)");
		}
		catch (Exception ex)
		{
			CamelPlugin.Log.LogError((object)("Camel registration failed: " + ex));
		}
	}

	private static void AddPrefab(ZNetScene zs, GameObject go)
	{
		if (!zs.m_prefabs.Contains(go))
		{
			zs.m_prefabs.Add(go);
		}
		Traverse.Create((object)zs).Field("m_namedPrefabs").GetValue<Dictionary<int, GameObject>>()[StringExtensionMethods.GetStableHashCode(((Object)go).name)] = go;
	}

	private static void Create(ZNetScene zs)
	{
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Expected O, but got Unknown
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Expected O, but got Unknown
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		GameObject prefab = zs.GetPrefab("Deer");
		GameObject prefab2 = zs.GetPrefab("Lox");
		if ((Object)(object)prefab == (Object)null)
		{
			CamelPlugin.Log.LogError((object)"Deer prefab not found, camel not created");
			return;
		}
		Character component = prefab.GetComponent<Character>();
		GameObject val = null;
		EffectData[] effectPrefabs = component.m_deathEffects.m_effectPrefabs;
		foreach (EffectData val2 in effectPrefabs)
		{
			if ((Object)(object)val2.m_prefab != (Object)null && (Object)(object)val2.m_prefab.GetComponent<Ragdoll>() != (Object)null)
			{
				val = val2.m_prefab;
			}
		}
		if (CamelPlugin.DebugDump.Value)
		{
			CamelDebug.Dump(prefab);
			CamelDebug.Dump(val);
			CamelDebug.Dump(prefab2);
			CamelDebug.Dump(zs.GetPrefab("Goblin"));
		}
		s_holder = new GameObject("CamelMod_Prefabs");
		s_holder.SetActive(false);
		Object.DontDestroyOnLoad((Object)(object)s_holder);
		Material val3 = new Material(((Renderer)prefab.GetComponentInChildren<SkinnedMeshRenderer>(true)).sharedMaterial)
		{
			name = "CamelMat"
		};
		if (val3.HasProperty("_MainTex"))
		{
			val3.SetTexture("_MainTex", (Texture)(object)CamelAsset.Texture);
		}
		if (val3.HasProperty("_BumpMap"))
		{
			val3.SetTexture("_BumpMap", (Texture)null);
		}
		val3.DisableKeyword("_NORMALMAP");
		if (val3.HasProperty("_Color"))
		{
			val3.SetColor("_Color", Color.white);
		}
		CamelPlugin.Log.LogInfo((object)("Camel material based on shader " + ((Object)val3.shader).name));
		if ((Object)(object)val != (Object)null)
		{
			CamelRagdoll = MakeRagdoll(val, val3);
		}
		else
		{
			CamelPlugin.Log.LogWarning((object)"Deer ragdoll not found: camel will vanish on death without animation");
		}
		Camel = MakeCamel(prefab, prefab2, val3, zs);
	}

	private static GameObject MakeCamel(GameObject deer, GameObject lox, Material mat, ZNetScene zs)
	{
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: 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_021f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: 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_03ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c4: Expected O, but got Unknown
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: Expected O, but got Unknown
		GameObject val = Object.Instantiate<GameObject>(deer, s_holder.transform, false);
		((Object)val).name = "Camel";
		Character component = val.GetComponent<Character>();
		component.m_name = "$enemy_camel";
		component.m_group = "camel";
		component.m_health = CamelPlugin.Health.Value;
		component.m_walkSpeed = 1.2f;
		component.m_speed = 1.5f;
		component.m_runSpeed = 6.5f;
		component.m_turnSpeed = Mathf.Min(component.m_turnSpeed, 120f);
		component.m_runTurnSpeed = Mathf.Min(component.m_runTurnSpeed, 240f);
		Character val2 = (((Object)(object)lox != (Object)null) ? lox.GetComponent<Character>() : null);
		component.m_faction = (Faction)((!((Object)(object)val2 != (Object)null)) ? 7 : ((int)val2.m_faction));
		Transform val3 = val.transform.Find("Visual");
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = val.transform;
		}
		Renderer[] componentsInChildren = ((Component)val3).GetComponentsInChildren<Renderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
		}
		LevelEffects[] componentsInChildren2 = val.GetComponentsInChildren<LevelEffects>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
		}
		Animator[] componentsInChildren3 = val.GetComponentsInChildren<Animator>(true);
		for (int i = 0; i < componentsInChildren3.Length; i++)
		{
			componentsInChildren3[i].cullingMode = (AnimatorCullingMode)2;
		}
		SkinnedMeshRenderer smr;
		Animation anim;
		GameObject val4 = CamelAsset.Build(mat, val3, out smr, out anim);
		PlaceModel(val4.transform, val.transform);
		LODGroup component2 = ((Component)val3).GetComponent<LODGroup>();
		if ((Object)(object)component2 != (Object)null)
		{
			component2.SetLODs((LOD[])(object)new LOD[1]
			{
				new LOD(0.02f, (Renderer[])(object)new Renderer[1] { (Renderer)smr })
			});
			component2.RecalculateBounds();
		}
		Transform val5 = CamelAsset.FindDeep(val4.transform, "Head");
		if ((Object)(object)val5 != (Object)null)
		{
			component.m_eye = val5;
		}
		CapsuleCollider component3 = val.GetComponent<CapsuleCollider>();
		if ((Object)(object)component3 != (Object)null)
		{
			component3.direction = 1;
			component3.radius = 0.8f;
			component3.height = 2.5f;
			component3.center = new Vector3(0f, 1.25f, 0f);
		}
		Rigidbody component4 = val.GetComponent<Rigidbody>();
		Rigidbody val6 = (((Object)(object)lox != (Object)null) ? lox.GetComponent<Rigidbody>() : null);
		if ((Object)(object)component4 != (Object)null && (Object)(object)val6 != (Object)null)
		{
			component4.mass = val6.mass * 0.6f;
		}
		BaseAI component5 = val.GetComponent<BaseAI>();
		BaseAI val7 = (((Object)(object)lox != (Object)null) ? lox.GetComponent<BaseAI>() : null);
		if ((Object)(object)component5 != (Object)null)
		{
			if ((Object)(object)val7 != (Object)null)
			{
				component5.m_pathAgentType = val7.m_pathAgentType;
			}
			component5.m_randomMoveInterval = Mathf.Max(component5.m_randomMoveInterval, 8f);
			component5.m_randomMoveRange = Mathf.Max(component5.m_randomMoveRange, 14f);
		}
		CharacterDrop component6 = val.GetComponent<CharacterDrop>();
		if ((Object)(object)component6 != (Object)null)
		{
			component6.m_drops = new List<Drop>();
			AddDrop(component6, zs, "LoxMeat", 1, 2);
			AddDrop(component6, zs, "LoxPelt", 1, 1);
		}
		if ((Object)(object)CamelRagdoll != (Object)null)
		{
			List<EffectData> list = new List<EffectData>();
			EffectData[] effectPrefabs = component.m_deathEffects.m_effectPrefabs;
			foreach (EffectData val8 in effectPrefabs)
			{
				if ((Object)(object)val8.m_prefab != (Object)null && (Object)(object)val8.m_prefab.GetComponent<Ragdoll>() != (Object)null)
				{
					EffectData val9 = (EffectData)s_memberwiseClone.Invoke(val8, null);
					val9.m_prefab = CamelRagdoll;
					list.Add(val9);
				}
				else
				{
					list.Add(val8);
				}
			}
			component.m_deathEffects = new EffectList
			{
				m_effectPrefabs = list.ToArray()
			};
		}
		CamelSounds.Apply(val, s_holder.transform);
		val.AddComponent<CamelBrain>();
		return val;
	}

	private static GameObject MakeRagdoll(GameObject src, Material mat)
	{
		//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)
		GameObject val = Object.Instantiate<GameObject>(src, s_holder.transform, false);
		((Object)val).name = "Camel_ragdoll";
		for (int num = val.transform.childCount - 1; num >= 0; num--)
		{
			Object.DestroyImmediate((Object)(object)((Component)val.transform.GetChild(num)).gameObject);
		}
		Joint[] components = val.GetComponents<Joint>();
		for (int i = 0; i < components.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)components[i]);
		}
		Collider[] components2 = val.GetComponents<Collider>();
		for (int i = 0; i < components2.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)components2[i]);
		}
		Rigidbody component = val.GetComponent<Rigidbody>();
		if ((Object)(object)component != (Object)null)
		{
			component.isKinematic = true;
			component.useGravity = false;
		}
		Ragdoll component2 = val.GetComponent<Ragdoll>();
		component2.m_mainModel = null;
		component2.m_float = false;
		component2.m_ttl = Mathf.Max(component2.m_ttl, 8f);
		SkinnedMeshRenderer smr;
		Animation anim;
		GameObject val2 = CamelAsset.Build(mat, val.transform, out smr, out anim);
		PlaceModel(val2.transform, val.transform);
		LODGroup component3 = val.GetComponent<LODGroup>();
		if ((Object)(object)component3 != (Object)null)
		{
			component3.SetLODs((LOD[])(object)new LOD[1]
			{
				new LOD(0.02f, (Renderer[])(object)new Renderer[1] { (Renderer)smr })
			});
			component3.RecalculateBounds();
		}
		Transform val3 = CamelAsset.FindDeep(val2.transform, "Spine");
		if ((Object)(object)val3 != (Object)null)
		{
			component2.m_lootSpawnJoint = ((Component)val3).gameObject;
		}
		val.AddComponent<CamelDeath>();
		return val;
	}

	private static void PlaceModel(Transform model, Transform owner)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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_0062: 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)
		Vector3 lossyScale = model.parent.lossyScale;
		model.localScale = new Vector3(1f / lossyScale.x, 1f / lossyScale.y, 1f / lossyScale.z);
		model.SetPositionAndRotation(owner.TransformPoint(0f, 0f, 0.45f / Mathf.Max(0.0001f, owner.lossyScale.z)), owner.rotation);
	}

	private static void AddDrop(CharacterDrop cd, ZNetScene zs, string item, int min, int max)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: 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_0048: 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_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		GameObject prefab = zs.GetPrefab(item);
		if ((Object)(object)prefab == (Object)null)
		{
			CamelPlugin.Log.LogWarning((object)("Drop item not found: " + item));
			return;
		}
		cd.m_drops.Add(new Drop
		{
			m_prefab = prefab,
			m_amountMin = min,
			m_amountMax = max,
			m_chance = 1f,
			m_onePerPlayer = false,
			m_levelMultiplier = true
		});
	}

	internal static void AddSpawns(SpawnSystem ss)
	{
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Expected O, but got Unknown
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Camel == (Object)null || !CamelPlugin.SpawnEnabled.Value)
		{
			return;
		}
		try
		{
			if ((Object)(object)s_spawnList == (Object)null)
			{
				SpawnData val = null;
				foreach (SpawnSystemList spawnList in ss.m_spawnLists)
				{
					foreach (SpawnData spawner in spawnList.m_spawners)
					{
						if (val == null && spawner.m_enabled && (Object)(object)spawner.m_prefab != (Object)null && ((Object)spawner.m_prefab).name == "Lox")
						{
							val = spawner;
						}
					}
				}
				if (val == null)
				{
					if (!s_spawnLogged)
					{
						CamelPlugin.Log.LogWarning((object)"No Lox spawn entry found yet");
					}
					s_spawnLogged = true;
					return;
				}
				SpawnData val2 = val.Clone();
				val2.m_name = "Camel";
				val2.m_prefab = Camel;
				val2.m_enabled = true;
				GameObject val3 = new GameObject("CamelMod_SpawnList");
				Object.DontDestroyOnLoad((Object)val3);
				s_spawnList = val3.AddComponent<SpawnSystemList>();
				s_spawnList.m_spawners = new List<SpawnData> { val2 };
				CamelPlugin.Log.LogInfo((object)$"Camel spawns copied from Lox: biome={val2.m_biome} max={val2.m_maxSpawned} interval={val2.m_spawnInterval} chance={val2.m_spawnChance} group={val2.m_groupSizeMin}-{val2.m_groupSizeMax} day={val2.m_spawnAtDay} night={val2.m_spawnAtNight} levels={val2.m_minLevel}-{val2.m_maxLevel}");
			}
			if (!ss.m_spawnLists.Contains(s_spawnList))
			{
				ss.m_spawnLists.Add(s_spawnList);
			}
		}
		catch (Exception ex)
		{
			CamelPlugin.Log.LogError((object)("Camel spawn setup failed: " + ex));
		}
	}

	internal static void AddWords(Localization loc, string language)
	{
		if (loc != null && !(s_addWord == null))
		{
			bool flag = language == "Russian";
			Word(loc, "enemy_camel", flag ? "Верблюд" : "Camel");
			Word(loc, "caption_camel_idle", flag ? "Верблюд ворчит" : "Camel grumbles");
			Word(loc, "caption_camel_alert", flag ? "Верблюд тревожно стонет" : "Camel groans in alarm");
			Word(loc, "caption_camel_hit", flag ? "Верблюд вскрикивает" : "Camel cries out");
			Word(loc, "caption_camel_death", flag ? "Верблюд ревёт" : "Camel roars");
		}
	}

	private static void Word(Localization loc, string key, string text)
	{
		s_addWord.Invoke(loc, new object[2] { key, text });
	}
}
internal static class CamelSounds
{
	private static readonly Dictionary<string, List<AudioClip>> s_clips = new Dictionary<string, List<AudioClip>>();

	internal static readonly List<GameObject> Prefabs = new List<GameObject>();

	private static readonly MethodInfo s_memberwiseClone = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null);

	internal static void Load(string dir)
	{
		string path = Path.Combine(dir, "sounds");
		if (!Directory.Exists(path))
		{
			CamelPlugin.Log.LogWarning((object)"No sounds folder, camels keep deer sounds");
			return;
		}
		string[] files = Directory.GetFiles(path, "*.wav");
		foreach (string text in files)
		{
			try
			{
				AudioClip clip = LoadWav(text);
				string? fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
				Add(fileNameWithoutExtension.Split('_')[0], clip);
				if (fileNameWithoutExtension.StartsWith("idle_grunt"))
				{
					Add("hit", clip);
				}
			}
			catch (Exception ex)
			{
				CamelPlugin.Log.LogWarning((object)("Sound " + text + " skipped: " + ex.Message));
			}
		}
		StringBuilder stringBuilder = new StringBuilder("Camel sounds:");
		foreach (KeyValuePair<string, List<AudioClip>> s_clip in s_clips)
		{
			stringBuilder.Append(' ').Append(s_clip.Key).Append('=')
				.Append(s_clip.Value.Count);
		}
		CamelPlugin.Log.LogInfo((object)stringBuilder.ToString());
	}

	private static void Add(string role, AudioClip clip)
	{
		if (!s_clips.TryGetValue(role, out var value))
		{
			value = (s_clips[role] = new List<AudioClip>());
		}
		value.Add(clip);
	}

	private static AudioClip LoadWav(string path)
	{
		byte[] array = File.ReadAllBytes(path);
		if (Encoding.ASCII.GetString(array, 0, 4) != "RIFF" || Encoding.ASCII.GetString(array, 8, 4) != "WAVE")
		{
			throw new Exception("not a WAV file");
		}
		int i = 12;
		int num = 1;
		int num2 = 44100;
		int num3 = 16;
		int num4 = -1;
		int num5 = 0;
		int num6;
		for (; i + 8 <= array.Length; i += 8 + num6 + (num6 & 1))
		{
			string text = Encoding.ASCII.GetString(array, i, 4);
			num6 = BitConverter.ToInt32(array, i + 4);
			if (text == "fmt ")
			{
				num = BitConverter.ToInt16(array, i + 10);
				num2 = BitConverter.ToInt32(array, i + 12);
				num3 = BitConverter.ToInt16(array, i + 22);
			}
			else if (text == "data")
			{
				num4 = i + 8;
				num5 = Math.Min(num6, array.Length - num4);
				break;
			}
		}
		if (num3 != 16 || num4 < 0)
		{
			throw new Exception("only 16-bit PCM WAV is supported");
		}
		int num7 = num5 / 2;
		float[] array2 = new float[num7];
		for (int j = 0; j < num7; j++)
		{
			array2[j] = (float)BitConverter.ToInt16(array, num4 + j * 2) / 32768f;
		}
		AudioClip obj = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num7 / num, num, num2, false);
		obj.SetData(array2, 0);
		return obj;
	}

	internal static void Apply(GameObject camel, Transform holder)
	{
		if (s_clips.Count == 0)
		{
			return;
		}
		Character component = camel.GetComponent<Character>();
		BaseAI component2 = camel.GetComponent<BaseAI>();
		GameObject val = null;
		EffectList[] array = (EffectList[])(object)new EffectList[4]
		{
			((Object)(object)component2 != (Object)null) ? component2.m_idleSound : null,
			((Object)(object)component2 != (Object)null) ? component2.m_alertedEffects : null,
			((Object)(object)component != (Object)null) ? component.m_hitEffects : null,
			((Object)(object)component != (Object)null) ? component.m_deathEffects : null
		};
		foreach (EffectList list in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				val = FindSfx(list);
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			CamelPlugin.Log.LogWarning((object)"No deer sound prefab found to copy, camels keep deer sounds");
			return;
		}
		if ((Object)(object)component2 != (Object)null)
		{
			component2.m_idleSound = Swap(component2.m_idleSound, "idle", val, holder, 0.9f, 1.08f);
			component2.m_alertedEffects = Swap(component2.m_alertedEffects, "alert", val, holder, 0.95f, 1.05f);
		}
		if ((Object)(object)component != (Object)null)
		{
			component.m_hitEffects = Swap(component.m_hitEffects, "hit", val, holder, 1.08f, 1.22f);
			component.m_critHitEffects = Swap(component.m_critHitEffects, "hit", val, holder, 1.08f, 1.22f);
			component.m_deathEffects = Swap(component.m_deathEffects, "death", val, holder, 0.96f, 1f);
		}
	}

	private static GameObject FindSfx(EffectList list)
	{
		if (list == null || list.m_effectPrefabs == null)
		{
			return null;
		}
		EffectData[] effectPrefabs = list.m_effectPrefabs;
		foreach (EffectData val in effectPrefabs)
		{
			if (val != null && (Object)(object)val.m_prefab != (Object)null && (Object)(object)val.m_prefab.GetComponent<ZSFX>() != (Object)null)
			{
				return val.m_prefab;
			}
		}
		return null;
	}

	private static EffectList Swap(EffectList list, string role, GameObject fallback, Transform holder, float minPitch, float maxPitch)
	{
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Expected O, but got Unknown
		//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_0153: Expected O, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Expected O, but got Unknown
		if (!s_clips.TryGetValue(role, out var value) || value.Count == 0)
		{
			return list;
		}
		Array obj = ((list != null && list.m_effectPrefabs != null) ? ((Array)list.m_effectPrefabs) : ((Array)new EffectData[0]));
		GameObject val = FindSfx(list);
		GameObject prefab = MakeSfx(((Object)(object)val != (Object)null) ? val : fallback, "sfx_camel_" + role, value.ToArray(), minPitch, maxPitch, holder);
		List<EffectData> list2 = new List<EffectData>();
		bool flag = false;
		EffectData[] array = (EffectData[])obj;
		foreach (EffectData val2 in array)
		{
			if (val2 != null && (Object)(object)val2.m_prefab != (Object)null && (Object)(object)val2.m_prefab.GetComponent<ZSFX>() != (Object)null)
			{
				if (!flag)
				{
					EffectData val3 = (EffectData)s_memberwiseClone.Invoke(val2, null);
					val3.m_prefab = prefab;
					list2.Add(val3);
					flag = true;
				}
			}
			else
			{
				list2.Add(val2);
			}
		}
		if (!flag)
		{
			list2.Add(new EffectData
			{
				m_prefab = prefab,
				m_enabled = true
			});
		}
		CamelPlugin.Log.LogInfo((object)string.Format("Camel sound {0}: {1} clips (copied from {2})", role, value.Count, ((Object)(object)val != (Object)null) ? ((Object)val).name : (((Object)fallback).name + " [fallback]")));
		return new EffectList
		{
			m_effectPrefabs = list2.ToArray()
		};
	}

	private static GameObject MakeSfx(GameObject template, string name, AudioClip[] clips, float minPitch, float maxPitch, Transform holder)
	{
		foreach (GameObject prefab in Prefabs)
		{
			if (((Object)prefab).name == name)
			{
				return prefab;
			}
		}
		GameObject val = Object.Instantiate<GameObject>(template, holder, false);
		((Object)val).name = name;
		ZSFX component = val.GetComponent<ZSFX>();
		component.m_audioClips = clips;
		component.m_minPitch = minPitch;
		component.m_maxPitch = maxPitch;
		component.m_closedCaptionToken = "$caption_" + name.Substring(4);
		component.m_secondaryCaptionToken = "";
		component.m_hash = StringExtensionMethods.GetStableHashCode(name);
		AudioSource component2 = val.GetComponent<AudioSource>();
		if ((Object)(object)component2 != (Object)null && component2.maxDistance < 35f)
		{
			component2.maxDistance = 35f;
		}
		Prefabs.Add(val);
		return val;
	}
}