Decompiled source of BiomeCreatureSpeedModifier v1.5.2

BepInEx/plugins/BiomeCreatureSpeedModifier.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimDeerSpeed")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValheimDeerSpeed")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("dcfa2116-3b7e-4cb3-a9d2-88ee2a6a8895")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("ken.valheim.creaturespeed", "Biome Creature Speed Modifier", "1.5.2")]
public class CreatureSpeedMod : BaseUnityPlugin
{
	private class CreatureData
	{
		public float BaseRun;

		public float BaseWalk;

		public float BaseAttackValue;

		public ConfigEntry<float> MoveSpeed;

		public ConfigEntry<float> AttackSpeed;
	}

	[CompilerGenerated]
	private sealed class <Initialize>d__3 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public CreatureSpeedMod <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <Initialize>d__3(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			int num = <>1__state;
			CreatureSpeedMod creatureSpeedMod = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if ((Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null)
			{
				<>2__current = null;
				<>1__state = 1;
				return true;
			}
			creatureSpeedMod.RegisterAllCreatures();
			creatureSpeedMod.ApplyAll();
			((BaseUnityPlugin)creatureSpeedMod).Logger.LogInfo((object)$"Creature Speed Modifier loaded ({creatureSpeedMod.creatures.Count} creatures)");
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private readonly Dictionary<string, CreatureData> creatures = new Dictionary<string, CreatureData>();

	private void Awake()
	{
		((MonoBehaviour)this).StartCoroutine(Initialize());
	}

	[IteratorStateMachine(typeof(<Initialize>d__3))]
	private IEnumerator Initialize()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <Initialize>d__3(0)
		{
			<>4__this = this
		};
	}

	private void RegisterAllCreatures()
	{
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Expected O, but got Unknown
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Expected O, but got Unknown
		foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				continue;
			}
			Character component = prefab.GetComponent<Character>();
			if ((Object)(object)component == (Object)null || component.IsPlayer())
			{
				continue;
			}
			string prefabName = ((Object)prefab).name;
			if (!creatures.ContainsKey(prefabName))
			{
				string text = (component.m_boss ? "Bosses" : "Creatures");
				ConfigEntry<float> val = ((BaseUnityPlugin)this).Config.Bind<float>(text, prefabName + "MoveSpeed", 1f, new ConfigDescription("Movement speed multiplier for " + prefabName, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
				ConfigEntry<float> val2 = ((BaseUnityPlugin)this).Config.Bind<float>(text, prefabName + "AttackSpeed", 1f, new ConfigDescription("Attack speed multiplier for " + prefabName + "\nHigher = more frequent attacks (if supported)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
				CreatureData value = new CreatureData
				{
					MoveSpeed = val,
					AttackSpeed = val2
				};
				creatures[prefabName] = value;
				val.SettingChanged += delegate
				{
					ApplyCreature(prefabName);
				};
				val2.SettingChanged += delegate
				{
					ApplyCreature(prefabName);
				};
			}
		}
	}

	private void ApplyAll()
	{
		foreach (string key in creatures.Keys)
		{
			ApplyCreature(key);
		}
	}

	private void ApplyCreature(string prefabName)
	{
		GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
		if ((Object)(object)prefab == (Object)null)
		{
			return;
		}
		Character component = prefab.GetComponent<Character>();
		if (!((Object)(object)component == (Object)null))
		{
			CreatureData creatureData = creatures[prefabName];
			if (creatureData.BaseRun == 0f && creatureData.BaseWalk == 0f)
			{
				creatureData.BaseRun = component.m_runSpeed;
				creatureData.BaseWalk = component.m_walkSpeed;
			}
			component.m_runSpeed = creatureData.BaseRun * creatureData.MoveSpeed.Value;
			component.m_walkSpeed = creatureData.BaseWalk * creatureData.MoveSpeed.Value;
			ApplyAttackSpeed(component, creatureData);
		}
	}

	private void ApplyAttackSpeed(Character character, CreatureData data)
	{
		MonoBehaviour component = (MonoBehaviour)(object)((Component)character).GetComponent<MonsterAI>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		string[] array = new string[3] { "m_attackInterval", "m_attackCooldown", "m_attackTimer" };
		foreach (string name in array)
		{
			FieldInfo field = ((object)component).GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null) && !(field.FieldType != typeof(float)))
			{
				float baseAttackValue = (float)field.GetValue(component);
				if (data.BaseAttackValue == 0f)
				{
					data.BaseAttackValue = baseAttackValue;
				}
				float num = Mathf.Max(0.01f, data.AttackSpeed.Value);
				field.SetValue(component, data.BaseAttackValue / num);
				break;
			}
		}
	}
}