using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EnemySpeedUp { [BepInPlugin("REPOJP.EnemySpeedUp", "EnemySpeedUp", "4.0.0")] public sealed class EnemySpeedUpV2_AllVisuals : BaseUnityPlugin { [CompilerGenerated] private sealed class d__15 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemySpeedUpV2_AllVisuals <>4__this; private float 5__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } if (EnemySpeedUpConfig.Enable != null && EnemySpeedUpConfig.Enable.Value) { LateSpawnSupport.Apply(); } 5__1 = 1f; if (EnemySpeedUpConfig.LateSpawnSupportIntervalSeconds != null) { 5__1 = Mathf.Clamp(EnemySpeedUpConfig.LateSpawnSupportIntervalSeconds.Value, 0.25f, 5f); } <>2__current = (object)new WaitForSeconds(5__1); <>1__state = 2; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "REPOJP.EnemySpeedUp"; public const string PluginName = "EnemySpeedUp"; public const string PluginVersion = "4.0.0"; private Harmony _harmony; private Coroutine _lateSpawnSupportCoroutine; private float _reloadAt; private bool _reloadQueued; internal static EnemySpeedUpV2_AllVisuals Instance { get; private set; } internal static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger; private void Awake() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown Instance = this; ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); EnemySpeedUpConfig.Bind(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged; _harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); _harmony.PatchAll(); DynamicEnemyAnimPatcher.PatchAll(_harmony); DynamicEnemyTimerPatcher.PatchAll(_harmony); RuntimeCache.Rebuild(); _lateSpawnSupportCoroutine = ((MonoBehaviour)this).StartCoroutine(CoLateSpawnSupport()); Log.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} loaded"); } private void OnDestroy() { try { if (((BaseUnityPlugin)this).Config != null) { ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; } } catch { } try { if (_lateSpawnSupportCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_lateSpawnSupportCoroutine); _lateSpawnSupportCoroutine = null; } } catch { } try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } } [IteratorStateMachine(typeof(d__15))] private IEnumerator CoLateSpawnSupport() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__15(0) { <>4__this = this }; } private void Update() { if (_reloadQueued && !(Time.unscaledTime - _reloadAt < 0.25f)) { _reloadQueued = false; RuntimeCache.Rebuild(); ApplyUtil.ReapplyAll(); if (EnemySpeedUpConfig.LogLevel.Value >= EnemySpeedUpLogLevel.Info) { RateLog.Info("ConfigReload", "Config reloaded. 設定再読み込み完了"); } } } private void OnSettingChanged(object sender, SettingChangedEventArgs e) { _reloadAt = Time.unscaledTime; _reloadQueued = true; } } internal enum EnemySpeedUpLogLevel { Off, Error, Warn, Info, Debug } [Flags] internal enum EnemySpeedUpDamageRageAffects { None = 0, MoveNav = 1, MoveRb = 2, Anim = 4 } internal enum EnemySpeedUpDamageRageMode { MissingHpRatio, CurrentHpRatio } internal static class EnemySpeedUpConfig { internal static ConfigEntry Enable; internal static ConfigEntry NavMoveMultiplier; internal static ConfigEntry NavAttackMoveMultiplier; internal static ConfigEntry RbMoveMultiplier; internal static ConfigEntry RbAttackMoveMultiplier; internal static ConfigEntry AnimationSpeedMultiplier; internal static ConfigEntry EnableEnemyTimerAcceleration; internal static ConfigEntry EnemyTimerMultiplier; internal static ConfigEntry EnableLateSpawnSupport; internal static ConfigEntry LateSpawnSupportIntervalSeconds; internal static ConfigEntry ExcludedEnemies; internal static ConfigEntry DamageRageMode; internal static ConfigEntry DamageRageMaxMultiplier; internal static ConfigEntry DamageRageAffects; internal static ConfigEntry LogLevel; internal static ConfigEntry LogAppliedMultipliers; internal static void Bind(ConfigFile config) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Expected O, but got Unknown Enable = config.Bind("General", "Enable", true, "Enable or disable the mod. MOD有効/無効"); NavMoveMultiplier = config.Bind("Move", "NavMoveMultiplier", 2f, new ConfigDescription("NavMesh normal movement multiplier. NavMesh通常移動倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 100f), Array.Empty())); NavAttackMoveMultiplier = config.Bind("Move", "NavAttackMoveMultiplier", 2f, new ConfigDescription("NavMesh attack movement multiplier. NavMesh攻撃中移動倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 100f), Array.Empty())); RbMoveMultiplier = config.Bind("Move", "RbMoveMultiplier", 2f, new ConfigDescription("Rigidbody normal movement multiplier. Rigidbody通常移動倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 100f), Array.Empty())); RbAttackMoveMultiplier = config.Bind("Move", "RbAttackMoveMultiplier", 2f, new ConfigDescription("Rigidbody attack movement multiplier. Rigidbody攻撃中移動倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 100f), Array.Empty())); AnimationSpeedMultiplier = config.Bind("Anim", "AnimationSpeedMultiplier", 1f, new ConfigDescription("Global animation and visual speed multiplier for all enemy states. 敵の全状態の見た目速度倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), Array.Empty())); EnableEnemyTimerAcceleration = config.Bind("State", "EnableAttackIntervalAcceleration", false, "Enable enemy internal timer acceleration for attack interval, wait, cooldown, delay fields.スタン系を除いた攻撃間隔、待機、クールダウン、ディレイ系内部タイマー加速の有効化"); EnemyTimerMultiplier = config.Bind("State", "EnemyTimerMultiplier", 2f, new ConfigDescription("Enemy internal attack interval and wait timer multiplier. スタン系を除いた敵内部の攻撃間隔、待機タイマー倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 100f), Array.Empty())); EnableLateSpawnSupport = config.Bind("Runtime", "EnableLateSpawnSupport", true, "Apply speed setup and player awareness support to enemies spawned after level generation.レベル生成後に追加された敵へ速度設定とプレイヤー認識補助を適用"); LateSpawnSupportIntervalSeconds = config.Bind("Runtime", "LateSpawnSupportIntervalSeconds", 1f, new ConfigDescription("Late-spawn support interval seconds.途中生成敵サポートの実行間隔秒数", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 5f), Array.Empty())); ExcludedEnemies = config.Bind("Exclude", "ExcludedEnemies", "EnemyCeilingEye", "Excluded enemy names in CSV. 除外敵名CSV"); DamageRageMode = config.Bind("DamageRage", "DamageRageMode", EnemySpeedUpDamageRageMode.MissingHpRatio, "Damage rage calculation mode. 被ダメ加速計算方式"); DamageRageMaxMultiplier = config.Bind("DamageRage", "DamageRageMaxMultiplier", 2f, new ConfigDescription("Maximum rage multiplier. 被ダメ加速最大倍率", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10f), Array.Empty())); DamageRageAffects = config.Bind("DamageRage", "DamageRageAffects", EnemySpeedUpDamageRageAffects.Anim, "Where damage rage applies. MoveNav/MoveRb/Anim. 被ダメ加速適用先"); LogLevel = config.Bind("Logging", "LogLevel", EnemySpeedUpLogLevel.Info, "Log level. ログレベル"); LogAppliedMultipliers = config.Bind("Logging", "LogAppliedMultipliers", false, "Log applied multipliers. 倍率適用ログ"); } } internal static class FixedSpec { internal const bool MasterClientOnly = true; internal const bool ApplyClientVisuals = true; internal const float MinNavSpeed = 0.1f; internal const float MinRbSpeed = 0.1f; internal const float MinAnimSpeed = 0.01f; internal const float MaxVfxMultiplier = 3f; internal const float LogRateLimitSeconds = 10f; internal const float MinTimerMultiplier = 0.1f; internal const float MaxTimerMultiplier = 100f; } internal static class RuntimeCache { internal struct VfxSnapshot { internal Dictionary ParticleSimulationSpeed; internal Dictionary TrailTime; internal Dictionary LineTextureScale; internal static VfxSnapshot Capture(GameObject root) { //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_0112: Unknown result type (might be due to invalid IL or missing references) VfxSnapshot vfxSnapshot = default(VfxSnapshot); vfxSnapshot.ParticleSimulationSpeed = new Dictionary(); vfxSnapshot.TrailTime = new Dictionary(); vfxSnapshot.LineTextureScale = new Dictionary(); VfxSnapshot result = vfxSnapshot; ParticleSystem[] componentsInChildren = root.GetComponentsInChildren(true); foreach (ParticleSystem val in componentsInChildren) { try { MainModule main = val.main; result.ParticleSimulationSpeed[((Object)val).GetInstanceID()] = ((MainModule)(ref main)).simulationSpeed; } catch { } } TrailRenderer[] componentsInChildren2 = root.GetComponentsInChildren(true); foreach (TrailRenderer val2 in componentsInChildren2) { try { result.TrailTime[((Object)val2).GetInstanceID()] = val2.time; } catch { } } LineRenderer[] componentsInChildren3 = root.GetComponentsInChildren(true); foreach (LineRenderer val3 in componentsInChildren3) { try { Material sharedMaterial = ((Renderer)val3).sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_MainTex")) { result.LineTextureScale[((Object)val3).GetInstanceID()] = sharedMaterial.mainTextureScale; } } catch { } } return result; } } internal static HashSet ExcludedNames = new HashSet(StringComparer.Ordinal); private static readonly Dictionary> AnimatorGetterCache = new Dictionary>(); private static readonly Dictionary LastAppliedAnimatorMultiplier = new Dictionary(); private static readonly Dictionary VfxSnapshots = new Dictionary(); internal static void Rebuild() { ExcludedNames.Clear(); if (string.IsNullOrWhiteSpace(EnemySpeedUpConfig.ExcludedEnemies.Value)) { return; } string[] array = EnemySpeedUpConfig.ExcludedEnemies.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (text2.Length > 0) { ExcludedNames.Add(text2); } } } internal static bool IsExcluded(Component component) { if ((Object)(object)component == (Object)null) { return false; } if (ExcludedNames.Contains(((object)component).GetType().Name)) { return true; } if ((Object)(object)component.gameObject != (Object)null && ExcludedNames.Contains(((Object)component.gameObject).name)) { return true; } return false; } internal static bool TryGetAnimator(object instance, out Animator animator) { animator = null; if (instance == null) { return false; } Type type = instance.GetType(); if (!AnimatorGetterCache.TryGetValue(type, out var value)) { value = BuildAnimatorGetter(type); AnimatorGetterCache[type] = value; } if (value == null) { return false; } try { animator = value(instance); return (Object)(object)animator != (Object)null; } catch { animator = null; return false; } } private static Func BuildAnimatorGetter(Type type) { string[] array = new string[4] { "animator", "Animator", "anim", "_animator" }; string[] array2 = array; foreach (string text in array2) { FieldInfo field = AccessTools.Field(type, text); if (field != null && typeof(Animator).IsAssignableFrom(field.FieldType)) { return delegate(object obj) { object? value2 = field.GetValue(obj); return (Animator)((value2 is Animator) ? value2 : null); }; } } string[] array3 = array; foreach (string text2 in array3) { PropertyInfo property = AccessTools.Property(type, text2); if (property != null && typeof(Animator).IsAssignableFrom(property.PropertyType) && property.GetIndexParameters().Length == 0) { return delegate(object obj) { object? value = property.GetValue(obj, null); return (Animator)((value is Animator) ? value : null); }; } } return null; } internal static float GetLastAnimatorMultiplier(Animator animator) { if ((Object)(object)animator == (Object)null) { return 1f; } if (LastAppliedAnimatorMultiplier.TryGetValue(((Object)animator).GetInstanceID(), out var value)) { return value; } return 1f; } internal static void SetLastAnimatorMultiplier(Animator animator, float multiplier) { if (!((Object)(object)animator == (Object)null)) { LastAppliedAnimatorMultiplier[((Object)animator).GetInstanceID()] = multiplier; } } internal static VfxSnapshot GetOrCreateVfxSnapshot(GameObject root) { if ((Object)(object)root == (Object)null) { return default(VfxSnapshot); } int instanceID = ((Object)root).GetInstanceID(); if (VfxSnapshots.TryGetValue(instanceID, out var value)) { return value; } value = VfxSnapshot.Capture(root); VfxSnapshots[instanceID] = value; return value; } } internal static class RateLog { private static readonly Dictionary LastAt = new Dictionary(StringComparer.Ordinal); internal static void Info(string key, string message) { if (EnemySpeedUpConfig.LogLevel.Value >= EnemySpeedUpLogLevel.Info && Pass(key)) { EnemySpeedUpV2_AllVisuals.Log.LogInfo((object)message); } } internal static void Warn(string key, string message) { if (EnemySpeedUpConfig.LogLevel.Value >= EnemySpeedUpLogLevel.Warn && Pass(key)) { EnemySpeedUpV2_AllVisuals.Log.LogWarning((object)message); } } internal static void Debug(string key, string message) { if (EnemySpeedUpConfig.LogLevel.Value >= EnemySpeedUpLogLevel.Debug && Pass(key)) { EnemySpeedUpV2_AllVisuals.Log.LogInfo((object)message); } } private static bool Pass(string key) { float unscaledTime = Time.unscaledTime; if (LastAt.TryGetValue(key, out var value) && unscaledTime - value < 10f) { return false; } LastAt[key] = unscaledTime; return true; } } internal static class ApplyUtil { private struct NavOriginal { internal float DefaultSpeed; internal float DefaultAcceleration; } private struct RbOriginal { internal float PositionSpeedIdle; internal float PositionSpeedChase; internal float RotationSpeedIdle; internal float RotationSpeedChase; } private static readonly Dictionary NavOriginals = new Dictionary(); private static readonly Dictionary RbOriginals = new Dictionary(); internal static void ReapplyAll() { EnemyNavMeshAgent[] array = Object.FindObjectsOfType(true); foreach (EnemyNavMeshAgent instance in array) { try { ApplyNav(instance); } catch { } } EnemyRigidbody[] array2 = Object.FindObjectsOfType(true); foreach (EnemyRigidbody instance2 in array2) { try { ApplyRb(instance2); } catch { } } } internal static void ApplyNewOnly() { EnemyNavMeshAgent[] array = Object.FindObjectsOfType(true); foreach (EnemyNavMeshAgent val in array) { try { if (!((Object)(object)val == (Object)null) && !NavOriginals.ContainsKey(((Object)val).GetInstanceID())) { ApplyNav(val); } } catch { } } EnemyRigidbody[] array2 = Object.FindObjectsOfType(true); foreach (EnemyRigidbody val2 in array2) { try { if (!((Object)(object)val2 == (Object)null) && !RbOriginals.ContainsKey(((Object)val2).GetInstanceID())) { ApplyRb(val2); } } catch { } } } internal static bool ShouldApplyGameplay(Component component) { if ((Object)(object)component == (Object)null) { return false; } if (!EnemySpeedUpConfig.Enable.Value) { return false; } if ((Object)(object)GameManager.instance == (Object)null) { return false; } if (RuntimeCache.IsExcluded(component)) { return false; } if (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient) { return false; } return true; } internal static bool ShouldApplyVisual(Component component) { if ((Object)(object)component == (Object)null) { return false; } if (!EnemySpeedUpConfig.Enable.Value) { return false; } if ((Object)(object)GameManager.instance == (Object)null) { return false; } if (RuntimeCache.IsExcluded(component)) { return false; } return true; } internal static void ApplyNav(EnemyNavMeshAgent instance) { if (!((Object)(object)instance == (Object)null) && ShouldApplyGameplay((Component)(object)instance)) { int instanceID = ((Object)instance).GetInstanceID(); if (!NavOriginals.TryGetValue(instanceID, out var value)) { NavOriginal navOriginal = default(NavOriginal); navOriginal.DefaultSpeed = instance.DefaultSpeed; navOriginal.DefaultAcceleration = instance.DefaultAcceleration; value = navOriginal; NavOriginals[instanceID] = value; } float damageRageMultiplier = GetDamageRageMultiplier(((Component)instance).gameObject, EnemySpeedUpDamageRageAffects.MoveNav); float num = EnemySpeedUpConfig.NavMoveMultiplier.Value * damageRageMultiplier; instance.DefaultSpeed = Mathf.Max(0.1f, value.DefaultSpeed * num); instance.DefaultAcceleration = Mathf.Max(0f, value.DefaultAcceleration * num); } } internal static void ApplyRb(EnemyRigidbody instance) { if (!((Object)(object)instance == (Object)null) && ShouldApplyGameplay((Component)(object)instance)) { int instanceID = ((Object)instance).GetInstanceID(); if (!RbOriginals.TryGetValue(instanceID, out var value)) { RbOriginal rbOriginal = default(RbOriginal); rbOriginal.PositionSpeedIdle = instance.positionSpeedIdle; rbOriginal.PositionSpeedChase = instance.positionSpeedChase; rbOriginal.RotationSpeedIdle = instance.rotationSpeedIdle; rbOriginal.RotationSpeedChase = instance.rotationSpeedChase; value = rbOriginal; RbOriginals[instanceID] = value; } float damageRageMultiplier = GetDamageRageMultiplier(((Component)instance).gameObject, EnemySpeedUpDamageRageAffects.MoveRb); float num = EnemySpeedUpConfig.RbMoveMultiplier.Value * damageRageMultiplier; instance.positionSpeedIdle = Mathf.Max(0.1f, value.PositionSpeedIdle * num); instance.positionSpeedChase = Mathf.Max(0.1f, value.PositionSpeedChase * num); instance.rotationSpeedIdle = Mathf.Max(0.1f, value.RotationSpeedIdle * num); instance.rotationSpeedChase = Mathf.Max(0.1f, value.RotationSpeedChase * num); } } internal static float GetVisualMultiplier(Component component) { if ((Object)(object)component == (Object)null) { return 1f; } float value = EnemySpeedUpConfig.AnimationSpeedMultiplier.Value; value *= GetDamageRageMultiplier(component.gameObject, EnemySpeedUpDamageRageAffects.Anim); return Mathf.Max(0.01f, value); } internal static float GetDamageRageMultiplier(GameObject owner, EnemySpeedUpDamageRageAffects target) { if ((Object)(object)owner == (Object)null) { return 1f; } if ((EnemySpeedUpConfig.DamageRageAffects.Value & target) == 0) { return 1f; } EnemyHealth val = owner.GetComponentInParent(); if ((Object)(object)val == (Object)null) { val = owner.GetComponent(); } if ((Object)(object)val == (Object)null) { return 1f; } if (val.dead) { return 1f; } float num = Mathf.Max(1f, (float)val.health); float num2 = Mathf.Clamp((float)val.healthCurrent, 0f, num); float num3 = num2 / num; EnemySpeedUpDamageRageMode value = EnemySpeedUpConfig.DamageRageMode.Value; EnemySpeedUpDamageRageMode enemySpeedUpDamageRageMode = value; float num4 = ((enemySpeedUpDamageRageMode == EnemySpeedUpDamageRageMode.MissingHpRatio || enemySpeedUpDamageRageMode != EnemySpeedUpDamageRageMode.CurrentHpRatio) ? (1f - num3) : (1f - num3)); float num5 = Mathf.Max(1f, EnemySpeedUpConfig.DamageRageMaxMultiplier.Value); return 1f + num4 * (num5 - 1f); } internal static void ApplyAnimatorSpeed(Animator animator, float multiplier) { if (!((Object)(object)animator == (Object)null) && !(animator.speed <= 0f)) { float lastAnimatorMultiplier = RuntimeCache.GetLastAnimatorMultiplier(animator); float num = animator.speed; if (lastAnimatorMultiplier > 0f) { num = animator.speed / lastAnimatorMultiplier; } float speed = Mathf.Max(0.01f, num * multiplier); animator.speed = speed; RuntimeCache.SetLastAnimatorMultiplier(animator, multiplier); } } internal static void ApplyVfx(GameObject root, float multiplier) { //IL_0062: 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_015b: 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_016b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } float num = Mathf.Clamp(multiplier, 0f, 3f); RuntimeCache.VfxSnapshot orCreateVfxSnapshot = RuntimeCache.GetOrCreateVfxSnapshot(root); ParticleSystem[] componentsInChildren = root.GetComponentsInChildren(true); foreach (ParticleSystem val in componentsInChildren) { try { if (orCreateVfxSnapshot.ParticleSimulationSpeed.TryGetValue(((Object)val).GetInstanceID(), out var value)) { MainModule main = val.main; ((MainModule)(ref main)).simulationSpeed = value * num; } } catch { } } TrailRenderer[] componentsInChildren2 = root.GetComponentsInChildren(true); foreach (TrailRenderer val2 in componentsInChildren2) { try { if (orCreateVfxSnapshot.TrailTime.TryGetValue(((Object)val2).GetInstanceID(), out var value2)) { val2.time = value2 / Mathf.Max(0.001f, num); } } catch { } } LineRenderer[] componentsInChildren3 = root.GetComponentsInChildren(true); foreach (LineRenderer val3 in componentsInChildren3) { try { if (orCreateVfxSnapshot.LineTextureScale.TryGetValue(((Object)val3).GetInstanceID(), out var value3)) { Material material = ((Renderer)val3).material; if (!((Object)(object)material == (Object)null) && material.HasProperty("_MainTex")) { material.mainTextureScale = new Vector2(value3.x * num, value3.y); } } } catch { } } } } internal static class VisualContext { [ThreadStatic] private static int _depth; [ThreadStatic] private static float _multiplier; internal static bool Active => _depth > 0; internal static float Multiplier => (_multiplier > 0f) ? _multiplier : 1f; internal static void Enter(Component component) { _depth++; _multiplier = (((Object)(object)component != (Object)null) ? ApplyUtil.GetVisualMultiplier(component) : 1f); } internal static void Exit() { _depth--; if (_depth <= 0) { _depth = 0; _multiplier = 1f; } } internal static float GetScaledDeltaTime(float original) { if (!Active) { return original; } return original * Multiplier; } } internal static class OverrideGuard { private static readonly Dictionary LastFrameByKey = new Dictionary(); internal static bool TryEnter(Component owner, int methodKind) { if ((Object)(object)owner == (Object)null) { return true; } int frameCount = Time.frameCount; long key = ((long)((Object)owner).GetInstanceID() << 8) ^ (uint)methodKind; if (LastFrameByKey.TryGetValue(key, out var value) && value == frameCount) { return false; } LastFrameByKey[key] = frameCount; return true; } } internal static class DynamicEnemyAnimPatcher { [CompilerGenerated] private sealed class d__5 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private MethodInfo 5__1; private MethodInfo 5__2; private IEnumerator <>s__3; private CodeInstruction 5__4; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__5(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } 5__1 = null; 5__2 = null; <>s__3 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = AccessTools.PropertyGetter(typeof(Time), "deltaTime"); 5__2 = AccessTools.Method(typeof(VisualContext), "GetScaledDeltaTime", (Type[])null, (Type[])null); <>s__3 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; if (CodeInstructionExtensions.Calls(5__4, 5__1)) { <>2__current = new CodeInstruction(OpCodes.Call, (object)5__2); <>1__state = 2; return true; } goto IL_00f9; case 2: { <>1__state = -3; goto IL_00f9; } IL_00f9: 5__4 = null; break; } if (<>s__3.MoveNext()) { 5__4 = <>s__3.Current; <>2__current = 5__4; <>1__state = 1; return true; } <>m__Finally1(); <>s__3 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__3 != null) { <>s__3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__5 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__5(0); } d__.instructions = <>3__instructions; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static bool _patched; private static readonly string[] TargetTypes = new string[32] { "EnemyAnimalAnim", "EnemyBangAnim", "EnemyBeamerAnim", "EnemyBirthdayBoy", "EnemyBombThrowerAnim", "EnemyBowtieAnim", "EnemyCeilingEyeAnim", "EnemyDuckAnim", "EnemyElsaAnim", "EnemyFloaterAnim", "EnemyGnomeAnim", "EnemyHeadAnimationSystem", "EnemyHeadVisual", "EnemyHeadEye", "EnemyHeadGrabberAnim", "EnemyHeartHugger", "EnemyHiddenAnim", "EnemyHunterAnim", "EnemyOogly", "EnemyRobeAnim", "EnemyRunnerAnim", "EnemyShadowAnim", "EnemySlowMouthAnim", "EnemySlowWalkerAnim", "EnemySpinnyAnim", "EnemyThinManAnim", "EnemyTickAnim", "EnemyTricycle", "EnemyTricycleVisuals", "EnemyTumblerAnim", "EnemyUpscreamAnim", "EnemyValuableThrowerAnim" }; internal static void PatchAll(Harmony harmony) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown if (_patched || harmony == null) { return; } Assembly assembly = typeof(Enemy).Assembly; HarmonyMethod val = new HarmonyMethod(typeof(DynamicEnemyAnimPatcher).GetMethod("VisualMethodPrefix", BindingFlags.Static | BindingFlags.NonPublic)); HarmonyMethod val2 = new HarmonyMethod(typeof(DynamicEnemyAnimPatcher).GetMethod("VisualMethodPostfix", BindingFlags.Static | BindingFlags.NonPublic)); HarmonyMethod val3 = new HarmonyMethod(typeof(DynamicEnemyAnimPatcher).GetMethod("DeltaTimeTranspiler", BindingFlags.Static | BindingFlags.NonPublic)); int num = 0; string[] targetTypes = TargetTypes; foreach (string name in targetTypes) { Type type = assembly.GetType(name); if (type == null) { continue; } MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (!methodInfo.IsAbstract && !methodInfo.IsGenericMethod && !methodInfo.ContainsGenericParameters && methodInfo.GetMethodBody() != null && !methodInfo.IsSpecialName) { try { harmony.Patch((MethodBase)methodInfo, val, val2, val3, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } } } if (EnemySpeedUpConfig.LogLevel.Value >= EnemySpeedUpLogLevel.Info) { RateLog.Info("DynamicPatch", $"Dynamic enemy visual patches applied: {num}"); } _patched = true; } private static void VisualMethodPrefix(object __instance) { Component val = (Component)((__instance is Component) ? __instance : null); if (val != null && ApplyUtil.ShouldApplyVisual(val)) { VisualContext.Enter(val); } else { VisualContext.Enter(null); } } private static void VisualMethodPostfix(object __instance) { try { Component val = (Component)((__instance is Component) ? __instance : null); if (val != null && ApplyUtil.ShouldApplyVisual(val)) { if (RuntimeCache.TryGetAnimator(__instance, out var animator) && (Object)(object)animator != (Object)null) { ApplyUtil.ApplyAnimatorSpeed(animator, ApplyUtil.GetVisualMultiplier(val)); } ApplyUtil.ApplyVfx(val.gameObject, ApplyUtil.GetVisualMultiplier(val)); } } catch { } finally { VisualContext.Exit(); } } [IteratorStateMachine(typeof(d__5))] private static IEnumerable DeltaTimeTranspiler(IEnumerable instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(-2) { <>3__instructions = instructions }; } } [HarmonyPatch(typeof(SemiFunc), "SpringFloatGet")] internal static class Patch_SemiFunc_SpringFloatGet { private static void Prefix(SpringFloat _attributes, ref float _deltaTime, out float __state) { __state = 0f; if (VisualContext.Active && _attributes != null) { float multiplier = VisualContext.Multiplier; __state = _attributes.speed; _attributes.speed *= multiplier; if (_deltaTime == -1f) { _deltaTime = Time.deltaTime * multiplier; } else { _deltaTime *= multiplier; } } } private static void Postfix(SpringFloat _attributes, float __state) { if (VisualContext.Active && _attributes != null && __state > 0f) { _attributes.speed = __state; } } } [HarmonyPatch(typeof(SemiFunc), "SpringQuaternionGet")] internal static class Patch_SemiFunc_SpringQuaternionGet { private static void Prefix(SpringQuaternion _attributes, ref float _deltaTime, out float __state) { __state = 0f; if (VisualContext.Active && _attributes != null) { float multiplier = VisualContext.Multiplier; __state = _attributes.speed; _attributes.speed *= multiplier; if (_deltaTime == -1f) { _deltaTime = Time.deltaTime * multiplier; } else { _deltaTime *= multiplier; } } } private static void Postfix(SpringQuaternion _attributes, float __state) { if (VisualContext.Active && _attributes != null && __state > 0f) { _attributes.speed = __state; } } } [HarmonyPatch(typeof(SemiFunc), "SpringVector3Get")] internal static class Patch_SemiFunc_SpringVector3Get { private static void Prefix(SpringVector3 _attributes, ref float _deltaTime, out float __state) { __state = 0f; if (VisualContext.Active && _attributes != null) { float multiplier = VisualContext.Multiplier; __state = _attributes.speed; _attributes.speed *= multiplier; if (_deltaTime == -1f) { _deltaTime = Time.deltaTime * multiplier; } else { _deltaTime *= multiplier; } } } private static void Postfix(SpringVector3 _attributes, float __state) { if (VisualContext.Active && _attributes != null && __state > 0f) { _attributes.speed = __state; } } } internal static class LateSpawnSupport { private static readonly Dictionary LastPlayerAwarenessAt = new Dictionary(); private static readonly FieldInfo EnemyParentSetupDoneField = AccessTools.Field(typeof(EnemyParent), "SetupDone"); internal static void Apply() { if (EnemySpeedUpConfig.EnableLateSpawnSupport != null && EnemySpeedUpConfig.EnableLateSpawnSupport.Value && !((Object)(object)GameManager.instance == (Object)null) && (!GameManager.Multiplayer() || PhotonNetwork.IsMasterClient)) { ReleaseLateSpawnedEnemyParents(); ApplyUtil.ApplyNewOnly(); SyncPlayersToEnemies(); } } private static void ReleaseLateSpawnedEnemyParents() { if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated || EnemyParentSetupDoneField == null) { return; } EnemyParent[] array = Object.FindObjectsOfType(true); foreach (EnemyParent val in array) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy) { continue; } try { if (!(EnemyParentSetupDoneField.GetValue(val) is int num) || num == 0) { Enemy componentInChildren = ((Component)val).GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null)) { EnemyParentSetupDoneField.SetValue(val, true); } } } catch { } } } private static void SyncPlayersToEnemies() { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return; } PlayerAvatar[] array = GameDirector.instance.PlayerList.ToArray(); if (array.Length == 0) { return; } Enemy[] array2 = Object.FindObjectsOfType(true); foreach (Enemy val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy) { continue; } int instanceID = ((Object)val).GetInstanceID(); if (LastPlayerAwarenessAt.TryGetValue(instanceID, out var value) && Time.time - value < 3f) { continue; } LastPlayerAwarenessAt[instanceID] = Time.time; foreach (PlayerAvatar val2 in array) { if (!((Object)(object)val2 == (Object)null) && !val2.isDisabled && !((Object)(object)val2.photonView == (Object)null)) { try { val.PlayerAdded(val2.photonView.ViewID); } catch { } } } } } } internal static class EnemyTimerAcceleration { private static readonly Dictionary> TimerFieldsByType = new Dictionary>(); internal static void Apply(Component component, float deltaTime) { if ((Object)(object)component == (Object)null || !EnemySpeedUpConfig.Enable.Value || !EnemySpeedUpConfig.EnableEnemyTimerAcceleration.Value || RuntimeCache.IsExcluded(component) || (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient)) { return; } float num = Mathf.Clamp(EnemySpeedUpConfig.EnemyTimerMultiplier.Value, 0.1f, 100f); if (num <= 1.001f) { return; } float num2 = deltaTime * (num - 1f); if (num2 <= 0f) { return; } List timerFields = GetTimerFields(((object)component).GetType()); for (int i = 0; i < timerFields.Count; i++) { FieldInfo fieldInfo = timerFields[i]; try { object value = fieldInfo.GetValue(component); if (value is float) { float num3 = (float)value; if (!(num3 <= 0f)) { fieldInfo.SetValue(component, Mathf.Max(0f, num3 - num2)); } } } catch { } } } private static List GetTimerFields(Type type) { if (type == null) { return new List(); } if (TimerFieldsByType.TryGetValue(type, out var value)) { return value; } List list = new List(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!(fieldInfo.FieldType != typeof(float)) && LooksLikeAttackIntervalTimerField(fieldInfo.Name)) { list.Add(fieldInfo); } } TimerFieldsByType[type] = list; return list; } private static bool LooksLikeAttackIntervalTimerField(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLowerInvariant(); if (text.Contains("stun") || text.Contains("freeze") || text.Contains("frozen") || text.Contains("invincible") || text.Contains("invulnerable") || text.Contains("indestructible") || text.Contains("tumble") || text.Contains("hurt") || text.Contains("damage") || text.Contains("death") || text.Contains("dead") || text.Contains("disable") || text.Contains("disabled") || text.Contains("spawn") || text.Contains("despawn")) { return false; } return text.Contains("timer") || text.Contains("cooldown") || text.Contains("delay") || text.Contains("pause") || text.Contains("wait") || text.Contains("interval"); } } internal static class DynamicEnemyTimerPatcher { private static bool _patched; internal static void PatchAll(Harmony harmony) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown if (_patched || harmony == null) { return; } Assembly assembly = typeof(Enemy).Assembly; HarmonyMethod val = new HarmonyMethod(typeof(DynamicEnemyTimerPatcher).GetMethod("UpdatePostfix", BindingFlags.Static | BindingFlags.NonPublic)); HarmonyMethod val2 = new HarmonyMethod(typeof(DynamicEnemyTimerPatcher).GetMethod("FixedUpdatePostfix", BindingFlags.Static | BindingFlags.NonPublic)); int num = 0; Type[] types = assembly.GetTypes(); foreach (Type type in types) { if (type == null || !typeof(Component).IsAssignableFrom(type) || !type.Name.StartsWith("Enemy", StringComparison.Ordinal)) { continue; } MethodInfo declaredInstanceMethodNoWarn = GetDeclaredInstanceMethodNoWarn(type, "Update"); if (declaredInstanceMethodNoWarn != null && !declaredInstanceMethodNoWarn.IsStatic && declaredInstanceMethodNoWarn.GetMethodBody() != null) { try { harmony.Patch((MethodBase)declaredInstanceMethodNoWarn, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } MethodInfo declaredInstanceMethodNoWarn2 = GetDeclaredInstanceMethodNoWarn(type, "FixedUpdate"); if (declaredInstanceMethodNoWarn2 != null && !declaredInstanceMethodNoWarn2.IsStatic && declaredInstanceMethodNoWarn2.GetMethodBody() != null) { try { harmony.Patch((MethodBase)declaredInstanceMethodNoWarn2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } } if (EnemySpeedUpConfig.LogLevel.Value >= EnemySpeedUpLogLevel.Info) { RateLog.Info("DynamicTimerPatch", "Dynamic enemy attack interval timer patches applied: " + num); } _patched = true; } private static MethodInfo GetDeclaredInstanceMethodNoWarn(Type type, string methodName) { if (type == null || string.IsNullOrEmpty(methodName)) { return null; } try { return type.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); } catch { return null; } } private static void UpdatePostfix(object __instance) { Component component = (Component)((__instance is Component) ? __instance : null); EnemyTimerAcceleration.Apply(component, Time.deltaTime); } private static void FixedUpdatePostfix(object __instance) { Component component = (Component)((__instance is Component) ? __instance : null); EnemyTimerAcceleration.Apply(component, Time.fixedDeltaTime); } } [HarmonyPatch(typeof(EnemyNavMeshAgent), "Awake")] internal static class Patch_EnemyNavMeshAgent_Awake { private static void Postfix(EnemyNavMeshAgent __instance) { ApplyUtil.ApplyNav(__instance); } } [HarmonyPatch(typeof(EnemyNavMeshAgent), "OnEnable")] internal static class Patch_EnemyNavMeshAgent_OnEnable { private static void Postfix(EnemyNavMeshAgent __instance) { ApplyUtil.ApplyNav(__instance); } } [HarmonyPatch(typeof(EnemyNavMeshAgent), "OverrideAgent")] internal static class Patch_EnemyNavMeshAgent_OverrideAgent { private static void Prefix(EnemyNavMeshAgent __instance, ref float speed, ref float acceleration, float time) { if (!((Object)(object)__instance == (Object)null) && ApplyUtil.ShouldApplyGameplay((Component)(object)__instance) && OverrideGuard.TryEnter((Component)(object)__instance, 1)) { float damageRageMultiplier = ApplyUtil.GetDamageRageMultiplier(((Component)__instance).gameObject, EnemySpeedUpDamageRageAffects.MoveNav); float num = EnemySpeedUpConfig.NavAttackMoveMultiplier.Value * damageRageMultiplier; speed = Mathf.Max(0.1f, speed * num); acceleration = Mathf.Max(0f, acceleration * num); } } } [HarmonyPatch(typeof(EnemyRigidbody), "Awake")] internal static class Patch_EnemyRigidbody_Awake { private static void Postfix(EnemyRigidbody __instance) { ApplyUtil.ApplyRb(__instance); } } [HarmonyPatch(typeof(EnemyRigidbody), "OverrideFollowPosition")] internal static class Patch_EnemyRigidbody_OverrideFollowPosition { private static void Prefix(EnemyRigidbody __instance, ref float speed) { if (!((Object)(object)__instance == (Object)null) && ApplyUtil.ShouldApplyGameplay((Component)(object)__instance) && OverrideGuard.TryEnter((Component)(object)__instance, 2)) { float damageRageMultiplier = ApplyUtil.GetDamageRageMultiplier(((Component)__instance).gameObject, EnemySpeedUpDamageRageAffects.MoveRb); float num = EnemySpeedUpConfig.RbAttackMoveMultiplier.Value * damageRageMultiplier; speed = Mathf.Max(0.1f, speed * num); } } } [HarmonyPatch(typeof(EnemyRigidbody), "OverrideFollowRotation")] internal static class Patch_EnemyRigidbody_OverrideFollowRotation { private static void Prefix(EnemyRigidbody __instance, ref float speed) { if (!((Object)(object)__instance == (Object)null) && ApplyUtil.ShouldApplyGameplay((Component)(object)__instance) && OverrideGuard.TryEnter((Component)(object)__instance, 3)) { float damageRageMultiplier = ApplyUtil.GetDamageRageMultiplier(((Component)__instance).gameObject, EnemySpeedUpDamageRageAffects.MoveRb); float num = EnemySpeedUpConfig.RbAttackMoveMultiplier.Value * damageRageMultiplier; speed = Mathf.Max(0.1f, speed * num); } } } [HarmonyPatch(typeof(EnemyParent), "SpawnRPC")] internal static class Patch_EnemyParent_SpawnRPC { private static void Postfix() { LateSpawnSupport.Apply(); } } [HarmonyPatch(typeof(Enemy), "Start")] internal static class Patch_Enemy_Start { private static void Postfix(Enemy __instance) { if (!((Object)(object)__instance == (Object)null)) { LateSpawnSupport.Apply(); } } } }