Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SpecialAttack v1.1.0
plugins/SpecialAttackPlugin.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SpecialAttackPlugin")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SpecialAttackPlugin")] [assembly: AssemblyTitle("SpecialAttackPlugin")] [assembly: AssemblyVersion("1.0.0.0")] namespace SpecialAttackPlugin; internal static class AftershockCooldown { private sealed class State { public double ReadyAt; public float Duration; public Sprite Icon; } private static readonly ConditionalWeakTable<Character, State> _states = new ConditionalWeakTable<Character, State>(); internal static bool IsOnCooldown(Character c) { if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); return num < value.ReadyAt; } internal static bool TryConsume(Character c, float cooldown, Sprite icon = null) { if (cooldown <= 0f) { return true; } State value = _states.GetValue(c, (Character _) => new State()); double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); if (num < value.ReadyAt) { return false; } value.ReadyAt = num + (double)cooldown; value.Duration = cooldown; value.Icon = icon; return true; } internal static bool CollectEntry(Character c, out CooldownEntry entry) { entry = default(CooldownEntry); if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); float num2 = (float)Math.Max(0.0, value.ReadyAt - num); if (num2 <= 0f) { return false; } entry = new CooldownEntry { Icon = value.Icon, Remaining = num2, Duration = value.Duration }; return true; } } internal static class AftershockFilter { internal static bool Matches(ItemData weapon) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if (weapon?.m_shared == null) { return false; } SharedData shared = weapon.m_shared; if ((int)shared.m_itemType != 14) { return false; } string text = shared.m_secondaryAttack?.m_attackAnimation ?? ""; if (text.IndexOf("sledge", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("slam", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } string text2 = shared.m_name ?? ""; return text2.IndexOf("sledge", StringComparison.OrdinalIgnoreCase) >= 0; } } internal static class AftershockSystem { private static readonly Collider[] _hitBuf = (Collider[])(object)new Collider[64]; private static readonly HashSet<GameObject> _hitSet = new HashSet<GameObject>(); private static int _maskChars; private static int _maskTerrain; private static bool _pending; private static Player _pendingPlayer; private static ItemData _pendingWeapon; private static Attack _pendingAttack; private static Vector3 _pendingForward; private static readonly string[] _waveVfxNames = new string[2] { "sledge_aoe", "fx_goblinbrute_groundslam" }; private static int GetMaskChars() { if (_maskChars == 0) { _maskChars = LayerMask.GetMask(new string[9] { "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle", "piece", "piece_nonsolid", "Default" }); } return _maskChars; } private static int GetMaskTerrain() { if (_maskTerrain == 0) { _maskTerrain = LayerMask.GetMask(new string[1] { "terrain" }); } return _maskTerrain; } internal static void QueueTrigger(Humanoid humanoid, Attack attack) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0165: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.AsEnable.Value) { return; } ItemData currentWeapon = humanoid.GetCurrentWeapon(); if (!AftershockFilter.Matches(currentWeapon)) { if (currentWeapon?.m_shared != null) { SharedData shared = currentWeapon.m_shared; Plugin.Log.LogInfo((object)string.Format("[AS] Filter MISS | wep={0} itemType={1} skill={2} secAnim={3}", shared.m_name, shared.m_itemType, shared.m_skillType, shared.m_secondaryAttack?.m_attackAnimation ?? "null")); } return; } Character val = (Character)humanoid; if (val.IsOwner()) { Player val2 = (Player)(object)((humanoid is Player) ? humanoid : null); if (!((Object)(object)val2 == (Object)null) && (!(Plugin.AsMinSkillLevel.Value > 0f) || !(((Character)val2).GetSkillLevel((SkillType)3) < Plugin.AsMinSkillLevel.Value)) && !AftershockCooldown.IsOnCooldown(val)) { _pending = true; _pendingPlayer = val2; _pendingWeapon = currentWeapon; _pendingAttack = attack; _pendingForward = ((Component)val).transform.forward; Plugin.Log.LogInfo((object)$"[AS] Queued | wep={currentWeapon.m_shared.m_name} dir={_pendingForward}"); } } } internal static void ExecuteIfQueued(Humanoid humanoid) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) if (_pending && (object)humanoid == _pendingPlayer) { _pending = false; Character c = (Character)_pendingPlayer; SharedData shared = _pendingWeapon.m_shared; Sprite icon = ((shared != null && shared.m_icons?.Length > 0) ? _pendingWeapon.m_shared.m_icons[0] : null); if (AftershockCooldown.TryConsume(c, Plugin.AsCooldown.Value, icon)) { SaVfx.PlayAdrenaline1(((Component)_pendingPlayer).transform.position); GameObject gameObject = ((Component)_pendingPlayer).gameObject; AftershockController aftershockController = gameObject.AddComponent<AftershockController>(); aftershockController.Initialize(_pendingPlayer, _pendingWeapon, _pendingAttack, _pendingForward); Plugin.Log.LogInfo((object)("[AS] Triggered (OnAttackTrigger) | wep=" + _pendingWeapon.m_shared.m_name)); } } } internal static void ApplyWave(Player player, ItemData weapon, Attack attack, int waveIndex, Vector3 attackForward, Vector3 startPosition) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) Character val = (Character)player; if ((Object)(object)val == (Object)null || val.IsDead()) { return; } float num = 1f - Mathf.Clamp01(Plugin.AsWaveDecay.Value); float num2 = ((waveIndex <= 0) ? 1f : Mathf.Pow(num, (float)waveIndex)); float num3 = Plugin.AsRadius.Value * num2; float value = Plugin.AsForwardStep.Value; float dmgFactor = Plugin.AsDamageFactor.Value * num2; float randomSkillFactor = val.GetRandomSkillFactor((SkillType)3); Vector3 val2 = startPosition + attackForward * (value * (float)(waveIndex + 1)); val2.y = GetGroundY(val2, startPosition.y) + 0.3f; Quaternion rotation = ((((Vector3)(ref attackForward)).sqrMagnitude > 0.001f) ? Quaternion.LookRotation(attackForward) : Quaternion.identity); SpawnWaveVFX(weapon, attack, val2, rotation, num2); _hitSet.Clear(); int num4 = Physics.OverlapSphereNonAlloc(val2, num3, _hitBuf, GetMaskChars(), (QueryTriggerInteraction)0); int num5 = 0; Vector3 val3 = Vector3.zero; for (int i = 0; i < num4; i++) { Collider val4 = _hitBuf[i]; if ((Object)(object)val4 == (Object)null) { continue; } GameObject val5 = Projectile.FindHitObject(val4); if ((Object)(object)val5 == (Object)null || !_hitSet.Add(val5)) { continue; } Character componentInParent = val5.GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null) { if (componentInParent != val && !componentInParent.IsDead() && BaseAI.IsEnemy(val, componentInParent) && !componentInParent.InDodge() && !componentInParent.IsDebugFlying()) { ApplyHit(val, componentInParent, weapon, val2, dmgFactor, randomSkillFactor); val3 += componentInParent.GetCenterPoint(); num5++; } } else { IDestructible componentInParent2 = val5.GetComponentInParent<IDestructible>(); if (componentInParent2 != null) { ApplyDestructibleHit(val, componentInParent2, weapon, val2, dmgFactor, randomSkillFactor); num5++; } } } Plugin.Log.LogInfo((object)$"[AS] Wave {waveIndex} | origin={val2} radius={num3:F2} hits={num5} scale={num2:F2}"); } private static void SpawnWaveVFX(ItemData weapon, Attack attack, Vector3 origin, Quaternion rotation, float scale) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_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) if ((Object)(object)ZNetScene.instance != (Object)null) { string[] waveVfxNames = _waveVfxNames; foreach (string text in waveVfxNames) { GameObject prefab = ZNetScene.instance.GetPrefab(text); if (!((Object)(object)prefab == (Object)null)) { GameObject val = Object.Instantiate<GameObject>(prefab, origin, rotation); val.transform.localScale = Vector3.one * scale; ScaleParticleSystems(val, scale); Plugin.Log.LogInfo((object)$"[AS VFX] spawned={text} scale={scale:F2}"); return; } } } if (attack != null && attack.m_triggerEffect?.m_effectPrefabs?.Length > 0) { attack.m_triggerEffect.Create(origin, rotation, (Transform)null, scale, -1); } else { Plugin.Log.LogWarning((object)"[AS VFX] NO VFX"); } } private static void ScaleParticleSystems(GameObject obj, float scale) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Approximately(scale, 1f)) { return; } ParticleSystem[] componentsInChildren = obj.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren) { MainModule main = val.main; if (((MainModule)(ref main)).startSize3D) { ((MainModule)(ref main)).startSizeX = ScaleCurve(((MainModule)(ref main)).startSizeX, scale); ((MainModule)(ref main)).startSizeY = ScaleCurve(((MainModule)(ref main)).startSizeY, scale); ((MainModule)(ref main)).startSizeZ = ScaleCurve(((MainModule)(ref main)).startSizeZ, scale); } else { ((MainModule)(ref main)).startSize = ScaleCurve(((MainModule)(ref main)).startSize, scale); } ((MainModule)(ref main)).startSpeed = ScaleCurve(((MainModule)(ref main)).startSpeed, scale); ShapeModule shape = val.shape; if (((ShapeModule)(ref shape)).enabled) { ((ShapeModule)(ref shape)).radius = ((ShapeModule)(ref shape)).radius * scale; ((ShapeModule)(ref shape)).scale = ((ShapeModule)(ref shape)).scale * scale; ((ShapeModule)(ref shape)).position = ((ShapeModule)(ref shape)).position * scale; } TrailModule trails = val.trails; if (((TrailModule)(ref trails)).enabled) { ((TrailModule)(ref trails)).widthOverTrail = ScaleCurve(((TrailModule)(ref trails)).widthOverTrail, scale); } ParticleSystemRenderer component = ((Component)val).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component != (Object)null) { component.lengthScale *= scale; component.velocityScale *= scale; } } } private static MinMaxCurve ScaleCurve(MinMaxCurve curve, float scale) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected I4, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) ParticleSystemCurveMode mode = ((MinMaxCurve)(ref curve)).mode; ParticleSystemCurveMode val = mode; switch ((int)val) { case 0: ((MinMaxCurve)(ref curve)).constant = ((MinMaxCurve)(ref curve)).constant * scale; break; case 3: ((MinMaxCurve)(ref curve)).constantMin = ((MinMaxCurve)(ref curve)).constantMin * scale; ((MinMaxCurve)(ref curve)).constantMax = ((MinMaxCurve)(ref curve)).constantMax * scale; break; case 1: case 2: ((MinMaxCurve)(ref curve)).curveMultiplier = ((MinMaxCurve)(ref curve)).curveMultiplier * scale; break; } return curve; } private static float GetGroundY(Vector3 pos, float fallback) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) RaycastHit val = default(RaycastHit); if (Physics.Raycast(new Vector3(pos.x, pos.y + 10f, pos.z), Vector3.down, ref val, 25f, GetMaskTerrain(), (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val)).point.y; } return fallback; } private static void ApplyHit(Character attacker, Character target, ItemData weapon, Vector3 origin, float dmgFactor, float skillFactor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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) DamageTypes damage = weapon.GetDamage(); ((DamageTypes)(ref damage)).Modify(dmgFactor * skillFactor); HitData val = new HitData(); val.m_damage = damage; val.m_skill = (SkillType)3; val.m_pushForce = Plugin.AsPushForce.Value * ((dmgFactor > 0f) ? Mathf.Sqrt(dmgFactor) : 0f); val.m_staggerMultiplier = 1f; val.m_blockable = false; val.m_dodgeable = false; val.m_skillRaiseAmount = 0f; val.m_point = target.GetCenterPoint(); Vector3 val2 = target.GetCenterPoint() - origin; val2.y = 0f; val.m_dir = ((((Vector3)(ref val2)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val2)).normalized : ((Component)attacker).transform.forward); val.SetAttacker(attacker); target.Damage(val); } private static void ApplyDestructibleHit(Character attacker, IDestructible target, ItemData weapon, Vector3 origin, float dmgFactor, float skillFactor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_005e: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) DamageTypes damage = weapon.GetDamage(); ((DamageTypes)(ref damage)).Modify(dmgFactor * skillFactor); HitData val = new HitData(); val.m_damage = damage; val.m_skill = (SkillType)3; val.m_pushForce = 0f; val.m_blockable = false; val.m_dodgeable = false; val.m_skillRaiseAmount = 0f; Component val2 = (Component)(object)((target is Component) ? target : null); val.m_point = (((Object)(object)val2 != (Object)null) ? val2.transform.position : origin); Vector3 val3 = val.m_point - origin; val3.y = 0f; val.m_dir = ((((Vector3)(ref val3)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val3)).normalized : ((Component)attacker).transform.forward); val.SetAttacker(attacker); target.Damage(val); } } internal sealed class AftershockController : MonoBehaviour { private Player _player; private ItemData _weapon; private Attack _attack; private Vector3 _forwardDir; private Vector3 _startPosition; private int _nextWave; private float _nextWaveTime; private int _totalWaves; internal void Initialize(Player player, ItemData weapon, Attack attack, Vector3 attackForward) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) _player = player; _weapon = weapon; _attack = attack; _forwardDir = ((((Vector3)(ref attackForward)).sqrMagnitude > 0.001f) ? ((Vector3)(ref attackForward)).normalized : Vector3.forward); _startPosition = ((Component)(Character)player).transform.position; _nextWave = 0; _totalWaves = Mathf.Max(1, Plugin.AsWaves.Value); _nextWaveTime = Time.time; ((Behaviour)this).enabled = true; } private void Update() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_player == (Object)null || ((Character)_player).IsDead()) { Object.Destroy((Object)(object)this); return; } while (_nextWave < _totalWaves && Time.time >= _nextWaveTime) { AftershockSystem.ApplyWave(_player, _weapon, _attack, _nextWave, _forwardDir, _startPosition); _nextWave++; float num = Mathf.Max(0f, Plugin.AsInterval.Value); _nextWaveTime += num; if (num > 0f) { break; } } if (_nextWave >= _totalWaves) { Object.Destroy((Object)(object)this); } } } internal static class ChargeSlashCooldown { private sealed class State { public double ReadyAt; public float Duration; public Sprite Icon; } private static readonly ConditionalWeakTable<Character, State> _states = new ConditionalWeakTable<Character, State>(); internal static bool IsOnCooldown(Character c) { if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); return num < value.ReadyAt; } internal static bool TryConsume(Character c, float cooldown, Sprite icon = null) { if (cooldown <= 0f) { return true; } State value = _states.GetValue(c, (Character _) => new State()); double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); if (num < value.ReadyAt) { return false; } value.ReadyAt = num + (double)cooldown; value.Duration = cooldown; value.Icon = icon; return true; } internal static bool CollectEntry(Character c, out CooldownEntry entry) { entry = default(CooldownEntry); if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); float num2 = (float)Math.Max(0.0, value.ReadyAt - num); if (num2 <= 0f) { return false; } entry = new CooldownEntry { Icon = value.Icon, Remaining = num2, Duration = value.Duration }; return true; } } internal static class ChargeSlashFilter { internal static bool Matches(ItemData weapon) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 if (weapon?.m_shared == null) { return false; } SharedData shared = weapon.m_shared; if ((int)shared.m_skillType != 1) { return false; } if ((int)shared.m_itemType != 14) { return false; } string text = (((Object)(object)weapon.m_dropPrefab != (Object)null) ? ((Object)weapon.m_dropPrefab).name : ""); return text.IndexOf("bastard", StringComparison.OrdinalIgnoreCase) >= 0; } } internal static class ChargeSlashSystem { private static bool _multiplyNext; private static float _chargeTime; private static ZDOID _zdoid; private static bool _allowSlash; internal static bool AllowSlash => _allowSlash; internal static void StartCharging(Humanoid humanoid) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)humanoid).gameObject; if (!((Object)(object)gameObject.GetComponent<ChargeSlashController>() != (Object)null)) { Character val = (Character)humanoid; _zdoid = val.GetZDOID(); ChargeSlashController chargeSlashController = gameObject.AddComponent<ChargeSlashController>(); chargeSlashController.Begin(humanoid, humanoid.GetCurrentWeapon()); Plugin.Log.LogInfo((object)"[CS] 충전 시작"); } } internal static bool FireSlash(Humanoid humanoid, float chargeTime) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) _multiplyNext = true; _chargeTime = chargeTime; _allowSlash = true; bool flag = ((Character)humanoid).StartAttack((Character)null, true); _allowSlash = false; if (!flag) { _multiplyNext = false; } Plugin.Log.LogInfo((object)$"[CS] 슬래시 발동 — 충전 {chargeTime:F2}s, ok={flag}"); return flag; } internal static void ClearPending() { _multiplyNext = false; } internal static void TryHandleDamage(Character target, ref HitData hit) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) if (Plugin.CsEnable.Value && _multiplyNext && !((Object)(object)target == (Object)null) && !target.IsPlayer() && (int)hit.m_skill == 1 && !(((DamageTypes)(ref hit.m_damage)).GetTotalDamage() <= 0f) && !(hit.m_attacker != _zdoid)) { _multiplyNext = false; float value = Plugin.CsMaxChargeTime.Value; float num = ((value > 0f) ? Mathf.Clamp01(_chargeTime / value) : 1f); float num2 = Mathf.Lerp(1f, Plugin.CsDamageMult.Value, num); ((DamageTypes)(ref hit.m_damage)).Modify(num2); SaVfx.PlayAdrenaline1(((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : ((Component)target).transform.position); Plugin.Log.LogInfo((object)$"[CS] 슬래시 ×{num2:F2} (충전 {_chargeTime:F2}s / {value:F1}s)"); SpawnHitVfx(hit.m_point); } } private static void SpawnHitVfx(Vector3 point) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) string value = Plugin.CsHitVfxName.Value; if (!string.IsNullOrEmpty(value) && !((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab(value); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogWarning((object)("[CS] VFX 프리팹 없음: " + value)); } else { Object.Instantiate<GameObject>(prefab, point, Quaternion.identity); } } } } internal sealed class ChargeSlashController : MonoBehaviour { private static readonly FieldInfo _secHoldField = AccessTools.Field(typeof(Player), "m_secondaryAttackHold"); private Humanoid _humanoid; private ItemData _weapon; private float _chargeTimer; private bool _releasing; private float _releaseTime; private int _diagFrame; internal bool IsCharging => !_releasing; internal float ChargeTime => _chargeTimer; internal float MaxCharge => Plugin.CsMaxChargeTime.Value; internal float ChargeRatio { get { float maxCharge = MaxCharge; return (maxCharge > 0f) ? Mathf.Clamp01(_chargeTimer / maxCharge) : 1f; } } private bool IsSecondaryHeld() { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) KeyCode value = Plugin.SpecialKey.Value; if ((int)value > 0) { return Input.GetKey(value); } Humanoid humanoid = _humanoid; Player val = (Player)(object)((humanoid is Player) ? humanoid : null); if (val != null && _secHoldField != null) { return (bool)_secHoldField.GetValue(val); } return ZInput.GetButton("SecondaryAttack") || ZInput.GetButton("JoySecondaryAttack"); } internal void Begin(Humanoid h, ItemData w) { _humanoid = h; _weapon = w; _chargeTimer = 0f; _releasing = false; _releaseTime = 0f; ((Behaviour)this).enabled = true; } private void Update() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) Character val = (Character)_humanoid; if ((Object)(object)_humanoid == (Object)null || val.IsDead() || !val.IsOwner()) { Object.Destroy((Object)(object)this); } else if (!ChargeSlashFilter.Matches(_humanoid.GetCurrentWeapon())) { Plugin.Log.LogWarning((object)$"[CS-DIAG] 무기 필터 실패 → 컨트롤러 종료 (timer={_chargeTimer:F3})"); Object.Destroy((Object)(object)this); } else if (val.IsStaggering()) { Object.Destroy((Object)(object)this); } else if (!_releasing) { _chargeTimer = Mathf.Min(_chargeTimer + Time.deltaTime, MaxCharge); bool flag = IsSecondaryHeld(); _diagFrame++; if (_diagFrame % 10 == 0) { Plugin.Log.LogInfo((object)$"[CS-DIAG] timer={_chargeTimer:F3} held={flag} secHoldField={_secHoldField != null}"); } if (_chargeTimer > 0.2f && !flag) { _releasing = true; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Character c = (Character)localPlayer; ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon(); Sprite icon = ((currentWeapon != null && currentWeapon.m_shared?.m_icons?.Length > 0) ? currentWeapon.m_shared.m_icons[0] : null); ChargeSlashCooldown.TryConsume(c, Plugin.CsCooldown.Value, icon); } bool flag2 = ChargeSlashSystem.FireSlash(_humanoid, _chargeTimer); _releaseTime = Time.time + 0.5f; if (!flag2) { Plugin.Log.LogInfo((object)"[CS] 슬래시 실패"); Object.Destroy((Object)(object)this); } } } else if (Time.time > _releaseTime && !val.InAttack()) { Object.Destroy((Object)(object)this); } } private void OnDestroy() { if (!_releasing) { ChargeSlashSystem.ClearPending(); } Plugin.Log.LogInfo((object)$"[CS] 컨트롤러 종료 (충전 {_chargeTimer:F2}s, releasing={_releasing})"); } } internal static class QuadSlashCooldown { private sealed class State { public double ReadyAt; public float Duration; public Sprite Icon; } private static readonly ConditionalWeakTable<Character, State> _states = new ConditionalWeakTable<Character, State>(); internal static bool TryConsume(Character c, float cooldown, Sprite icon = null) { if (cooldown <= 0f) { return true; } State value = _states.GetValue(c, (Character _) => new State()); double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); if (num < value.ReadyAt) { return false; } value.ReadyAt = num + (double)cooldown; value.Duration = cooldown; value.Icon = icon; return true; } internal static bool CollectEntry(Character c, out CooldownEntry entry) { entry = default(CooldownEntry); if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); float num2 = (float)Math.Max(0.0, value.ReadyAt - num); if (num2 <= 0f) { return false; } entry = new CooldownEntry { Icon = value.Icon, Remaining = num2, Duration = value.Duration }; return true; } } internal static class QuadSlashFilter { internal static bool Matches(ItemData weapon) { if (weapon?.m_shared == null || (Object)(object)weapon.m_dropPrefab == (Object)null) { return false; } string name = ((Object)weapon.m_dropPrefab).name; return name.Equals("THSwordKrom", StringComparison.OrdinalIgnoreCase) || name.IndexOf("claymore", StringComparison.OrdinalIgnoreCase) >= 0; } } internal static class QuadSlashVfx { private static Material _trailMat; private static bool _searched; private static readonly FieldInfo _trailMatField = AccessTools.Field(typeof(MeleeWeaponTrail), "m_trailMaterial") ?? AccessTools.Field(typeof(MeleeWeaponTrail), "m_material") ?? AccessTools.Field(typeof(MeleeWeaponTrail), "_material"); private static readonly FieldInfo _rightItemField = AccessTools.Field(typeof(VisEquipment), "m_rightItemInstance"); internal static Material GetDvergrMat() { if (_searched) { return _trailMat; } _searched = true; ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab("BattleaxeDvergr_TW") : null); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"[QS-VFX] BattleaxeDvergr_TW 프리팹 없음"); return null; } MeleeWeaponTrail[] componentsInChildren = val.GetComponentsInChildren<MeleeWeaponTrail>(true); foreach (MeleeWeaponTrail val2 in componentsInChildren) { if (_trailMatField != null) { object? value = _trailMatField.GetValue(val2); Material val3 = (Material)((value is Material) ? value : null); if ((Object)(object)val3 != (Object)null) { _trailMat = val3; Plugin.Log.LogInfo((object)"[QS-VFX] Dvergr trail mat 캐시 완료"); return _trailMat; } } Renderer val4 = ((Component)val2).GetComponent<Renderer>() ?? ((Component)val2).GetComponentInChildren<Renderer>(true); if ((Object)(object)((val4 != null) ? val4.sharedMaterial : null) != (Object)null) { _trailMat = val4.sharedMaterial; Plugin.Log.LogInfo((object)"[QS-VFX] Dvergr trail renderer mat 캐시 완료"); return _trailMat; } } Plugin.Log.LogWarning((object)"[QS-VFX] Dvergr trail 머티리얼 접근 실패 — VFX 생략"); return null; } internal static void Apply(Humanoid humanoid, out Material[] saved, out Renderer[] renderers) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) saved = null; renderers = null; Material dvergrMat = GetDvergrMat(); if ((Object)(object)dvergrMat == (Object)null) { return; } VisEquipment component = ((Component)humanoid).GetComponent<VisEquipment>(); if ((Object)(object)component == (Object)null) { return; } object? obj = _rightItemField?.GetValue(component); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { return; } MeleeWeaponTrail[] componentsInChildren = val.GetComponentsInChildren<MeleeWeaponTrail>(true); if (componentsInChildren.Length == 0) { Plugin.Log.LogWarning((object)"[QS-VFX] 무기 모델에 MeleeWeaponTrail 없음"); return; } List<Material> list = new List<Material>(); List<Renderer> list2 = new List<Renderer>(); MeleeWeaponTrail[] array = componentsInChildren; foreach (MeleeWeaponTrail val2 in array) { if (_trailMatField != null) { object? value = _trailMatField.GetValue(val2); Material val3 = (Material)((value is Material) ? value : null); if ((Object)(object)val3 != (Object)null) { _trailMatField.SetValue(val2, dvergrMat); list.Add(val3); list2.Add(null); continue; } } Renderer component2 = ((Component)val2).GetComponent<Renderer>(); if (!((Object)(object)component2 == (Object)null)) { list.Add(component2.sharedMaterial); list2.Add(component2); component2.sharedMaterial = dvergrMat; } } saved = list.ToArray(); renderers = list2.ToArray(); } internal static void Restore(Material[] saved, Renderer[] renderers) { if (saved == null || renderers == null) { return; } int num = Math.Min(saved.Length, renderers.Length); for (int i = 0; i < num; i++) { if ((Object)(object)renderers[i] != (Object)null) { renderers[i].sharedMaterial = saved[i]; } else if (!((Object)(object)saved[i] != (Object)null)) { } } } } internal static class QuadSlashSystem { internal static bool TryInterceptSA(Humanoid humanoid) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.QsEnable.Value) { return false; } ItemData currentWeapon = humanoid.GetCurrentWeapon(); if (!QuadSlashFilter.Matches(currentWeapon)) { return false; } Character val = (Character)humanoid; if (!val.IsOwner()) { return false; } Player val2 = (Player)(object)((humanoid is Player) ? humanoid : null); if (val2 == null) { return false; } if ((int)Plugin.SpecialKey.Value != 0 && !SpecialInput.Active) { return false; } if (Plugin.QsMinSkillLevel.Value > 0f && ((Character)val2).GetSkillLevel((SkillType)1) < Plugin.QsMinSkillLevel.Value) { return false; } SharedData shared = currentWeapon.m_shared; Sprite icon = ((shared != null && shared.m_icons?.Length > 0) ? currentWeapon.m_shared.m_icons[0] : null); if (!QuadSlashCooldown.TryConsume(val, Plugin.QsCooldown.Value, icon)) { return false; } SaVfx.PlayAdrenaline1(((Component)val2).transform.position); QuadSlashController.Begin(humanoid, currentWeapon); Plugin.Log.LogInfo((object)"[QS] SA 차단 → 4연 베기 시작"); return true; } internal static void ExecuteIfQueued(Humanoid humanoid) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) QuadSlashController component = ((Component)humanoid).GetComponent<QuadSlashController>(); if ((Object)(object)component != (Object)null && component.IsActive) { component.OnAttackTriggered(); } } } internal sealed class QuadSlashController : MonoBehaviour { private static readonly FieldInfo _fChainLevels = AccessTools.Field(typeof(Attack), "m_attackChainLevels"); private static readonly FieldInfo _fCurrentLevel = AccessTools.Field(typeof(Attack), "m_currentAttackCainLevel"); private static readonly FieldInfo _fAnimBase = AccessTools.Field(typeof(Attack), "m_attackAnimation"); private static readonly FieldInfo _fZsyncAnimator = AccessTools.Field(typeof(ZSyncAnimation), "m_animator"); private static readonly FieldInfo _fAnimChain = AccessTools.Field(typeof(CharacterAnimEvent), "m_chain"); private Humanoid _humanoid; private ItemData _weapon; private Animator _animator; private CharacterAnimEvent _animEvent; private float _savedAnimSpeed; private int _hitsLeft; private int _currentHit; internal bool IsFiringNext; private Material[] _savedTrailMats; private Renderer[] _trailRenderers; private static string _cachedBattleaxeTrigger; private static bool _battleaxeTriggerSearched; internal bool IsActive => _hitsLeft > 0; internal int CurrentHit => _currentHit; internal static QuadSlashController Begin(Humanoid humanoid, ItemData weapon) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)humanoid).gameObject; QuadSlashController component = gameObject.GetComponent<QuadSlashController>(); if ((Object)(object)component != (Object)null) { ((MonoBehaviour)component).StopAllCoroutines(); component.ForceCleanup(); } QuadSlashController quadSlashController = component ?? gameObject.AddComponent<QuadSlashController>(); quadSlashController.Setup(humanoid, weapon); return quadSlashController; } private void Setup(Humanoid humanoid, ItemData weapon) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) _humanoid = humanoid; _weapon = weapon; _hitsLeft = 4; _currentHit = 0; ZSyncAnimation componentInChildren = ((Component)humanoid).GetComponentInChildren<ZSyncAnimation>(); _animator = (Animator)((_fZsyncAnimator != null && (Object)(object)componentInChildren != (Object)null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)((Component)humanoid).GetComponentInChildren<Animator>())); _animEvent = ((Component)humanoid).GetComponentInChildren<CharacterAnimEvent>(); if ((Object)(object)_animator != (Object)null) { _savedAnimSpeed = _animator.speed; _animator.speed = GetSpeed(0); } QuadSlashVfx.Apply(humanoid, out _savedTrailMats, out _trailRenderers); Plugin.Log.LogInfo((object)string.Format("[QS-Speed] animator={0} savedSpeed={1} speed0={2}", ((Object)(object)_animator != (Object)null) ? ((Object)_animator).name : "NULL", _savedAnimSpeed, GetSpeed(0))); ((MonoBehaviour)this).StartCoroutine(FireFirstPA()); } private float GetSpeed(int hit) { if (1 == 0) { } float result = hit switch { 0 => Plugin.QsAnimSpeed1.Value, 1 => Plugin.QsAnimSpeed2.Value, 2 => Plugin.QsAnimSpeed3.Value, _ => Plugin.QsAnimSpeed4.Value, }; if (1 == 0) { } return result; } private IEnumerator FireFirstPA() { yield return null; if ((Object)(object)_humanoid != (Object)null && _hitsLeft > 0) { ((Character)_humanoid).StartAttack((Character)null, false); } } internal void OnAttackTriggered() { if (_hitsLeft <= 0) { return; } _hitsLeft--; _currentHit++; if (_hitsLeft > 0) { float speed = GetSpeed(_currentHit); if ((Object)(object)_animator != (Object)null) { _animator.speed = speed; } Plugin.Log.LogInfo((object)string.Format("[QS-Speed] hit={0} speed={1} animator.speed(after)={2}", _currentHit, speed, ((Object)(object)_animator != (Object)null) ? _animator.speed.ToString("F2") : "NULL")); ((MonoBehaviour)this).StartCoroutine(FireNextPA()); } else { Finish(); } } private IEnumerator FireNextPA() { Character ch = (Character)_humanoid; float timeout = Time.time + 2f; while ((Object)(object)ch != (Object)null && !ch.IsDead() && Time.time < timeout) { if (!ch.InAttack()) { if ((Object)(object)_humanoid != (Object)null && _hitsLeft > 0) { ch.StartAttack((Character)null, false); } break; } if ((Object)(object)_animEvent != (Object)null && _fAnimChain != null && (bool)_fAnimChain.GetValue(_animEvent) && (Object)(object)_humanoid != (Object)null && _hitsLeft > 0) { IsFiringNext = true; ch.StartAttack((Character)null, false); IsFiringNext = false; break; } yield return null; } } internal void InjectAnimOverride(Attack attack, ref float timeSinceLastAttack) { timeSinceLastAttack = 0f; } internal void OverrideAnimTrigger(Attack attack) { if ((Object)(object)_animator == (Object)null) { return; } string text = ((_fAnimBase != null) ? ((string)_fAnimBase.GetValue(attack)) : attack.m_attackAnimation); int num = ((_fChainLevels != null) ? ((int)_fChainLevels.GetValue(attack)) : 0); int num2 = ((_fCurrentLevel != null) ? ((int)_fCurrentLevel.GetValue(attack)) : 0); if (string.IsNullOrEmpty(text)) { return; } if (_currentHit == 0) { Plugin.Log.LogInfo((object)$"[QS-Anim] animBase='{text}' chainLevels={num} naturalLevel={num2}"); } string text2 = ((num > 1) ? (text + num2) : text); string text3; if (_currentHit == 3) { text3 = GetBattleaxeLastTrigger() ?? (text + ((num > 1) ? (num - 1).ToString() : "")); } else { if (num <= 1) { Plugin.Log.LogWarning((object)$"[QS-Anim] chainLevels={num} ≤ 1, 애니메이션 순서 제어 불가 (베기 {_currentHit + 1})"); return; } int currentHit = _currentHit; if (1 == 0) { } int num3 = currentHit switch { 0 => Mathf.Min(1, num - 1), 1 => 0, 2 => Mathf.Min(1, num - 1), _ => num - 1, }; if (1 == 0) { } int num4 = num3; text3 = text + num4; } if (!(text2 == text3)) { Plugin.Log.LogInfo((object)$"[QS-Anim] hit={_currentHit} {text2} → {text3}"); _animator.ResetTrigger(text2); _animator.SetTrigger(text3); } } private static string GetBattleaxeLastTrigger() { if (_battleaxeTriggerSearched) { return _cachedBattleaxeTrigger; } ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab("BattleaxeDvergr_TW") : null); if ((Object)(object)val == (Object)null) { return null; } _battleaxeTriggerSearched = true; Attack val2 = ((val != null) ? val.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_attack; if (val2 == null || string.IsNullOrEmpty(val2.m_attackAnimation)) { Plugin.Log.LogWarning((object)"[QS-Anim] BattleaxeDvergr_TW m_attack 미발견 — 배틀액스 AA4 스킵"); return null; } int num = ((_fChainLevels != null) ? ((int)_fChainLevels.GetValue(val2)) : 0); string text = ((_fAnimBase != null) ? ((string)_fAnimBase.GetValue(val2)) : val2.m_attackAnimation); _cachedBattleaxeTrigger = ((num > 1) ? (text + (num - 1)) : text); Plugin.Log.LogInfo((object)$"[QS-Anim] battleaxe trigger 캐시: '{_cachedBattleaxeTrigger}' (chainLevels={num})"); return _cachedBattleaxeTrigger; } internal void RestoreAnimOverride() { } private void Update() { if (IsActive && !((Object)(object)_animator == (Object)null)) { _animator.speed = GetSpeed(_currentHit); } } private void Finish() { ForceCleanup(); Object.Destroy((Object)(object)this); } private void OnDestroy() { ForceCleanup(); } internal void ForceCleanup() { IsFiringNext = false; RestoreAnimSpeed(); RestoreAnimOverride(); QuadSlashVfx.Restore(_savedTrailMats, _trailRenderers); _savedTrailMats = null; _trailRenderers = null; } internal void RestoreAnimSpeed() { if ((Object)(object)_animator != (Object)null && _savedAnimSpeed > 0f) { _animator.speed = _savedAnimSpeed; } } internal float GetCurrentSpeed() { return GetSpeed(_currentHit); } } internal static class QuadSlash_CharAnimHelper { internal static readonly FieldInfo FAnimator = AccessTools.Field(typeof(CharacterAnimEvent), "m_animator"); internal static void RestoreSpeed(CharacterAnimEvent instance) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)((Component)instance).GetComponentInParent<Character>() != (Object)(Character)localPlayer) { return; } QuadSlashController component = ((Component)localPlayer).GetComponent<QuadSlashController>(); if (!((Object)(object)component == (Object)null) && component.IsActive) { object? obj = FAnimator?.GetValue(instance); Animator val = (Animator)((obj is Animator) ? obj : null); if ((Object)(object)val != (Object)null) { val.speed = component.GetCurrentSpeed(); } } } } [HarmonyPatch(typeof(CharacterAnimEvent), "CustomFixedUpdate")] internal static class QuadSlash_Patch_CharAnimFixedUpdate { private static void Postfix(CharacterAnimEvent __instance) { QuadSlash_CharAnimHelper.RestoreSpeed(__instance); } } [HarmonyPatch(typeof(CharacterAnimEvent), "Speed")] internal static class QuadSlash_Patch_CharAnimSpeed { private static void Postfix(CharacterAnimEvent __instance) { QuadSlash_CharAnimHelper.RestoreSpeed(__instance); } } [HarmonyPatch(typeof(Player), "HaveQueuedChain")] internal static class QuadSlash_Patch_HaveQueuedChain { private static void Postfix(Player __instance, ref bool __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!__result) { QuadSlashController component = ((Component)__instance).GetComponent<QuadSlashController>(); if ((Object)(object)component != (Object)null && component.IsActive && component.IsFiringNext) { __result = true; } } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class QuadSlash_Patch_Damage { private static void Prefix(Character __instance, ref HitData hit) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) if ((Object)(object)Player.m_localPlayer == (Object)null || hit.m_attacker != ((Character)Player.m_localPlayer).GetZDOID()) { return; } QuadSlashController component = ((Component)Player.m_localPlayer).GetComponent<QuadSlashController>(); if (!((Object)(object)component == (Object)null) && component.IsActive) { int currentHit = component.CurrentHit; if (1 == 0) { } float num = currentHit switch { 0 => Plugin.QsDamage1.Value, 1 => Plugin.QsDamage2.Value, 2 => Plugin.QsDamage3.Value, _ => Plugin.QsDamage4.Value, }; if (1 == 0) { } float num2 = num; if (!Mathf.Approximately(num2, 1f)) { ((DamageTypes)(ref hit.m_damage)).Modify(num2); } } } } internal static class CounterUpperFilter { internal static bool Matches(ItemData weapon) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 if (weapon?.m_shared == null || (Object)(object)weapon.m_dropPrefab == (Object)null) { return false; } if ((int)weapon.m_shared.m_skillType != 11) { return false; } string name = ((Object)weapon.m_dropPrefab).name; return name.IndexOf("Fist", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Claw", StringComparison.OrdinalIgnoreCase) >= 0; } } internal static class CounterUpperCooldown { private sealed class State { public double ReadyAt; public float Duration; public Sprite Icon; } private static readonly ConditionalWeakTable<Character, State> _states = new ConditionalWeakTable<Character, State>(); internal static bool TryConsume(Character c, float cooldown, Sprite icon = null) { if (cooldown <= 0f) { return true; } State value = _states.GetValue(c, (Character _) => new State()); double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); if (num < value.ReadyAt) { return false; } value.ReadyAt = num + (double)cooldown; value.Duration = cooldown; value.Icon = icon; return true; } internal static bool CollectEntry(Character c, out CooldownEntry entry) { entry = default(CooldownEntry); if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); float num2 = (float)Math.Max(0.0, value.ReadyAt - num); if (num2 <= 0f) { return false; } entry = new CooldownEntry { Icon = value.Icon, Remaining = num2, Duration = value.Duration }; return true; } } internal static class CounterUpperSystem { internal static bool TryInterceptSA(Humanoid humanoid) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.CuEnable.Value) { return false; } ItemData currentWeapon = humanoid.GetCurrentWeapon(); if (!CounterUpperFilter.Matches(currentWeapon)) { return false; } Character val = (Character)humanoid; if (!val.IsOwner()) { return false; } Player val2 = (Player)(object)((humanoid is Player) ? humanoid : null); if (val2 == null) { return false; } if ((int)Plugin.SpecialKey.Value != 0 && !SpecialInput.Active) { return false; } if (Plugin.CuMinSkillLevel.Value > 0f && ((Character)val2).GetSkillLevel((SkillType)11) < Plugin.CuMinSkillLevel.Value) { return false; } SharedData shared = currentWeapon.m_shared; Sprite icon = ((shared != null && shared.m_icons?.Length > 0) ? currentWeapon.m_shared.m_icons[0] : null); if (!CounterUpperCooldown.TryConsume(val, Plugin.CuCooldown.Value, icon)) { return false; } SaVfx.PlayAdrenaline1(((Component)val2).transform.position); CounterUpperController.Begin(humanoid, currentWeapon); Plugin.Log.LogInfo((object)"[CU] SA 차단 → 더킹+어퍼컷 시작"); return true; } } internal sealed class CounterUpperController : MonoBehaviour { private static readonly FieldInfo _fInDodge = AccessTools.Field(typeof(Player), "m_inDodge"); private static readonly FieldInfo _fDodgeInvincible = AccessTools.Field(typeof(Player), "m_dodgeInvincible"); private static readonly FieldInfo _fDodgeInvincCached = AccessTools.Field(typeof(Player), "m_dodgeInvincibleCached"); private static readonly FieldInfo _fAnimBase = AccessTools.Field(typeof(Attack), "m_attackAnimation"); private static readonly FieldInfo _fZsyncAnimator = AccessTools.Field(typeof(ZSyncAnimation), "m_animator"); private static readonly int _hashDodge = Animator.StringToHash("dodge"); private const string UppercutTrigger = "RightPowerUppercut_TW"; private Humanoid _humanoid; private Player _player; private Animator _animator; private ZSyncAnimation _zsync; internal bool IsActive; internal bool IsInDuck; internal bool CounterReady; internal bool IsFiringNext; internal static CounterUpperController Begin(Humanoid humanoid, ItemData weapon) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)humanoid).gameObject; CounterUpperController component = gameObject.GetComponent<CounterUpperController>(); if ((Object)(object)component != (Object)null) { ((MonoBehaviour)component).StopAllCoroutines(); component.ForceCleanup(); } CounterUpperController counterUpperController = component ?? gameObject.AddComponent<CounterUpperController>(); counterUpperController.Setup(humanoid, weapon); return counterUpperController; } private void Setup(Humanoid humanoid, ItemData weapon) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) _humanoid = humanoid; _player = (Player)(object)((humanoid is Player) ? humanoid : null); IsActive = true; _zsync = ((Component)humanoid).GetComponentInChildren<ZSyncAnimation>(); _animator = (Animator)((_fZsyncAnimator != null && (Object)(object)_zsync != (Object)null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)((Component)humanoid).GetComponentInChildren<Animator>())); ((MonoBehaviour)this).StartCoroutine(DuckThenUppercut()); } private IEnumerator DuckThenUppercut() { IsInDuck = false; CounterReady = false; if ((Object)(object)_player != (Object)null) { Animator animator = _animator; if (animator != null) { animator.SetTrigger(_hashDodge); } _fInDodge?.SetValue(_player, true); IsInDuck = true; Plugin.Log.LogInfo((object)"[CU] 더킹 시작"); } yield return (object)new WaitForSeconds(Plugin.CuDodgeTime.Value); _fInDodge?.SetValue(_player, false); float remaining = Plugin.CuDuckTime.Value - Plugin.CuDodgeTime.Value; if (remaining > 0f) { yield return (object)new WaitForSeconds(remaining); } if ((Object)(object)_player != (Object)null) { IsInDuck = false; Plugin.Log.LogInfo((object)$"[CU] 더킹 종료 — counter={CounterReady}"); } yield return (object)new WaitForSeconds(0.05f); if ((Object)(object)_humanoid == (Object)null || !IsActive) { yield break; } Character ch = (Character)_humanoid; IsFiringNext = true; bool started = ch.StartAttack((Character)null, false); IsFiringNext = false; Plugin.Log.LogInfo((object)$"[CU] 어퍼컷 StartAttack={started}"); if (started) { yield return null; while (ch.InAttack()) { if ((Object)(object)_zsync != (Object)null) { _zsync.SetSpeed(Plugin.CuUppercutSpeed.Value); } yield return null; } ZSyncAnimation zsync = _zsync; if (zsync != null) { zsync.SetSpeed(1f); } } IsActive = false; } internal void OverrideAnimTrigger(Attack attack) { if ((Object)(object)_zsync == (Object)null || !IsActive) { return; } string text = ((_fAnimBase != null) ? ((string)_fAnimBase.GetValue(attack)) : null); if (!string.IsNullOrEmpty(text) && (Object)(object)_animator != (Object)null) { _animator.ResetTrigger(text); for (int i = 0; i < 4; i++) { _animator.ResetTrigger(text + i); } } _zsync.SetTrigger("RightPowerUppercut_TW"); Plugin.Log.LogInfo((object)string.Format("[CU-Anim] → {0} (animBase={1} counter={2})", "RightPowerUppercut_TW", text, CounterReady)); } internal void ForceCleanup() { IsActive = false; IsInDuck = false; IsFiringNext = false; CounterReady = false; ZSyncAnimation zsync = _zsync; if (zsync != null) { zsync.SetSpeed(1f); } if ((Object)(object)_player != (Object)null) { _fInDodge?.SetValue(_player, false); } } private void OnDestroy() { ForceCleanup(); } } [HarmonyPatch(typeof(Character), "Damage")] internal static class CounterUpper_Patch_DodgeDetect { private static void Prefix(Character __instance, HitData hit) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Player.m_localPlayer == (Object)null) && (object)__instance == Player.m_localPlayer) { CounterUpperController component = ((Component)Player.m_localPlayer).GetComponent<CounterUpperController>(); if (!((Object)(object)component == (Object)null) && component.IsInDuck && !(hit.m_attacker == ((Character)Player.m_localPlayer).GetZDOID())) { hit.m_damage.m_damage = 0f; hit.m_damage.m_blunt = 0f; hit.m_damage.m_slash = 0f; hit.m_damage.m_pierce = 0f; hit.m_damage.m_chop = 0f; hit.m_damage.m_pickaxe = 0f; hit.m_damage.m_fire = 0f; hit.m_damage.m_frost = 0f; hit.m_damage.m_lightning = 0f; hit.m_damage.m_poison = 0f; hit.m_damage.m_spirit = 0f; component.CounterReady = true; Plugin.Log.LogInfo((object)"[CU] 카운터 판정 성공 — 피격 차단"); } } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class CounterUpper_Patch_ApplyMult { private static void Prefix(Character __instance, long sender, ref HitData hit) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) if (!((Object)(object)Player.m_localPlayer == (Object)null) && !(hit.m_attacker != ((Character)Player.m_localPlayer).GetZDOID())) { CounterUpperController component = ((Component)Player.m_localPlayer).GetComponent<CounterUpperController>(); if (!((Object)(object)component == (Object)null) && component.IsActive && component.CounterReady && !Mathf.Approximately(Plugin.CuCounterMult.Value, 1f)) { ((DamageTypes)(ref hit.m_damage)).Modify(Plugin.CuCounterMult.Value); component.CounterReady = false; Plugin.Log.LogInfo((object)$"[CU] 카운터 데미지 ×{Plugin.CuCounterMult.Value}"); } } } } internal static class ImpactBurstCooldown { private sealed class State { public double ReadyAt; public float Duration; public Sprite Icon; } private static readonly ConditionalWeakTable<Character, State> _states = new ConditionalWeakTable<Character, State>(); internal static bool TryConsume(Character c, float cooldown, Sprite icon = null) { if (cooldown <= 0f) { return true; } State value = _states.GetValue(c, (Character _) => new State()); double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); if (num < value.ReadyAt) { return false; } value.ReadyAt = num + (double)cooldown; value.Duration = cooldown; value.Icon = icon; return true; } internal static bool CollectEntry(Character c, out CooldownEntry entry) { entry = default(CooldownEntry); if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); float num2 = (float)Math.Max(0.0, value.ReadyAt - num); if (num2 <= 0f) { return false; } entry = new CooldownEntry { Icon = value.Icon, Remaining = num2, Duration = value.Duration }; return true; } } internal static class ImpactBurstFilter { internal static bool Matches(ItemData weapon) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 if (weapon?.m_shared == null) { return false; } SharedData shared = weapon.m_shared; if ((int)shared.m_skillType != 7) { return false; } if ((int)shared.m_itemType != 14) { return false; } GameObject dropPrefab = weapon.m_dropPrefab; string text = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? string.Empty; return text.IndexOf("battleaxe", StringComparison.OrdinalIgnoreCase) >= 0; } } internal static class ImpactBurstSystem { private sealed class ThrownState { public Character Attacker; public ItemData WeaponData; public HitData HitData; } private static readonly ConditionalWeakTable<Projectile, ThrownState> _thrown = new ConditionalWeakTable<Projectile, ThrownState>(); private static readonly Collider[] _hitBuf = (Collider[])(object)new Collider[64]; private static readonly HashSet<GameObject> _hitSet = new HashSet<GameObject>(); private static int _maskChars; private static bool _pending; private static Player _pendingPlayer; private static ItemData _pendingWeapon; private static GameObject _cachedCarrier; private static readonly string[] _vfxNames = new string[3] { "vfx_sledge_iron_hit", "fx_goblinbrute_groundslam", "vfx_sledge_hit" }; private static int GetMaskChars() { if (_maskChars == 0) { _maskChars = LayerMask.GetMask(new string[5] { "character", "character_net", "character_ghost", "hitbox", "character_noenv" }); } return _maskChars; } internal static void QueueTrigger(Humanoid humanoid) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.IbEnable.Value) { return; } ItemData currentWeapon = humanoid.GetCurrentWeapon(); if (!ImpactBurstFilter.Matches(currentWeapon)) { return; } Character val = (Character)humanoid; if (!val.IsOwner()) { return; } Player val2 = (Player)(object)((humanoid is Player) ? humanoid : null); if (!((Object)(object)val2 == (Object)null) && (!(Plugin.IbMinSkillLevel.Value > 0f) || !(((Character)val2).GetSkillLevel((SkillType)7) < Plugin.IbMinSkillLevel.Value)) && !ImpactBurstCooldown.CollectEntry(val, out var _)) { _pending = true; _pendingPlayer = val2; _pendingWeapon = currentWeapon; Animator componentInChildren = ((Component)humanoid).GetComponentInChildren<Animator>(); ZSyncAnimation zAnim = val.GetZAnim(); if (zAnim != null) { zAnim.SetTrigger("OverheadSlashBattleaxe"); } if (componentInChildren != null) { componentInChildren.CrossFade("OverheadSlashBattleaxe", 0.1f, 0, 0f); } Plugin.Log.LogInfo((object)("[IB] Queued | wep=" + currentWeapon.m_shared.m_name)); } } internal static void ExecuteIfQueued(Humanoid humanoid) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (_pending && (object)humanoid == _pendingPlayer) { _pending = false; Character c = (Character)_pendingPlayer; SharedData shared = _pendingWeapon.m_shared; Sprite icon = ((shared != null && shared.m_icons?.Length > 0) ? _pendingWeapon.m_shared.m_icons[0] : null); if (ImpactBurstCooldown.TryConsume(c, Plugin.IbCooldown.Value, icon)) { SaVfx.PlayAdrenaline1(((Component)_pendingPlayer).transform.position); SpawnThrowProjectile(_pendingPlayer, _pendingWeapon); } } } private static void SpawnThrowProjectile(Player player, ItemData weapon) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) Character val = (Character)player; GameObject val2 = FindCarrierPrefab(); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"[IB] 캐리어 프로젝타일 없음 — 빌드 후 재시작 필요"); return; } ItemData val3 = weapon.Clone(); val3.m_equipped = false; ((Humanoid)player).UnequipItem(weapon, false); ((Humanoid)player).GetInventory().RemoveItem(weapon); Vector3 val4 = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform.forward : ((Component)val).transform.forward); Vector3 val5 = val.GetEyePoint() + val4 * 0.6f; Vector3 val6 = val4; float value = Plugin.IbThrowSpeed.Value; HitData val7 = new HitData(); val7.m_damage = val3.GetDamage(); val7.m_skill = (SkillType)7; val7.m_pushForce = val3.m_shared.m_attackForce; val7.m_blockable = false; val7.m_dodgeable = false; val7.m_skillRaiseAmount = 0f; val7.SetAttacker(val); GameObject val8 = Object.Instantiate<GameObject>(val2, val5, Quaternion.LookRotation(val6)); Projectile component = val8.GetComponent<Projectile>(); IProjectile component2 = val8.GetComponent<IProjectile>(); if ((Object)(object)component == (Object)null || component2 == null) { Object.Destroy((Object)(object)val8); ((Humanoid)player).GetInventory().AddItem(val3); Plugin.Log.LogWarning((object)"[IB] Projectile 컴포넌트 없음 — 무기 복원"); return; } ApplyWeaponVisual(val8, val3); component2.Setup(val, val6 * value, 0f, val7, val3, (ItemData)null); component.m_respawnItemOnHit = false; component.m_spawnItem = null; component.m_spawnOnTtl = false; component.m_ttl = Mathf.Max(component.m_ttl, 8f); _thrown.Remove(component); _thrown.Add(component, new ThrownState { Attacker = val, WeaponData = val3, HitData = val7 }); Plugin.Log.LogInfo((object)("[IB] Thrown | wep=" + val3.m_shared.m_name + " prefab=" + ((Object)val2).name)); } internal static void TryTriggerOnHit(Projectile projectile, Vector3 hitPoint, bool water) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)projectile == (Object)null) && _thrown.TryGetValue(projectile, out var value)) { _thrown.Remove(projectile); if (!((Object)(object)value.Attacker == (Object)null) && !value.Attacker.IsDead()) { Vector3 pos = (water ? (hitPoint + Vector3.up * 1f) : (hitPoint + Vector3.up * 0.3f)); DropWeaponItem(value.WeaponData, pos); projectile.m_spawnOnTtl = false; SpawnBurstVFX(hitPoint); ApplyBurst(value, hitPoint); Plugin.Log.LogInfo((object)$"[IB] Burst | origin={hitPoint} radius={Plugin.IbRadius.Value:F2}"); } } } private static void ApplyBurst(ThrownState state, Vector3 origin) { //IL_0061: 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) float num = Mathf.Max(0f, Plugin.IbRadius.Value); float dmgFactor = Mathf.Max(0f, Plugin.IbDamageFactor.Value); float pushFactor = Mathf.Max(0f, Plugin.IbPushFactor.Value); if (num <= 0f) { return; } _hitSet.Clear(); int num2 = Physics.OverlapSphereNonAlloc(origin, num, _hitBuf, GetMaskChars(), (QueryTriggerInteraction)0); for (int i = 0; i < num2; i++) { Collider val = _hitBuf[i]; if ((Object)(object)val == (Object)null) { continue; } GameObject val2 = Projectile.FindHitObject(val); if (!((Object)(object)val2 == (Object)null) && _hitSet.Add(val2)) { Character componentInParent = val2.GetComponentInParent<Character>(); if (!((Object)(object)componentInParent == (Object)null) && componentInParent != state.Attacker && !componentInParent.IsDead() && BaseAI.IsEnemy(state.Attacker, componentInParent) && !componentInParent.InDodge() && !componentInParent.IsDebugFlying()) { ApplyHit(state, componentInParent, origin, dmgFactor, pushFactor); } } } } private static void ApplyHit(ThrownState state, Character target, Vector3 origin, float dmgFactor, float pushFactor) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) DamageTypes damage = ((DamageTypes)(ref state.HitData.m_damage)).Clone(); if (!Mathf.Approximately(dmgFactor, 1f)) { ((DamageTypes)(ref damage)).Modify(dmgFactor); } HitData val = new HitData(); val.m_damage = damage; val.m_skill = (SkillType)7; val.m_pushForce = state.HitData.m_pushForce * pushFactor; val.m_staggerMultiplier = 1f; val.m_blockable = false; val.m_dodgeable = false; val.m_skillRaiseAmount = 0f; val.m_point = target.GetCenterPoint(); Vector3 val2 = Vector3.ProjectOnPlane(target.GetCenterPoint() - origin, Vector3.up); val.m_dir = ((((Vector3)(ref val2)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val2)).normalized : ((Component)state.Attacker).transform.forward); val.SetAttacker(state.Attacker); target.Damage(val); } private static void ApplyWeaponVisual(GameObject projGo, ItemData weapon) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0069: 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) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)weapon?.m_dropPrefab == (Object)null)) { Renderer[] componentsInChildren = projGo.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { val.enabled = false; } GameObject val2 = new GameObject("IB_WeaponVisual"); val2.transform.SetParent(projGo.transform); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; CopyMeshRenderers(weapon.m_dropPrefab, val2.transform); ImpactBurstWeaponSpin impactBurstWeaponSpin = val2.AddComponent<ImpactBurstWeaponSpin>(); impactBurstWeaponSpin.Initialize(Plugin.IbSpinSpeed.Value); } } private static void CopyMeshRenderers(GameObject source, Transform parent) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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) MeshRenderer[] componentsInChildren = source.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null)) { GameObject val2 = new GameObject(((Object)((Component)val).gameObject).name); val2.transform.SetParent(parent); val2.transform.localPosition = source.transform.InverseTransformPoint(((Component)val).transform.position); val2.transform.localRotation = Quaternion.Inverse(source.transform.rotation) * ((Component)val).transform.rotation; val2.transform.localScale = ((Component)val).transform.lossyScale; MeshFilter val3 = val2.AddComponent<MeshFilter>(); val3.sharedMesh = component.sharedMesh; MeshRenderer val4 = val2.AddComponent<MeshRenderer>(); ((Renderer)val4).sharedMaterials = ((Renderer)val).sharedMaterials; } } } private static void DropWeaponItem(ItemData itemData, Vector3 pos) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)itemData?.m_dropPrefab == (Object)null)) { GameObject val = Object.Instantiate<GameObject>(itemData.m_dropPrefab, pos, Quaternion.identity); ItemDrop component = val.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null)) { component.m_itemData = itemData.Clone(); component.m_itemData.m_stack = 1; component.m_itemData.m_equipped = false; } } } private static GameObject FindCarrierPrefab() { if ((Object)(object)_cachedCarrier != (Object)null) { return _cachedCarrier; } if ((Object)(object)ObjectDB.instance != (Object)null) { string[] array = new string[6] { "SpearFlint", "SpearBronze", "SpearChitin", "SpearWolfFang", "SpearElderbark", "Spear" }; foreach (string text in array) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); GameObject val = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_secondaryAttack?.m_attackProjectile); if ((Object)(object)val != (Object)null) { _cachedCarrier = val; Plugin.Log.LogInfo((object)("[IB] 캐리어: " + ((Object)val).name + " (" + text + " secondary)")); return _cachedCarrier; } } } if ((Object)(object)ZNetScene.instance != (Object)null) { string[] array2 = new string[3] { "projectile_spear", "projectile_spear_chitin", "projectile_knife" }; foreach (string text2 in array2) { GameObject prefab = ZNetScene.instance.GetPrefab(text2); if ((Object)(object)((prefab != null) ? prefab.GetComponent<Projectile>() : null) != (Object)null) { _cachedCarrier = prefab; Plugin.Log.LogInfo((object)("[IB] 캐리어: " + text2 + " (ZNetScene)")); return _cachedCarrier; } } } return null; } private static void SpawnBurstVFX(Vector3 origin) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null) { return; } string[] vfxNames = _vfxNames; foreach (string text in vfxNames) { GameObject prefab = ZNetScene.instance.GetPrefab(text); if (!((Object)(object)prefab == (Object)null)) { Object.Instantiate<GameObject>(prefab, origin, Quaternion.identity); Plugin.Log.LogInfo((object)("[IB VFX] " + text)); break; } } } } internal sealed class ImpactBurstWeaponSpin : MonoBehaviour { private float _spinSpeed; internal void Initialize(float spinSpeed) { _spinSpeed = spinSpeed; } private void Update() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.Rotate(Vector3.right, _spinSpeed * Time.deltaTime, (Space)1); } } internal static class LaunchSlamCooldown { private sealed class State { public double ReadyAt; public float Duration; public Sprite Icon; } private static readonly ConditionalWeakTable<Character, State> _states = new ConditionalWeakTable<Character, State>(); internal static bool TryConsume(Character c, float cooldown, Sprite icon = null) { if (cooldown <= 0f) { return true; } State value = _states.GetValue(c, (Character _) => new State()); double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); if (num < value.ReadyAt) { return false; } value.ReadyAt = num + (double)cooldown; value.Duration = cooldown; value.Icon = icon; return true; } internal static bool CollectEntry(Character c, out CooldownEntry entry) { entry = default(CooldownEntry); if (!_states.TryGetValue(c, out var value)) { return false; } double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble); float num2 = (float)Math.Max(0.0, value.ReadyAt - num); if (num2 <= 0f) { return false; } entry = new CooldownEntry { Icon = value.Icon, Remaining = num2, Duration = value.Duration }; return true; } } internal static class LaunchSlamFilter { internal static bool Matches(ItemData weapon) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 if (weapon?.m_shared == null) { return false; } SharedData shared = weapon.m_shared; return (int)shared.m_skillType == 3 && (int)shared.m_itemType == 3; } } internal static class LaunchSlamSystem { internal const float MinAirTime = 0.2f; internal const float LandingTimeout = 3f; private static bool _pending; private static ZDOID _pendingAttacker; private static readonly FieldInfo _bodyField = AccessTools.Field(typeof(Character), "m_body"); internal static bool IsApplyingLandingDamage { get; private set; } internal static void OnSecondaryStarted(Humanoid humanoid) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (Plugin.LsEnable.Value && LaunchSlamFilter.Matches(humanoid.GetCurrentWeapon())) { Player val = (Player)(object)((humanoid is Player) ? humanoid : null); if (!((Object)(object)val != (Object)null) || !(Plugin.LsMinSkillLevel.Value > 0f) || !(((Character)val).GetSkillLevel((SkillType)3) < Plugin.LsMinSkillLevel.Value)) { _pending = true; _pendingAttacker = ((Character)humanoid).GetZDOID(); } } } internal static void TryApply(Character target, ref HitData hit) { //IL_002c: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) if (IsApplyingLandingDamage || !_pending || !Plugin.LsEnable.Value || hit.m_attacker != _pendingAttacker || ((DamageTypes)(ref hit.m_damage)).GetTotalDamage() <= 0f || (Object)(object)target == (Object)null || target.IsDead()) { return; } _pending = false; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Character val = (Character)localPlayer; if (target == val) { return; } ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon(); Sprite icon = ((currentWeapon != null && currentWeapon.m_shared?.m_icons?.Length > 0) ? currentWeapon.m_shared.m_icons[0] : null); if (!LaunchSlamCooldown.TryConsume(val, Plugin.LsCooldown.Value, icon)) { return; } float num = Mathf.Max(0f, Plugin.LsLaunchHeight.Value); if (!(num <= 0f)) { DamageTypes landingDamage = ((DamageTypes)(ref hit.m_damage)).Clone(); ((DamageTypes)(ref landingDamage)).Modify(Mathf.Max(0f, Plugin.LsDamageFactor.Value)); if (!(((DamageTypes)(ref landingDamage)).GetTotalDamage() <= 0f) && TryLaunchTarget(target, num)) { hit.m_pushForce = 0f; LaunchSlamLandingTracker launchSlamLandingTracker = ((Component)target).GetComponent<LaunchSlamLandingTracker>() ?? ((Component)target).gameObject.AddComponent<LaunchSlamLandingTracker>(); launchSlamLandingTracker.Initialize(target, val, hit, landingDamage, num); SaVfx.PlayAdrenaline1(((Component)val).transform.position); } } } private static bool TryLaunchTarget(Character target, float liftHeight) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (!target.IsOwner()) { return false; } object? obj = _bodyField?.GetValue(target); Rigidbody val = (Rigidbody)(((obj is Rigidbody) ? obj : null) ?? ((Component)target).GetComponent<Rigidbody>()); if ((Object)(object)val == (Object)null) { return false; } if (val.isKinematic) { val.isKinematic = false; } float num = Mathf.Abs(Physics.gravity.y) * 25f; float num2 = Mathf.Sqrt(2f * num * liftHeight); Vector3 linearVelocity = val.linearVelocity; linearVelocity.y = Mathf.Max(linearVelocity.y, num2); val.linearVelocity = linearVelocity; return true; } internal static void ApplyLandingDamage(Character target, Character attacker, HitData sourceHit, DamageTypes landingDamage) { //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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null || (Object)(object)attacker == (Object)null || target.IsDead() || ((DamageTypes)(ref landingDamage)).GetTotalDamage() <= 0f) { return; } Vector3 position = ((Component)target).transform.position; float value = Plugin.LsLandingRadius.Value; List<Character> list = GatherLandingTargets(target, attacker, position, value); if (list.Count == 0) { return; } IsApplyingLandingDamage = true; try { foreach (Character item in list) { ApplyLandingHit(item, attacker, sourceHit, landingDamage, position); } } finally { IsApplyingLandingDamage = false; } } private static List<Character> GatherLandingTargets(Character source, Character attacker, Vector3 origin, float radius) { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) List<Character> list = new List<Character>(); HashSet<Character> hashSet = new HashSet<Character>(); if (!source.IsDead()) { hashSet.Add(source); list.Add(source); } if (radius <= 0f) { return list; } foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsDead() && allCharacter != source && allCharacter != attacker && hashSet.Add(allCharacter) && (BaseAI.IsEnemy(attacker, allCharacter) || (attacker.IsPlayer() && (Object)(object)allCharacter.GetBaseAI() != (Object)null && allCharacter.GetBaseAI().IsAggravatable()))) { Vector3 val = allCharacter.GetCenterPoint() - origin; val.y = 0f; if (((Vector3)(ref val)).magnitude <= radius) { list.Add(allCharacter); } } } return list; } private static void ApplyLandingHit(Character target, Character attacker, HitData sourceHit, DamageTypes landingDamage, Vector3 origin) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && !target.IsDead()) { HitData val = sourceHit.Clone(); val.m_damage = ((DamageTypes)(ref landingDamage)).Clone(); val.m_pushForce = 0f; val.m_staggerMultiplier = 0f; val.m_skillRaiseAmount = 0f; val.m_blockable = false; val.m_dodgeable = false; val.m_point = target.GetCenterPoint(); Vector3 val2 = target.GetCenterPoint() - origin; val2.y = 0f; val.m_dir = ((((Vector3)(ref val2)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val2)).normalized : Vector3.down); val.m_hitCollider = null; val.SetAttacker(attacker); target.Damage(val); } } } internal sealed class LaunchSlamLandingTracker : MonoBehaviour { private Character _target; private Character _attacker; private HitData _sourceHit; private DamageTypes _landingDamage = default(DamageTypes); private float _startTime; private float _startHeight; private float _targetApexHeight; private bool _hasBeenAirborne; internal void Initialize(Character target, Character attacker, HitData sourceHit, DamageTypes landingDamage, float launchHeight) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (_sourceHit == null || !(((DamageTypes)(ref landingDamage)).GetTotalDamage() <= ((DamageTypes)(ref _landingDamage)).GetTotalDamage())) { Plugin.Log.LogInfo((object)$"[LS] Tracker Initialize: target={((target != null) ? ((Object)target).name : null)} startY={((target != null) ? new float?(((Component)target).transform.position.y) : ((float?)null)):F2}"); _target = target; _attacker = attacker; _sourceHit = sourceHit.Clone(); _landingDamage = ((DamageTypes)(ref landingDamage)).Clone(); _targetApexHeight = ((Component)target).transform.position.y + Mathf.Max(0f, launchHeight); _startTime = Time.time; _startHeight = ((Component)target).transform.position.y; _hasBeenAirborne = false; ((Behaviour)this).enabled = true; } } private void Update() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_target == (Object)null || (Object)(object)_attacker == (Object)null || _target.IsDead()) { Object.Destroy((Object)(object)this); return; } if (Time.time - _startTime > 3f) { Plugin.Log.LogInfo((object)$"[LS] Tracker timeout. airborne={_hasBeenAirborne} y={((Component)_target).transform.position.y:F2} startY={_startHeight:F2}"); Object.Destroy((Object)(object)this); return; } float y = ((Component)_target).transform.position.y; if (y > _startHeight + 0.5f) { _hasBeenAirborne = true; } if (_hasBeenAirborne && !(Time.time - _startTime < 0.2f) && y <= _startHeight + 0.5f) { Plugin.Log.LogInfo((object)$"[LS] Landing! y={y:F2} startY={_startHeight:F2}"); LaunchSlamSystem.ApplyLandingDamage(_target, _attacker, _sourceHit, _landingDamage); Object.Destroy((Object)(object)this); } } } [BepInPlugin("com.specialattack.plugin", "SpecialAttack", "1.0.0")] [BepInProcess("valheim.exe")] public class Plugin : BaseUnityPlugin { public const string GUID = "com.specialattack.plugin"; public const string NAME = "SpecialAttack"; public const string VERSION = "1.0.0"; private readonly Harmony _harmony = new Harmony("com.specialattack.plugin"); internal static ManualLogSource Log; internal static ConfigEntry<bool> EnableBattleHammer; internal static ConfigEntry<float> Cooldown; internal static ConfigEntry<float> LoopStart; internal static ConfigEntry<float> LoopEnd; internal static ConfigEntry<float> AnimationSpeed; internal static ConfigEntry<float> BattleHammerMoveSpeedFactor; internal static ConfigEntry<float> SkillRaiseFactor; internal static ConfigEntry<float> SsMinSkillLevel; internal static ConfigEntry<bool> KcEnable; internal static ConfigEntry<float> KcCooldown; internal static ConfigEntry<float> KcMinSkillLevel; internal static ConfigEntry<float> KcPushFactor; internal static ConfigEntry<int> KcMaxChainTargets; internal static ConfigEntry<float> KcCollisionRadius; internal static ConfigEntry<float> KcChainDecay; internal static ConfigEntry<float> KcChainDamageFactor; internal static ConfigEntry<bool> LsEnable; internal static ConfigEntry<float> LsCooldown; internal static ConfigEntry<float> LsMinSkillLevel; internal static ConfigEntry<float> LsLaunchHeight; internal static ConfigEntry<float> LsDamageFactor; internal static ConfigEntry<float> LsLandingRadius; internal static ConfigEntry<bool> SaEnable; internal static ConfigEntry<float> SaCooldown; internal static ConfigEntry<float> SaMinSkillLevel; internal static ConfigEntry<float> SaChargeTime; internal static ConfigEntry<float> SaChargeSpeedFactor; internal static ConfigEntry<float> SaAggroResetRadius; internal static ConfigEntry<float> SaBackstabBonus; internal static ConfigEntry<bool> AsEnable; internal static ConfigEntry<float> AsCooldown; internal static ConfigEntry<float> AsMinSkillLevel; internal static ConfigEntry<int> AsWaves; internal static ConfigEntry<float> AsInterval; internal static ConfigEntry<float> AsWaveDecay; internal static ConfigEntry<float> AsForwardStep; internal static ConfigEntry<float> AsRadius; internal static ConfigEntry<float> AsDamageFactor; internal static ConfigEntry<float> AsPushForce; internal static ConfigEntry<bool> QsEnable; internal static ConfigEntry<float> QsCooldown; internal static ConfigEntry<float> QsMinSkillLevel; internal static ConfigEntry<float> QsAnimSpeed1; internal static ConfigEntry<float> QsAnimSpeed2; internal static ConfigEntry<float> QsAnimSpeed3; internal static ConfigEntry<float> QsAnimSpeed4; internal static ConfigEntry<float> QsDamage1; internal static ConfigEntry<float> QsDamage2; internal static ConfigEntry<float> QsDamage3; internal static ConfigEntry<float> QsDamage4; internal static ConfigEntry<bool> CuEnable; internal static ConfigEntry<float> CuCooldown; internal static ConfigEntry<float> CuMinSkillLevel; internal static ConfigEntry<float> CuDuckTime; internal static ConfigEntry<float> CuCounterMult; internal static ConfigEntry<float> CuUppercutSpeed; internal static ConfigEntry<float> CuDodgeTime; internal static ConfigEntry<bool> IbEnable; internal static ConfigEntry<float> IbCooldown; internal static ConfigEntry<float> IbMinSkillLevel; internal static ConfigEntry<float> IbDamageFactor; internal static ConfigEntry<float> IbPushFactor; internal static ConfigEntry<float> IbRadius; internal static ConfigEntry<float> IbThrowSpeed; internal static ConfigEntry<float> IbSpinSpeed; internal static ConfigEntry<bool> ScEnable; internal stati