using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using AIGraph; using AK; using AccurateCrosshair.API; using Agents; using AmorLib.Utils; using AssetShards; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Hook; using BepInEx.Unity.IL2CPP.Utils.Collections; using CharacterDestruction; using CullingSystem; using DamSync; using EEC.CustomAbilities.Bleed; using EWC.API; using EWC.Attributes; using EWC.CustomWeapon; using EWC.CustomWeapon.ComponentWrapper; using EWC.CustomWeapon.ComponentWrapper.OwnerComps; using EWC.CustomWeapon.ComponentWrapper.WeaponComps; using EWC.CustomWeapon.CustomShot; using EWC.CustomWeapon.Enums; using EWC.CustomWeapon.HitTracker; using EWC.CustomWeapon.ObjectWrappers; using EWC.CustomWeapon.Properties; using EWC.CustomWeapon.Properties.Effects; using EWC.CustomWeapon.Properties.Effects.Debuff; using EWC.CustomWeapon.Properties.Effects.Heal; using EWC.CustomWeapon.Properties.Effects.Hit.CustomFoam; using EWC.CustomWeapon.Properties.Effects.Hit.DOT; using EWC.CustomWeapon.Properties.Effects.Hit.DOT.DOTGlowFX; using EWC.CustomWeapon.Properties.Effects.Hit.Explosion; using EWC.CustomWeapon.Properties.Effects.Hit.Explosion.EEC_ExplosionFX; using EWC.CustomWeapon.Properties.Effects.Hit.Explosion.EEC_ExplosionFX.Handlers; using EWC.CustomWeapon.Properties.Effects.Infection; using EWC.CustomWeapon.Properties.Effects.PlayerPush; using EWC.CustomWeapon.Properties.Effects.ShrapnelHit; using EWC.CustomWeapon.Properties.Effects.Speed; using EWC.CustomWeapon.Properties.Effects.Stamina; using EWC.CustomWeapon.Properties.Effects.TriggerModifier; using EWC.CustomWeapon.Properties.Shared.Triggers; using EWC.CustomWeapon.Properties.Traits; using EWC.CustomWeapon.Properties.Traits.CustomProjectile; using EWC.CustomWeapon.Properties.Traits.CustomProjectile.Components; using EWC.CustomWeapon.Properties.Traits.CustomProjectile.Managers; using EWC.CustomWeapon.Structs; using EWC.CustomWeapon.WeaponContext; using EWC.CustomWeapon.WeaponContext.Attributes; using EWC.CustomWeapon.WeaponContext.Contexts; using EWC.CustomWeapon.WeaponContext.Contexts.Base; using EWC.Dependencies; using EWC.JSON; using EWC.JSON.Converters; using EWC.Networking; using EWC.Networking.Structs; using EWC.Patches.Checkpoint; using EWC.Patches.Enemy; using EWC.Patches.Gun; using EWC.Patches.Melee; using EWC.Patches.Player; using EWC.Utils; using EWC.Utils.Extensions; using EWC.Utils.Structs; using EndskApi.Api; using Enemies; using ExtraRecoilData.API; using ExtraToolCustomization.ToolData; using FX_EffectSystem; using FirstPersonItem; using GTFO.API; using GTFO.API.JSON.Converters; using GTFO.API.Utilities; using GTFuckingXP.Enums; using GTFuckingXP.Extensions; using GTFuckingXP.Information.Level; using GameData; using GameEvent; using Gear; using Globals; using HarmonyLib; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.Runtime; using Il2CppSystem; using Il2CppSystem.Collections; using Il2CppSystem.Collections.Generic; using KillIndicatorFix; using LevelGeneration; using MTFO.API; using Microsoft.CodeAnalysis; using ModifierAPI; using Player; using SNetwork; using StateMachines; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ExtraWeaponCustomization")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+cce96cb355a56b0d939489aa44aa8bcaab54a8ff")] [assembly: AssemblyProduct("ExtraWeaponCustomization")] [assembly: AssemblyTitle("ExtraWeaponCustomization")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace EWC { internal static class Configuration { private static readonly ConfigEntry _showExplosionEffect; private static readonly ConfigEntry _playExplosionSFX; private static readonly ConfigEntry _explosionSFXCooldown; private static readonly ConfigEntry _explosionSFXShotOverride; private static readonly ConfigEntry _playExplosionShake; private static readonly ConfigEntry _keybind1; private static readonly ConfigEntry _keybind2; private static readonly ConfigEntry _keybind3; private static readonly ConfigEntry _keybind4; private static readonly ConfigEntry _autoAimTickDelay; private static readonly ConfigEntry _homingTickDelay; private static readonly ConfigFile configFile; private static ConfigEntry ForceCreateTemplate { get; set; } public static bool ShowExplosionEffect => _showExplosionEffect.Value; public static bool PlayExplosionSFX => _playExplosionSFX.Value; public static float ExplosionSFXCooldown => _explosionSFXCooldown.Value; public static int ExplosionSFXShotOverride => _explosionSFXShotOverride.Value; public static bool PlayExplosionShake => _playExplosionShake.Value; public static KeyCode Keybind1 => _keybind1.Value; public static KeyCode Keybind2 => _keybind2.Value; public static KeyCode Keybind3 => _keybind3.Value; public static KeyCode Keybind4 => _keybind4.Value; public static float AutoAimTickDelay => _autoAimTickDelay.Value; public static float HomingTickDelay => _homingTickDelay.Value; static Configuration() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "ExtraWeaponCustomization.cfg"), true); string text = "Auto Aim Settings"; _autoAimTickDelay = configFile.Bind(text, "Search Cooldown", 0.1f, "Time between attempted searches to acquire targets."); text = "Explosion Settings"; _showExplosionEffect = configFile.Bind(text, "Show Effect", true, "Enables explosion visual FX."); _playExplosionSFX = configFile.Bind(text, "Play Sound", true, "Enables explosion sound FX."); _explosionSFXCooldown = configFile.Bind(text, "SFX Cooldown", 0.08f, "Minimum time between explosion sound effects, to prevent obnoxiously loud sounds."); _explosionSFXShotOverride = configFile.Bind(text, "Shots to Override SFX Cooldown", 8, "Amount of shots fired before another explosion sound effect is forced, regardless of cooldown.\nSmaller numbers let fast-firing weapons and shotguns make more sounds in a short span of time."); _playExplosionShake = configFile.Bind(text, "Play Screen Shake", true, "Enables explosion screen shake. Doesn't bypass the global screen shake settings modifier."); text = "Keybind Settings"; _keybind1 = configFile.Bind(text, "Keybind 1", (KeyCode)118, "A mappable keybind used to trigger properties.\nIf changed while in a level, requires re-drop/reloading weapon properties to update."); _keybind2 = configFile.Bind(text, "Keybind 2", (KeyCode)98, "A mappable keybind used to trigger properties.\nIf changed while in a level, requires re-drop/reloading weapon properties to update."); _keybind3 = configFile.Bind(text, "Keybind 3", (KeyCode)120, "A mappable keybind used to trigger properties.\nIf changed while in a level, requires re-drop/reloading weapon properties to update."); _keybind4 = configFile.Bind(text, "Keybind 4", (KeyCode)122, "A mappable keybind used to trigger properties.\nIf changed while in a level, requires re-drop/reloading weapon properties to update."); text = "Projectile Settings"; _homingTickDelay = configFile.Bind(text, "Homing Search Cooldown", 0.1f, "Minimum time between attempted searches to acquire a new target."); text = "Tools"; ForceCreateTemplate = configFile.Bind(text, "Force Create Template", false, "Creates the template file again."); CheckAndRefreshTemplate(); } [InvokeOnLoad] private static void Init() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown LiveEdit.CreateListener(Paths.ConfigPath, "ExtraWeaponCustomization.cfg", false).FileChanged += new LiveEditEventHandler(OnFileChanged); } private static void OnFileChanged(LiveEditEventArgs _) { configFile.Reload(); CheckAndRefreshTemplate(); } private static void CheckAndRefreshTemplate() { if (ForceCreateTemplate.Value) { ForceCreateTemplate.Value = false; CustomDataManager.Current.CreateTemplate(); configFile.Save(); } } } [BepInPlugin("Dinorush.ExtraWeaponCustomization", "ExtraWeaponCustomization", "4.11.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal sealed class EntryPoint : BasePlugin { public const string MODNAME = "ExtraWeaponCustomization"; private IEnumerable _cleanupCallbacks; private IEnumerable _checkpointCleanupCallbacks; private IEnumerable _checkpointCallbacks; private IEnumerable _enterCallbacks; private IEnumerable _buildDoneCallbacks; public static bool Loaded { get; private set; } public override void Load() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!MTFOAPIWrapper.HasCustomContent) { EWCLogger.Error("No MTFO datablocks detected. Not loading EWC..."); return; } Loaded = true; new Harmony("ExtraWeaponCustomization").PatchAll(); CacheFrequentCallbacks(); InvokeCallbacks(); SyncManagerPatches.OnCheckpointReload += RunFrequentCallback(_checkpointCleanupCallbacks); SyncManagerPatches.OnCheckpointReload += RunFrequentCallback(_checkpointCallbacks); LevelAPI.OnLevelCleanup += RunFrequentCallback(_cleanupCallbacks); LevelAPI.OnEnterLevel += RunFrequentCallback(_enterCallbacks); LevelAPI.OnBuildDone += RunFrequentCallback(_buildDoneCallbacks); AssetAPI.OnStartupAssetsLoaded += AssetAPI_OnStartupAssetsLoaded; EWCLogger.Log("Loaded ExtraWeaponCustomization"); } private static Action RunFrequentCallback(IEnumerable callbacks) { IEnumerable callbacks2 = callbacks; return delegate { foreach (MethodInfo item in callbacks2) { item.Invoke(null, null); } }; } private void AssetAPI_OnStartupAssetsLoaded() { InvokeCallbacks(); RuntimeHelpers.RunClassConstructor(typeof(CustomDataManager).TypeHandle); } private void CacheFrequentCallbacks() { IEnumerable source = from method in ((IEnumerable)AccessTools.GetTypesFromAssembly(((object)this).GetType().Assembly)).SelectMany((Func>)AccessTools.GetDeclaredMethods) where method.IsStatic select method; var source2 = from method in source let attr = method.GetCustomAttribute() where attr != null select new { Method = method, Attribute = attr }; _cleanupCallbacks = source2.Select(pair => pair.Method); _checkpointCleanupCallbacks = from pair in source2 where pair.Attribute.OnCheckpoint select pair.Method; _checkpointCallbacks = source.Where((MethodInfo method) => method.GetCustomAttribute() != null); _enterCallbacks = source.Where((MethodInfo method) => method.GetCustomAttribute() != null); _buildDoneCallbacks = source.Where((MethodInfo method) => method.GetCustomAttribute() != null); } private void InvokeCallbacks() where T : Attribute { foreach (MethodInfo item in from method in ((IEnumerable)AccessTools.GetTypesFromAssembly(((object)this).GetType().Assembly)).SelectMany((Func>)AccessTools.GetDeclaredMethods) where method.GetCustomAttribute() != null where method.IsStatic select method) { item.Invoke(null, null); } } } internal static class EWCLogger { private static ManualLogSource logger = Logger.CreateLogSource("ExtraWeaponCustomization"); public static void Log(string format, params object[] args) { Log(string.Format(format, args)); } public static void Log(string str) { if (logger != null) { logger.Log((LogLevel)8, (object)str); } } public static void Warning(string format, params object[] args) { Warning(string.Format(format, args)); } public static void Warning(string str) { if (logger != null) { logger.Log((LogLevel)4, (object)str); } } public static void Error(string format, params object[] args) { Error(string.Format(format, args)); } public static void Error(string str) { if (logger != null) { logger.Log((LogLevel)2, (object)str); } } public static void Debug(string format, params object[] args) { Debug(string.Format(format, args)); } public static void Debug(string str) { if (logger != null) { logger.Log((LogLevel)32, (object)str); } } } } namespace EWC.Utils { public static class CopyUtil { public static T Clone(T obj, params object?[]? args) where T : notnull { return CopyUtil.Clone(obj, args); } } public static class CopyUtil where T : notnull { private static readonly Dictionary> _classProperties = new Dictionary>(); public static T Clone(T obj, params object?[]? args) { Type type = obj.GetType(); if (!_classProperties.ContainsKey(type)) { List list = new List(); _classProperties.Add(type, list); Type type2 = type; while (type2.BaseType != null) { PropertyInfo[] properties = type2.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo propertyInfo in properties) { MethodInfo? getMethod = propertyInfo.GetGetMethod(nonPublic: false); MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if (!(getMethod == null) && !(setMethod == null) && !setMethod.IsPublic && propertyInfo.CanWrite) { list.Add(propertyInfo); } } type2 = type2.BaseType; } if (type.IsAssignableTo(typeof(ISyncProperty))) { list.Add(type.GetProperty("SyncPropertyID")); } } T val = (T)Activator.CreateInstance(type, args); foreach (PropertyInfo item in _classProperties[type]) { item.SetValue(val, item.GetValue(obj)); } return val; } } internal static class CoroutineUtil { public static bool Stop(ref Coroutine? routine, MonoBehaviour? parent = null) { if (routine != null) { if ((Object)(object)parent == (Object)null) { CoroutineManager.StopCoroutine(routine); } else { parent.StopCoroutine(routine); } routine = null; return true; } return false; } } internal static class DamageableUtil { private static IntPtr _cachedExpedition = default(IntPtr); private static float _cachedHealth = 15f; public static float LockHealth { get { if (RundownManager.ActiveExpedition != null && ((Il2CppObjectBase)RundownManager.ActiveExpedition).Pointer != _cachedExpedition) { _cachedExpedition = ((Il2CppObjectBase)RundownManager.ActiveExpedition).Pointer; _cachedHealth = RundownManager.ActiveExpeditionBalanceData.WeakDoorLockHealth; } return _cachedHealth; } } public static IDamageable? GetDamageableFromRayHit(RaycastHit rayHit) { return GetDamageableFromCollider(((RaycastHit)(ref rayHit)).collider); } public static IDamageable? GetDamageableFromCollider(Collider? collider) { if (!((Object)(object)collider == (Object)null)) { return GetDamageableFromGO(((Component)collider).gameObject); } return null; } public static IDamageable? GetDamageableFromGO(GameObject? go) { if ((Object)(object)go == (Object)null) { return null; } ColliderMaterial component = go.GetComponent(); IDamageable val = ((component != null) ? component.Damageable : null); if (val != null) { return val; } return go.GetComponent(); } public static bool IsValid([NotNullWhen(true)] this IDamageable? damageable) { if (damageable == null) { return false; } if (!((Object)(object)damageable.GetBaseAgent() != (Object)null)) { return (Object)(object)((Il2CppObjectBase)damageable).TryCast() == (Object)null; } return true; } public static bool IsEnemy([NotNullWhen(true)] this IDamageable? damageable) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if (damageable == null) { return false; } Agent baseAgent = damageable.GetBaseAgent(); if ((Object)(object)baseAgent != (Object)null && baseAgent.Alive) { return (int)baseAgent.Type == 1; } return false; } } public sealed class DelayedCallback { [CompilerGenerated] private sealed class d__16 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DelayedCallback <>4__this; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown int num = <>1__state; DelayedCallback delayedCallback = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; delayedCallback._onStart?.Invoke(); break; case 1: <>1__state = -1; break; } float num2; if ((num2 = delayedCallback._endTime - Clock.Time) > 0f) { <>2__current = (object)new WaitForSeconds(num2); <>1__state = 1; return true; } delayedCallback._routine = null; delayedCallback._onEnd?.Invoke(); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly float _delay; private readonly Func? _getDelay; private readonly Action? _onStart; private readonly Action? _onRefresh; private readonly Action? _onEnd; private float _endTime; private Coroutine? _routine; public bool Active { get { if (_endTime > Clock.Time) { return _routine != null; } return false; } } public DelayedCallback(Func getDelay, Action? onEnd) : this(getDelay, null, null, onEnd) { } public DelayedCallback(Func getDelay, Action? onStart, Action? onEnd) : this(getDelay, onStart, null, onEnd) { } public DelayedCallback(Func getDelay, Action? onStart, Action? onRefresh, Action? onEnd) { _getDelay = getDelay; _onStart = onStart; _onRefresh = onRefresh; _onEnd = onEnd; } public DelayedCallback(float delay, Action? onEnd) : this(delay, null, null, onEnd) { } public DelayedCallback(float delay, Action? onStart, Action? onEnd) : this(delay, onStart, null, onEnd) { } public DelayedCallback(float delay, Action? onStart, Action? onRefresh, Action? onEnd) { _delay = delay; _onStart = onStart; _onRefresh = onRefresh; _onEnd = onEnd; } public void Start(bool checkEnd = false, bool refresh = true) { bool active = Active; if (!refresh && active) { return; } float num = _getDelay?.Invoke() ?? _delay; if (num == 0f) { _onStart?.Invoke(); _onEnd?.Invoke(); return; } _endTime = Clock.Time + num; if (checkEnd && !active && _routine != null) { _onEnd?.Invoke(); _onStart?.Invoke(); } else if (_routine == null) { _routine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(Update()), (Action)null); } else { _onRefresh?.Invoke(); } } [IteratorStateMachine(typeof(d__16))] public IEnumerator Update() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__16(0) { <>4__this = this }; } public void Stop() { if (CoroutineUtil.Stop(ref _routine)) { _onEnd?.Invoke(); } } public void Cancel() { CoroutineUtil.Stop(ref _routine); } public bool CheckEnd() { if (_routine == null) { return true; } if (!Active && CoroutineUtil.Stop(ref _routine)) { _onEnd?.Invoke(); return true; } return false; } } public sealed class HitData { public float damage; public Vector2 damageFalloff; public float falloff = 1f; public int pierceLimit; public float precisionMulti; public float staggerMulti; public float maxRayDist; public float randomSpread; public float angOffsetX; public float angOffsetY; public PlayerAgent? owner; public Vector3 fireDir; public Vector3 hitPos; public IDamageable? damageable; public GameObject? gameObject; private RaycastHit _rayHit; public ShotInfo shotInfo; private readonly DamageType _baseDamageType; public DamageType damageType; private WeaponHitData? _weaponHitData; private MeleeWeaponFirstPerson? _meleeWeapon; public RaycastHit RayHit { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _rayHit; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0046: Unknown result type (might be due to invalid IL or missing references) _rayHit = value; hitPos = ((RaycastHit)(ref _rayHit)).point; gameObject = (((Object)(object)((RaycastHit)(ref _rayHit)).collider != (Object)null) ? ((Component)((RaycastHit)(ref _rayHit)).collider).gameObject : null); damageable = DamageableUtil.GetDamageableFromRayHit(_rayHit); UpdateDamageType(); } } public HitData(WeaponHitData hitData, float additionalDist = 0f) : this(DamageType.Bullet) { Setup(hitData, additionalDist); } public HitData(MeleeWeaponFirstPerson melee, MeleeWeaponDamageData hitData) : this(DamageType.Bullet) { Setup(melee, hitData); } public HitData(HitData data) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) _weaponHitData = data._weaponHitData; _meleeWeapon = data._meleeWeapon; shotInfo = new ShotInfo(data.shotInfo); damage = data.damage; falloff = data.falloff; pierceLimit = data.pierceLimit; damageFalloff = data.damageFalloff; precisionMulti = data.precisionMulti; staggerMulti = data.staggerMulti; randomSpread = data.randomSpread; angOffsetX = data.angOffsetX; angOffsetY = data.angOffsetY; owner = data.owner; fireDir = data.fireDir; maxRayDist = data.maxRayDist; _rayHit = data._rayHit; hitPos = data.hitPos; damageable = data.damageable; gameObject = data.gameObject; damageType = data.damageType; _baseDamageType = data._baseDamageType; } public HitData(DamageType baseDamageType) { _baseDamageType = baseDamageType; shotInfo = new ShotInfo(); } public void Setup(WeaponHitData hitData, float additionalDist = 0f) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) _weaponHitData = hitData; _meleeWeapon = null; shotInfo = ShotManager.GetVanillaShotInfo(hitData); ResetDamage(); damageFalloff = hitData.damageFalloff; randomSpread = hitData.randomSpread; angOffsetX = hitData.angOffsetX; angOffsetY = hitData.angOffsetY; owner = hitData.owner; fireDir = hitData.fireDir; maxRayDist = hitData.maxRayDist; RayHit = hitData.rayHit; falloff = CalcFalloff(additionalDist); } public void Setup(MeleeWeaponFirstPerson melee, MeleeWeaponDamageData hitData) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) _weaponHitData = null; _meleeWeapon = melee; ResetDamage(); falloff = 1f; Vector3 val = hitData.hitPos - hitData.sourcePos; fireDir = ((Vector3)(ref val)).normalized; hitPos = hitData.hitPos; damageable = hitData.damageComp ?? hitData.damageGO.GetComponent(); gameObject = hitData.damageGO; UpdateDamageType(); } public void Apply() { if (_weaponHitData != null) { Apply(_weaponHitData); } else if ((Object)(object)_meleeWeapon != (Object)null) { Apply(_meleeWeapon); } } public WeaponHitData Apply(WeaponHitData hitData) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) hitData.owner = owner; hitData.damage = damage; hitData.damageFalloff = damageFalloff; hitData.precisionMulti = precisionMulti; hitData.staggerMulti = staggerMulti; hitData.randomSpread = randomSpread; hitData.angOffsetX = angOffsetX; hitData.angOffsetY = angOffsetY; hitData.rayHit = RayHit; hitData.fireDir = fireDir; hitData.maxRayDist = maxRayDist; return hitData; } public MeleeWeaponFirstPerson Apply(MeleeWeaponFirstPerson melee) { melee.m_damageToDeal = damage; melee.m_precisionMultiToDeal = precisionMulti; melee.m_staggerMultiToDeal = staggerMulti; return melee; } public void ResetDamage() { damage = shotInfo.OrigDamage; precisionMulti = shotInfo.OrigPrecision; staggerMulti = shotInfo.OrigStagger; } public float CalcRawFalloff(float distance) { return Math.Max(distance.Map(damageFalloff.x, damageFalloff.y, 1f, 0f), BulletWeapon.s_falloffMin); } public float CalcFalloff(float additionalDist = 0f) { //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) RaycastHit rayHit = RayHit; return CalcRawFalloff(((RaycastHit)(ref rayHit)).distance + additionalDist); } public int GetPierceOrFallback(IWeaponComp weapon) { if (pierceLimit == 0) { return weapon.ArchetypeData.PierceLimit(); } return pierceLimit; } private void UpdateDamageType() { if ((Object)(object)gameObject != (Object)null) { damageType = ((damageable != null) ? _baseDamageType.WithSubTypes(damageable) : (_baseDamageType | DamageType.Terrain)); } else { damageType = _baseDamageType | DamageType.Dead; } } public WeaponHitData ToWeaponHitData() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown return new WeaponHitData { damage = damage, damageFalloff = damageFalloff, precisionMulti = precisionMulti, staggerMulti = staggerMulti, randomSpread = randomSpread, angOffsetX = angOffsetX, angOffsetY = angOffsetY, owner = owner, rayHit = RayHit, fireDir = fireDir, maxRayDist = maxRayDist }; } } internal static class JsonUtil { public static float[] ReadPairs(ref Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartArray) { throw new JsonException("Expected list object"); } List list = new List(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndArray) { if (list.Count % 2 != 0) { list.RemoveAt(list.Count - 1); } return list.ToArray(); } if (reader.TokenType == JsonTokenType.StartArray) { reader.Read(); if (reader.TokenType != JsonTokenType.Number) { throw new JsonException("Expected number for x offset"); } list.Add(reader.GetSingle()); reader.Read(); if (reader.TokenType != JsonTokenType.Number) { throw new JsonException("Expected number for y offset"); } list.Add(reader.GetSingle()); reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) { throw new JsonException("Expected EndArray token for [x,y] offset pair"); } } else { if (reader.TokenType != JsonTokenType.Number) { throw new JsonException("Expected number for offset value"); } list.Add(reader.GetSingle()); } } throw new JsonException("Expected EndArray token"); } } public static class LayerUtil { public static int MaskDynamic { get; private set; } public static int MaskEntityAndWorld { get; private set; } public static int MaskEntityAndWorld3P { get; private set; } public static int MaskWorld { get; private set; } public static int MaskWorldExcProj { get; private set; } public static int MaskDecalValid { get; private set; } public static int MaskEntityDynamic3P { get; private set; } public static int MaskEntity { get; private set; } public static int MaskEntity3P { get; private set; } public static int MaskLocal { get; private set; } public static int MaskFriendly { get; private set; } public static int MaskEnemy { get; private set; } public static int MaskEnemyDynamic { get; private set; } [InvokeOnAssetLoad] private static void Init() { MaskLocal = LayerMask.GetMask(new string[1] { "PlayerMover" }); MaskFriendly = LayerMask.GetMask(new string[1] { "PlayerSynced" }); MaskEnemy = LayerMask.GetMask(new string[1] { "EnemyDamagable" }); MaskDynamic = LayerMask.GetMask(new string[1] { "Dynamic" }); MaskEnemyDynamic = MaskEnemy | MaskDynamic; MaskEntity3P = MaskFriendly | MaskEnemy; MaskEntity = MaskLocal | MaskEntity3P; MaskDecalValid = LayerMask.GetMask(new string[3] { "Default", "Default_NoGraph", "Default_BlockGraph" }); MaskWorldExcProj = MaskDecalValid | MaskDynamic; MaskWorld = MaskWorldExcProj | LayerMask.GetMask(new string[1] { "ProjectileBlocker" }); MaskEntityAndWorld = MaskEntity | MaskWorld; MaskEntityDynamic3P = MaskEntity3P | MaskDynamic; MaskEntityAndWorld3P = MaskEntity3P | MaskWorld; } } [Flags] internal enum SearchSetting { None = 0, Alloc = 1, ClosestHit = 2, CheckLOS = 4, CheckDoors = 8, CheckOwner = 0x10, CheckFriendly = 0x20, IgnoreDupes = 0x40 } internal static class SearchUtil { private static readonly List s_enemyCache = new List(); private static readonly List<(EnemyAgent, RaycastHit)> s_combinedCache = new List<(EnemyAgent, RaycastHit)>(); private static readonly List<(PlayerAgent, RaycastHit)> s_combinedCachePlayer = new List<(PlayerAgent, RaycastHit)>(); private static readonly Queue s_nodeQueue = new Queue(); private static readonly List s_rayHitCache = new List(); public static HashSet? DupeCheckSet; public static int SightBlockLayer = 0; public const float WeakspotBufferDist = 0.1f; private static Ray s_ray; private static RaycastHit s_rayHit; private const float Epsilon = 1E-05f; private static Vector3 ClosestPointOnBounds(Bounds bounds, Vector3 point) { //IL_0000: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) return new Vector3(Math.Clamp(point.x, ((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x), Math.Clamp(point.y, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).max.y), Math.Clamp(point.z, ((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z)); } private static int GetMaxSteps(float dist) { if (!(dist <= 0.5f)) { return (int)Math.Ceiling(Math.Max(3.0, 2.0 * Math.Log2(dist))); } return 1; } private static float GetStepDist(float dist, int step, int maxSteps) { if (maxSteps != 1) { return dist * (float)step / (float)(maxSteps - 1); } return dist / 2f; } private static bool BoundsInRange(Ray il2Ray, float range, float angle, Bounds il2Bounds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0113: Unknown result type (might be due to invalid IL or missing references) float num = range * range; Vector3 vector = new Vector3(((Ray)(ref il2Ray)).origin.x, ((Ray)(ref il2Ray)).origin.y, ((Ray)(ref il2Ray)).origin.z); Vector3 vector2 = new Vector3(((Ray)(ref il2Ray)).direction.x, ((Ray)(ref il2Ray)).direction.y, ((Ray)(ref il2Ray)).direction.z); SBounds sBounds = il2Bounds; Vector3 vector3 = sBounds.ClosestPoint(vector) - vector; if (vector3.LengthSquared() >= num) { return false; } if (angle >= 180f || sBounds.Contains(vector)) { return true; } if (angle <= 90f) { vector3 = sBounds.center - vector; float num2 = Vector3.Dot(vector2, vector3); if (num2 < 0f) { float num3 = sBounds.extents.X * Math.Abs(vector2.X) + sBounds.extents.Y * Math.Abs(vector2.Y) + sBounds.extents.Z * Math.Abs(vector2.Z); if (num2 + num3 < 0f) { return false; } } } float num4 = default(float); if (((Bounds)(ref il2Bounds)).IntersectRay(il2Ray, ref num4) && num4 < range) { return true; } float num5 = (float)Math.Cos((double)angle * Math.PI / 180.0); Span span = stackalloc float[3] { sBounds.min.X, sBounds.min.Y, sBounds.min.Z }; Span span2 = stackalloc float[3] { sBounds.size.X, sBounds.size.Y, sBounds.size.Z }; Span span3 = stackalloc int[3] { GetMaxSteps(span2[0]), GetMaxSteps(span2[1]), GetMaxSteps(span2[2]) }; Span span4 = stackalloc int[3] { Math.Min(span3[0], 2), Math.Min(span3[1], 2), Math.Min(span3[2], 2) }; Span span5 = stackalloc float[3]; for (int i = 0; i < span4[0]; i++) { span5[0] = span[0] + GetStepDist(span2[0], i, span4[0]); for (int j = 0; j < span4[1]; j++) { span5[1] = span[1] + GetStepDist(span2[1], j, span4[1]); for (int k = 0; k < span4[2]; k++) { span5[2] = span[2] + GetStepDist(span2[2], k, span4[2]); vector3.X = span5[0] - vector.X; vector3.Y = span5[1] - vector.Y; vector3.Z = span5[2] - vector.Z; if (vector3.LengthSquared() < num && Vector3.Dot(vector2, Vector3.Normalize(vector3)) >= num5) { return true; } } } } for (int l = 0; l < 3; l++) { int index = (l + 1) % 3; int index2 = (l + 2) % 3; for (int m = 1; m < span3[l] - 1; m++) { span5[l] = span[l] + GetStepDist(span2[l], m, span3[l]); for (int n = 0; n < span4[index]; n++) { span5[index] = span[index] + GetStepDist(span2[index], n, span4[index]); for (int num6 = 0; num6 < span4[index2]; num6++) { span5[index2] = span[index2] + GetStepDist(span2[index2], num6, span4[index2]); vector3.X = span5[0] - vector.X; vector3.Y = span5[1] - vector.Y; vector3.Z = span5[2] - vector.Z; if (vector3.LengthSquared() < num && Vector3.Dot(vector2, Vector3.Normalize(vector3)) >= num5) { return true; } } } } } return false; } private static bool RaycastEnsured(Collider collider, float range, out RaycastHit hit) { //IL_0001: 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_002b: 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) //IL_0050: 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) //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) //IL_0067: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) if (collider.Raycast(s_ray, ref hit, range)) { return true; } ((Ray)(ref s_ray)).origin = ((Ray)(ref s_ray)).GetPoint(-5f); if (collider.Raycast(s_ray, ref hit, 5f)) { return true; } Vector3 direction = ((Ray)(ref s_ray)).direction; Bounds bounds = collider.bounds; ((Ray)(ref s_ray)).direction = ((Bounds)(ref bounds)).center - ((Ray)(ref s_ray)).origin; if (collider.Raycast(s_ray, ref hit, 10f)) { return true; } DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(101, 5); defaultInterpolatedStringHandler.AppendLiteral("Attempted to get a raycast to "); defaultInterpolatedStringHandler.AppendFormatted(((Object)collider).name); defaultInterpolatedStringHandler.AppendLiteral(" but failed! Pos: "); defaultInterpolatedStringHandler.AppendFormatted(((Ray)(ref s_ray)).origin); defaultInterpolatedStringHandler.AppendLiteral(", Dir: "); defaultInterpolatedStringHandler.AppendFormatted(CustomExtensions.ToDetailedString(direction)); defaultInterpolatedStringHandler.AppendLiteral(", Collider center: "); bounds = collider.bounds; defaultInterpolatedStringHandler.AppendFormatted(((Bounds)(ref bounds)).center); defaultInterpolatedStringHandler.AppendLiteral(", Diff to collider center: "); defaultInterpolatedStringHandler.AppendFormatted(CustomExtensions.ToDetailedString(((Ray)(ref s_ray)).direction)); EWCLogger.Warning(defaultInterpolatedStringHandler.ToStringAndClear()); return false; } private static List GetValidColliders(Ray ray, float range, float angle, Agent agent) { //IL_0031: 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) Il2CppArrayBase componentsInChildren = ((Component)agent).GetComponentsInChildren(); List list = new List(componentsInChildren.Length); foreach (Collider item in componentsInChildren) { if (((Component)item).GetComponent() != null && item.enabled && BoundsInRange(ray, range, angle, item.bounds)) { list.Add(item); } } return list; } public static bool IsAgentInCone(Ray ray, float range, float angle, Agent agent, out RaycastHit hit, SearchSetting settings = SearchSetting.None) { //IL_0002: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_00e2: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Invalid comparison between Unknown and I4 //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Invalid comparison between Unknown and I4 //IL_01a6: 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_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) hit = default(RaycastHit); if ((Object)(object)agent == (Object)null || !agent.Alive) { return false; } if (settings.HasFlag(SearchSetting.IgnoreDupes)) { if ((int)agent.Type == 1) { HashSet? dupeCheckSet = DupeCheckSet; if (dupeCheckSet != null && dupeCheckSet.Contains(((Il2CppObjectBase)((Il2CppObjectBase)agent).Cast().Damage).Pointer)) { return false; } } if ((int)agent.Type == 0) { HashSet? dupeCheckSet2 = DupeCheckSet; if (dupeCheckSet2 != null && dupeCheckSet2.Contains(((Il2CppObjectBase)((Il2CppObjectBase)agent).Cast().Damage).Pointer)) { return false; } } } List validColliders = GetValidColliders(ray, range, angle, agent); if (validColliders.Count == 0) { return false; } ((Ray)(ref s_ray)).origin = ((Ray)(ref ray)).origin; float num = range * range; float num2 = num; Collider val = null; bool flag = false; AgentType type = agent.Type; foreach (Collider item in validColliders) { Vector3 val2 = item.ClosestPoint(((Ray)(ref ray)).origin); Vector3 direction = val2 - ((Ray)(ref ray)).origin; float num3 = ((Vector3)(ref direction)).sqrMagnitude; float num4 = num3; if (settings.HasFlag(SearchSetting.ClosestHit) && (int)type == 1 && num3 < num && (int)((Component)item).GetComponent().m_type == 1) { float num5 = Math.Max(((Vector3)(ref direction)).magnitude - 0.1f, 0f); num3 = num5 * num5; } if (!(num3 < num2) || (settings.HasFlag(SearchSetting.CheckLOS) && Physics.Linecast(((Ray)(ref ray)).origin, val2, SightBlockLayer))) { continue; } num2 = num3; val = item; if (!settings.HasFlag(SearchSetting.ClosestHit)) { break; } ((Ray)(ref s_ray)).direction = direction; if (!(num2 < 1E-05f)) { continue; } if (!(num4 > 1E-05f)) { ((Ray)(ref s_ray)).origin = ((Ray)(ref s_ray)).origin - ((Ray)(ref ray)).direction * Math.Min(0.1f, range / 2f); ((Ray)(ref s_ray)).direction = val2 - ((Ray)(ref s_ray)).origin; if (RaycastEnsured(item, range, out hit)) { ((RaycastHit)(ref hit)).point = val2; ((RaycastHit)(ref hit)).distance = 0f; flag = true; } else { val = null; } } break; } if ((Object)(object)val == (Object)null) { return false; } if (settings.HasFlag(SearchSetting.ClosestHit) && !flag && !RaycastEnsured(val, range, out hit)) { return false; } return true; } private static void CacheEnemiesInRange(Ray ray, float range, float angle, AIG_CourseNode origin, SearchSetting settings) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) AIG_SearchID.IncrementSearchID(); ushort searchID = AIG_SearchID.SearchID; s_nodeQueue.Enqueue(origin); ((AIG_CourseGraphMember)origin).m_searchID = searchID; CacheEnemiesInRangeFromQueue(ray, range, angle, settings); } private static void CacheEnemiesInRangeFromQueue(Ray ray, float range, float angle, SearchSetting settings) { //IL_006b: 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_00ea: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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) ushort searchID = AIG_SearchID.SearchID; float num = range * range; s_combinedCache.Clear(); AIG_CourseNode result; while (s_nodeQueue.TryDequeue(out result)) { Enumerator enumerator = result.m_portals.GetEnumerator(); while (enumerator.MoveNext()) { AIG_CoursePortal current = enumerator.Current; AIG_CourseNode oppositeNode = current.GetOppositeNode(result); if ((!settings.HasFlag(SearchSetting.CheckDoors) || current.IsTraversable) && ((AIG_CourseGraphMember)oppositeNode).m_searchID != searchID && BoundsInRange(ray, range, angle, current.m_cullPortal.m_portalBounds)) { ((AIG_CourseGraphMember)oppositeNode).m_searchID = searchID; s_nodeQueue.Enqueue(oppositeNode); } } Enumerator enumerator2 = result.m_enemiesInNode.GetEnumerator(); while (enumerator2.MoveNext()) { EnemyAgent current2 = enumerator2.Current; if (!((Object)(object)current2 == (Object)null) && ((Agent)current2).Alive && !(((Dam_SyncedDamageBase)current2.Damage).Health <= 0f)) { Vector3 val = ClosestPointOnBounds(((C_Cullable)current2.MovingCuller.Culler).Bounds, ((Ray)(ref ray)).origin) - ((Ray)(ref ray)).origin; if (!(((Vector3)(ref val)).sqrMagnitude > num) && IsAgentInCone(ray, range, angle, (Agent)(object)current2, out s_rayHit, settings)) { s_combinedCache.Add((current2, s_rayHit)); } } } } } public static List GetEnemiesInRange(Ray ray, float range, float angle, AIG_CourseNode origin, SearchSetting settings = SearchSetting.None) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) s_enemyCache.Clear(); if (range == 0f || angle == 0f) { if (!settings.HasFlag(SearchSetting.Alloc)) { return s_enemyCache; } return new List(); } CacheEnemiesInRange(ray, range, angle, origin, settings); if (settings.HasFlag(SearchSetting.Alloc)) { return s_combinedCache.ConvertAll(((EnemyAgent, RaycastHit) pair) => pair.Item1); } foreach (var item2 in s_combinedCache) { EnemyAgent item = item2.Item1; s_enemyCache.Add(item); } return s_enemyCache; } public static List<(EnemyAgent enemy, RaycastHit hit)> GetEnemyHitsInRange(Ray ray, float range, float angle, AIG_CourseNode origin, SearchSetting settings = SearchSetting.ClosestHit) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (range == 0f || angle == 0f) { s_combinedCache.Clear(); if (!settings.HasFlag(SearchSetting.Alloc)) { return s_combinedCache; } return new List<(EnemyAgent, RaycastHit)>(); } settings |= SearchSetting.ClosestHit; CacheEnemiesInRange(ray, range, angle, origin, settings); if (settings.HasFlag(SearchSetting.Alloc)) { return new List<(EnemyAgent, RaycastHit)>(s_combinedCache); } return s_combinedCache; } public static List GetLockHitsInRange(Ray ray, float range, float angle, SearchSetting settings = SearchSetting.None) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_011c: 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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) s_rayHitCache.Clear(); if (range == 0f || angle == 0f) { if (!settings.HasFlag(SearchSetting.Alloc)) { return s_rayHitCache; } return new List(); } Collider[] array = Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)Physics.OverlapSphere(((Ray)(ref ray)).origin, range, LayerUtil.MaskDynamic)); Vector3 direction = ((Ray)(ref ray)).direction; Collider[] array2 = array; foreach (Collider val in array2) { IDamageable damageableFromCollider = DamageableUtil.GetDamageableFromCollider(val); if (damageableFromCollider == null) { continue; } if (settings.HasFlag(SearchSetting.IgnoreDupes)) { HashSet? dupeCheckSet = DupeCheckSet; if (dupeCheckSet != null && dupeCheckSet.Contains(((Il2CppObjectBase)damageableFromCollider.GetBaseDamagable()).Pointer)) { continue; } } if (!settings.HasFlag(SearchSetting.CheckLOS) || !Physics.Linecast(((Ray)(ref ray)).origin, damageableFromCollider.DamageTargetPos, ref s_rayHit, SightBlockLayer) || !(((Il2CppObjectBase)((Component)((RaycastHit)(ref s_rayHit)).collider).gameObject).Pointer != ((Il2CppObjectBase)((Component)val).gameObject).Pointer)) { ((Ray)(ref ray)).direction = damageableFromCollider.DamageTargetPos - ((Ray)(ref ray)).origin; if (val.Raycast(ray, ref s_rayHit, range) && Vector3.Angle(((Ray)(ref ray)).direction, direction) < angle) { s_rayHitCache.Add(s_rayHit); } } } if (settings.HasFlag(SearchSetting.Alloc)) { return new List(s_rayHitCache); } return s_rayHitCache; } public static List<(PlayerAgent player, RaycastHit hit)> GetPlayerHitsInRange(Ray ray, float range, float angle, PlayerAgent? source, SearchSetting settings = SearchSetting.CheckOwner | SearchSetting.CheckFriendly) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) s_combinedCachePlayer.Clear(); if (range == 0f || angle == 0f) { if (!settings.HasFlag(SearchSetting.Alloc)) { return s_combinedCachePlayer; } return new List<(PlayerAgent, RaycastHit)>(); } float num = range * range; Enumerator enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator(); while (enumerator.MoveNext()) { PlayerAgent current = enumerator.Current; if ((Object)(object)current == (Object)null || !((Agent)current).Alive) { continue; } IntPtr pointer = ((Il2CppObjectBase)current).Pointer; IntPtr? obj = ((source != null) ? new IntPtr?(((Il2CppObjectBase)source).Pointer) : null); bool flag = pointer == obj; if ((!settings.HasFlag(SearchSetting.CheckOwner) && flag) || (!settings.HasFlag(SearchSetting.CheckFriendly) && !flag)) { continue; } Vector3 val = ClosestPointOnBounds(((C_Cullable)current.m_movingCuller.Culler).Bounds, ((Ray)(ref ray)).origin) - ((Ray)(ref ray)).origin; if (((Vector3)(ref val)).sqrMagnitude > num) { continue; } if (((Agent)current).IsLocallyOwned) { ((Ray)(ref s_ray)).origin = ((Ray)(ref ray)).origin; ((Ray)(ref s_ray)).direction = ((Dam_SyncedDamageBase)current.Damage).DamageTargetPos - ((Ray)(ref ray)).origin; if (!((Component)current).GetComponent().Raycast(s_ray, ref s_rayHit, range) || (settings.HasFlag(SearchSetting.CheckLOS) && Physics.Linecast(((Ray)(ref ray)).origin, ((RaycastHit)(ref s_rayHit)).point, SightBlockLayer))) { continue; } } else if (!IsAgentInCone(ray, range, angle, (Agent)(object)current, out s_rayHit, settings)) { continue; } s_combinedCachePlayer.Add((current, s_rayHit)); } if (settings.HasFlag(SearchSetting.Alloc)) { return new List<(PlayerAgent, RaycastHit)>(s_combinedCachePlayer); } return s_combinedCachePlayer; } public static List RaycastAll(Ray ray, float maxDist, int layerMask, SearchSetting settings = SearchSetting.None) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if (settings.HasFlag(SearchSetting.CheckLOS) && Physics.Raycast(ray, ref s_rayHit, maxDist, SightBlockLayer)) { maxDist = ((RaycastHit)(ref s_rayHit)).distance; } s_rayHitCache.Clear(); DamageUtil.IncrementSearchID(); uint searchID = DamageUtil.SearchID; float num2; for (float num = 0f; Physics.Raycast(ray, ref s_rayHit, maxDist, layerMask); num += num2, ((Ray)(ref ray)).origin = ((Ray)(ref ray)).origin + ((Ray)(ref ray)).direction * num2, maxDist -= num2) { num2 = ((RaycastHit)(ref s_rayHit)).distance + 0.1f; IDamageable component = ((Component)((RaycastHit)(ref s_rayHit)).collider).GetComponent(); if (component == null) { continue; } IDamageable baseDamagable = component.GetBaseDamagable(); if (baseDamagable.TempSearchID == searchID) { continue; } if (settings.HasFlag(SearchSetting.IgnoreDupes)) { HashSet? dupeCheckSet = DupeCheckSet; if (dupeCheckSet != null && dupeCheckSet.Contains(((Il2CppObjectBase)baseDamagable).Pointer)) { continue; } } ((RaycastHit)(ref s_rayHit)).distance = ((RaycastHit)(ref s_rayHit)).distance + num; s_rayHitCache.Add(s_rayHit); baseDamagable.TempSearchID = searchID; } if (settings.HasFlag(SearchSetting.Alloc)) { return new List(s_rayHitCache); } return s_rayHitCache; } public static bool RaycastFirst(Ray ray, out RaycastHit hit, float maxDist, int layerMask, Func filter, SearchSetting settings = SearchSetting.None) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) if (settings.HasFlag(SearchSetting.CheckLOS) && Physics.Raycast(ray, ref s_rayHit, maxDist, SightBlockLayer)) { maxDist = ((RaycastHit)(ref s_rayHit)).distance; } DamageUtil.IncrementSearchID(); uint searchID = DamageUtil.SearchID; float num2; for (float num = 0f; Physics.Raycast(ray, ref hit, maxDist, layerMask); num += num2, ((Ray)(ref ray)).origin = ((Ray)(ref ray)).origin + ((Ray)(ref ray)).direction * num2, maxDist -= num2) { num2 = ((RaycastHit)(ref s_rayHit)).distance + 0.1f; IDamageable component = ((Component)((RaycastHit)(ref hit)).collider).GetComponent(); if (component == null) { continue; } IDamageable baseDamagable = component.GetBaseDamagable(); if (baseDamagable.TempSearchID == searchID) { continue; } if (settings.HasFlag(SearchSetting.IgnoreDupes)) { HashSet? dupeCheckSet = DupeCheckSet; if (dupeCheckSet != null && dupeCheckSet.Contains(((Il2CppObjectBase)baseDamagable).Pointer)) { continue; } } ((RaycastHit)(ref hit)).distance = ((RaycastHit)(ref hit)).distance + num; baseDamagable.TempSearchID = searchID; if (filter(component)) { return true; } } return false; } } internal static class SortUtil { private static List<(RaycastHit hit, float distance)> s_limbCache = new List<(RaycastHit, float)>(); private static List<((IDamageable damageable, RaycastHit hit), float distance)> s_damageableLimbCache = new List<((IDamageable, RaycastHit), float)>(); public static int Rayhit(RaycastHit x, RaycastHit y) { if (((RaycastHit)(ref x)).distance == ((RaycastHit)(ref y)).distance) { return 0; } if (!(((RaycastHit)(ref x)).distance < ((RaycastHit)(ref y)).distance)) { return 1; } return -1; } public static int RayhitTuple((T, RaycastHit hit) x, (T, RaycastHit hit) y) { if (((RaycastHit)(ref x.hit)).distance == ((RaycastHit)(ref y.hit)).distance) { return 0; } if (!(((RaycastHit)(ref x.hit)).distance < ((RaycastHit)(ref y.hit)).distance)) { return 1; } return -1; } public static void SortWithWeakspotBuffer(IList list) { //IL_001b: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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: Invalid comparison between Unknown and I4 s_limbCache.EnsureCapacity(list.Count); foreach (RaycastHit item in list) { RaycastHit current = item; IDamageable? damageableFromRayHit = DamageableUtil.GetDamageableFromRayHit(current); int num; if (damageableFromRayHit == null) { num = 0; } else { Dam_EnemyDamageLimb obj = ((Il2CppObjectBase)damageableFromRayHit).TryCast(); num = (((int)((obj != null) ? new eLimbDamageType?(obj.m_type) : null).GetValueOrDefault() == 1) ? 1 : 0); } bool flag = (byte)num != 0; s_limbCache.Add((current, flag ? Math.Max(((RaycastHit)(ref current)).distance - 0.1f, 0f) : ((RaycastHit)(ref current)).distance)); } s_limbCache.Sort(FloatTuple); CopySortedList(s_limbCache, list); s_limbCache.Clear(); } public static void SortWithWeakspotBuffer(IList<(IDamageable, RaycastHit)> list) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) s_damageableLimbCache.EnsureCapacity(list.Count); foreach (var item3 in list) { IDamageable item = item3.Item1; RaycastHit item2 = item3.Item2; Dam_EnemyDamageLimb obj = ((Il2CppObjectBase)item).TryCast(); bool flag = obj != null && (int)obj.m_type == 1; s_damageableLimbCache.Add(((item, item2), flag ? Math.Max(((RaycastHit)(ref item2)).distance - 0.1f, 0f) : ((RaycastHit)(ref item2)).distance)); } s_damageableLimbCache.Sort(FloatTuple); CopySortedList<(IDamageable, RaycastHit)>(s_damageableLimbCache, list); s_damageableLimbCache.Clear(); } public static void CopySortedList(IList<(T, float)> sortedList, IList list) { for (int i = 0; i < list.Count; i++) { list[i] = sortedList[i].Item1; } } public static void CopySortedList(IList<(T, float, float)> sortedList, IList list) { for (int i = 0; i < list.Count; i++) { list[i] = sortedList[i].Item1; } } public static int FloatTuple((T, float val) x, (T, float val) y) { if (x.val == y.val) { return 0; } if (!(x.val < y.val)) { return 1; } return -1; } public static int FloatTuple((T, float val1, float val2) x, (T, float val1, float val2) y) { if (x.val1 == y.val1) { if (x.val2 == y.val2) { return 0; } if (!(x.val2 < y.val2)) { return 1; } return -1; } if (!(x.val1 < y.val1)) { return 1; } return -1; } } } namespace EWC.Utils.Structs { public struct SBounds { public Vector3 center; public Vector3 extents; public Vector3 max; public Vector3 min; public Vector3 size; public SBounds(Bounds bounds) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) center = new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.y, ((Bounds)(ref bounds)).center.z); size = new Vector3(((Bounds)(ref bounds)).size.x, ((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z); extents = size * 0.5f; max = center + extents; min = center - extents; } public readonly Vector3 ClosestPoint(Vector3 point) { return new Vector3(Math.Clamp(point.X, min.X, max.X), Math.Clamp(point.Y, min.Y, max.Y), Math.Clamp(point.Z, min.Z, max.Z)); } public readonly bool Contains(Vector3 point) { if (point.X >= min.X && point.X <= max.X && point.Y >= min.Y && point.Y <= max.Y && point.Z >= min.Z) { return point.Z <= max.Z; } return false; } public static implicit operator SBounds(Bounds bounds) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return new SBounds(bounds); } } } namespace EWC.Utils.Extensions { internal static class ArchetypeExtensions { public static int PierceLimit(this ArchetypeDataBlock dataBlock) { if (!dataBlock.PiercingBullets) { return 1; } return dataBlock.PiercingDamageCountLimit; } } public static class CellSoundPlayerExtensions { public static uint PostWithDoneCallback(this CellSoundPlayer soundPlayer, uint eventID, Vector3 pos, Action onDone) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return soundPlayer.Post(eventID, pos, 1u, CreateOnDoneCallback(onDone), (Object)(object)soundPlayer); } public static EventCallback CreateOnDoneCallback(Action onDone) { Action onDone2 = onDone; return EventCallback.op_Implicit((Action)delegate { onDone2(); }); } } internal static class CollectionExtensions { public static bool TryGetValueAs(this IDictionary dict, Key key, [MaybeNullWhen(false)] out ValueAs valueAs) where Key : notnull where ValueAs : Value { if (dict.TryGetValue(key, out Value value)) { valueAs = (ValueAs)(object)value; return true; } valueAs = default(ValueAs); return false; } public static IReadOnlyDictionary OrEmptyIfNull(this IReadOnlyDictionary? dict) where Key : notnull { return dict ?? ImmutableDictionary.Empty; } public static IReadOnlyList OrEmptyIfNull(this IReadOnlyList? list) { return list ?? ImmutableList.Empty; } public static T[] Extend(this T[] array, params T[] newArray) { T[] array2 = new T[array.Length + newArray.Length]; array.CopyTo(array2, 0); newArray.CopyTo(array2, array.Length); return array2; } public static T[] Remove(this T[] array, params T[] removeValues) { T[] array2 = new T[array.Length - removeValues.Length]; int num = 0; for (int i = 0; i < array.Length; i++) { bool flag = false; for (int j = 0; j < removeValues.Length; j++) { T val = removeValues[j]; ref T reference = ref val; T val2 = default(T); if (val2 == null) { val2 = reference; reference = ref val2; } if (reference.Equals(array[i])) { flag = true; break; } } if (!flag) { array2[num++] = array[i]; } } return array2; } } internal static class EnemyExtensions { public static void OnTakeCustomDamage(this EnemyAgent enemy, float damage, Agent? damageSource, Vector3 position, Vector3 direction, ES_HitreactType hitreact, bool setCooldowns = true) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (setCooldowns) { enemy.Abilities.OnTakeDamage(damage); } EB_StateBase currentState = ((StateMachine)(object)enemy.AI.m_behaviour).CurrentState; if (currentState != null) { currentState.OnTakeDamage(damage, damageSource, position, direction, hitreact); } TakeDamageDelegate tookDamage = enemy.TookDamage; if (tookDamage != null) { tookDamage.Invoke(damage, hitreact); } } } internal static class EnumExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasAnyFlag(this T value, T flag) where T : Enum { int num = Convert.ToInt32(value); int num2 = Convert.ToInt32(flag); if (num2 != 0) { return (num & num2) != 0; } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlagIn(this Enum type, Enum[] flagSet) { foreach (Enum flag in flagSet) { if (type.HasFlag(flag)) { return true; } } return false; } } internal static class Il2ObjectExtensions { public static bool TryCastOut(this Object obj, [MaybeNullWhen(false)] out T result) where T : Object { result = ((Il2CppObjectBase)obj).TryCast(); return result != null; } public static bool TryGetComp(this GameObject obj, [MaybeNullWhen(false)] out T result) { result = obj.GetComponent(); return result != null; } public static bool TryGetComp(this Component obj, [MaybeNullWhen(false)] out T result) { result = obj.GetComponent(); return result != null; } } internal static class NumExtensions { public static float Map(this float orig, float fromMin, float fromMax, float toMin, float toMax, float exponent = 1f) { if (fromMin == fromMax) { if (!(orig < fromMin)) { return toMax; } return toMin; } fromMax -= fromMin; orig = Math.Clamp(orig - fromMin, 0f, fromMax); if (exponent != 1f) { return (float)Math.Pow(orig / fromMax, exponent) * (toMax - toMin) + toMin; } return orig / fromMax * (toMax - toMin) + toMin; } public static float MapInverted(this float orig, float fromMin, float fromMax, float toMax, float toMin, float exponent = 1f) { if (fromMin == fromMax) { if (!(orig < fromMin)) { return toMin; } return toMax; } fromMax -= fromMin; orig = Math.Clamp(orig - fromMin, 0f, fromMax); if (exponent != 1f) { return (float)Math.Pow((fromMax - orig) / fromMax, exponent) * (toMax - toMin) + toMin; } return (fromMax - orig) / fromMax * (toMax - toMin) + toMin; } public static float Lerp(this float t, float min, float max) { return (max - min) * Math.Clamp(t, 0f, 1f) + min; } public static float Lerp(this double t, float min, float max) { return (max - min) * (float)Math.Clamp(t, 0.0, 1.0) + min; } } internal static class SlotExtensions { public static InventorySlot ToInventorySlot(this AmmoType ammo) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected I4, but got Unknown //IL_0019: 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_0021: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) return (InventorySlot)((int)ammo switch { 0 => 1, 1 => 2, 2 => 3, 3 => 4, _ => 0, }); } public static AmmoType ToAmmoType(this InventorySlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected I4, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) return (AmmoType)((slot - 1) switch { 0 => 0, 1 => 1, 2 => 2, 3 => 3, _ => 4, }); } } internal static class StringExtensions { public static T ToEnum(this string? value, T defaultValue) where T : struct { if (string.IsNullOrEmpty(value)) { return defaultValue; } if (!Enum.TryParse(value.Replace(" ", null), ignoreCase: true, out var result)) { return defaultValue; } return result; } public static bool ContainsAny(this string input, params string[] args) { foreach (string value in args) { if (input.Contains(value)) { return true; } } return false; } } internal static class VectorExtensions { private static Vector3 _cacheDir = Vector3.zero; private static Vector3 _cacheUp = Vector3.zero; private static Vector3 _cacheRight = Vector3.zero; public static Vector3 RotateBy(this Vector3 dir, float x, float y) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_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_008c: 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_0092: 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_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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (_cacheDir != dir) { Vector3 val = Vector3.Cross((Math.Abs(dir.y) < 0.99f) ? Vector3.up : Vector3.forward, dir); _cacheRight = ((Vector3)(ref val)).normalized; val = Vector3.Cross(_cacheRight, dir); _cacheUp = ((Vector3)(ref val)).normalized; _cacheDir = dir; } if (x != 0f) { dir = Quaternion.AngleAxis(0f - x, _cacheUp) * dir; } if (y != 0f) { dir = Quaternion.AngleAxis(0f - y, _cacheRight) * dir; } return dir; } } } namespace EWC.Patches.Sentry { [HarmonyPatch] internal static class SentryPatches { [HarmonyPatch(typeof(SentryGunFirstPerson), "OnGearSpawnComplete")] [HarmonyWrapSafe] [HarmonyPostfix] private static void OnGearSpawn(SentryGunFirstPerson __instance) { CustomWeaponManager.AddSpawnedItem((ItemEquippable)(object)__instance); } [HarmonyPatch(typeof(SentryGunInstance), "OnGearSpawnComplete")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostSpawnCallback(SentryGunInstance __instance) { CustomWeaponManager.ActivateSentry(__instance); } [HarmonyPatch(typeof(SentryGunInstance), "SyncedPickup")] [HarmonyWrapSafe] [HarmonyPrefix] private static void PrePickupCallback(SentryGunInstance __instance) { CustomWeaponManager.RemoveSentry(__instance); } [HarmonyPatch(typeof(SentryGunInstance), "StartFiring")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostStartFiring(SentryGunInstance __instance) { if (((Component)(object)__instance).TryGetComp(out var result)) { ((SentryGunComp)result.Gun).IsFirstShot = true; } } [HarmonyPatch(typeof(SentryGunInstance), "StopFiring")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostStopFiring(SentryGunInstance __instance) { if (((Component)(object)__instance).TryGetComp(out var result) && !((SentryGunComp)result.Gun).IsFirstShot) { result.Invoke(StaticContext.Instance); } } [HarmonyPatch(typeof(SentryGunInstance_Firing_Bullets), "UpdateFireMaster")] [HarmonyWrapSafe] [HarmonyPrefix] private static void PreFireCallback(SentryGunInstance_Firing_Bullets __instance, bool targetIsTagged, out (CustomGunComponent? cgc, bool fired) __state) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 float time = Clock.Time; if (!((Component)(object)__instance).TryGetComp(out var result)) { if (__instance.m_fireBulletTimer < time && __instance.m_burstTimer < time) { ShotManager.CacheFiringSentry(((Il2CppObjectBase)__instance.m_core).Cast(), targetIsTagged); __state = (null, true); } else { __state = (null, false); } return; } SentryGunComp sentryGunComp = (SentryGunComp)result.Gun; bool num = (int)sentryGunComp.FireMode == 1; bool flag = !num || __instance.m_burstTimer < time; bool flag2 = num && __instance.m_burstClipCurr == 0; if (!flag2 && flag && __instance.m_fireBulletTimer < time) { ShotManager.CacheFiringSentry(sentryGunComp.Value, targetIsTagged); if (sentryGunComp.IsFirstShot) { result.Invoke(StaticContext.Instance); } result.UpdateStoredFireRate(targetIsTagged); if (sentryGunComp.IsFirstShot) { result.Invoke(StaticContext.Instance); } result.Invoke(StaticContext.Instance); ShotManager.AdvanceGroupMod(result, targetIsTagged); __state = (result, true); } else if (flag2 && flag) { __state = (result, false); } else { __state = (null, false); } } [HarmonyPatch(typeof(SentryGunInstance_Firing_Bullets), "UpdateFireMaster")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostFireCallback(SentryGunInstance_Firing_Bullets __instance, (CustomGunComponent? cgc, bool fired) __state) { var (customGunComponent, _) = __state; if ((Object)(object)customGunComponent == (Object)null) { if (__state.fired) { ShotManager.ClearFiringInfo(); } } else if (__state.fired) { customGunComponent.NotifyShotFired(); ShotManager.CancelTracerFX(customGunComponent); iSentrygunInstanceCore core = __instance.m_core; float costOfBullet = core.CostOfBullet; customGunComponent.Invoke(new WeaponAmmoContext((int)(core.Ammo / costOfBullet), (int)(core.AmmoMaxCap / costOfBullet))); customGunComponent.Invoke(StaticContext.Instance); customGunComponent.ModifyFireRate(); ShotManager.ClearFiringInfo(); } else { customGunComponent.Invoke(StaticContext.Instance); ((SentryGunComp)customGunComponent.Gun).IsFirstShot = true; customGunComponent.ModifyFireRate(); } } [HarmonyPatch(typeof(SentryGunInstance_Firing_Bullets), "UpdateFireClient")] [HarmonyWrapSafe] [HarmonyPrefix] private static void PreFireClientCallback(SentryGunInstance_Firing_Bullets __instance, out (CustomGunComponent? cgc, bool fired) __state) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 float time = Clock.Time; if (!((Component)(object)__instance).TryGetComp(out var result)) { if (__instance.m_fireBulletTimer < time && __instance.m_burstTimer < time) { ShotManager.CacheFiringSentry(((Il2CppObjectBase)__instance.m_core).Cast(), isTagged: false); __state = (null, true); } else { __state = (null, false); } return; } bool num = (int)result.Gun.FireMode == 1; bool flag = !num || __instance.m_burstTimer < time; bool flag2 = num && __instance.m_burstClipCurr == 0; if (!flag2 && flag && __instance.m_fireBulletTimer < time) { ShotManager.CacheFiringSentry(((SentryGunComp)result.Gun).Value, isTagged: false); result.Invoke(StaticContext.Instance); result.UpdateStoredFireRate(); __state = (result, true); } else if (flag2 && flag) { __state = (result, false); } else { __state = (null, false); } } [HarmonyPatch(typeof(SentryGunInstance_Firing_Bullets), "UpdateFireClient")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostFireClientCallback(SentryGunInstance_Firing_Bullets __instance, (CustomGunComponent? cgc, bool fired) __state) { var (customGunComponent, _) = __state; if ((Object)(object)customGunComponent == (Object)null) { ShotManager.ClearFiringInfo(); } else if (__state.fired) { customGunComponent.NotifyShotFired(); ShotManager.CancelTracerFX(customGunComponent); customGunComponent.Invoke(StaticContext.Instance); customGunComponent.ModifyFireRate(); ShotManager.ClearFiringInfo(); } else { customGunComponent.ModifyFireRate(); } } [HarmonyPatch(typeof(SentryGunInstance), "GiveAmmoRel")] [HarmonyWrapSafe] [HarmonyPrefix] private static void UpdateClip(SentryGunInstance __instance, ref float ammoClassRel, out CustomGunComponent? __state) { if ((int)(__instance.Ammo / __instance.CostOfBullet) != (int)(__instance.AmmoMaxCap / __instance.CostOfBullet) && ((Component)(object)__instance).TryGetComp(out __state)) { ammoClassRel = __state.Invoke(new WeaponPreAmmoPackContext(ammoClassRel)).AmmoAmount; } else { __state = null; } } [HarmonyPatch(typeof(SentryGunInstance), "GiveAmmoRel")] [HarmonyWrapSafe] [HarmonyPostfix] private static void UpdateAmmo(SentryGunInstance __instance, CustomGunComponent? __state) { if (!((Object)(object)__state == (Object)null)) { float costOfBullet = __instance.CostOfBullet; __state.Invoke(new WeaponAmmoContext((int)(__instance.Ammo / costOfBullet), (int)(__instance.AmmoMaxCap / costOfBullet))); } } } } namespace EWC.Patches.Player { [HarmonyPatch] internal static class PlayerBackpackPatches { [HarmonyPatch(typeof(PlayerBackpack), "SpawnAndEquipGearAsync")] [HarmonyWrapSafe] [HarmonyPostfix] private static void SpawnGearCallback(PlayerBackpack __instance, InventorySlot slot) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) PlayerAgent val = (__instance.Owner.HasPlayerAgent ? ((Il2CppObjectBase)__instance.Owner.PlayerAgent).Cast() : null); BackpackItem val2 = default(BackpackItem); if (!((Object)(object)val == (Object)null) && __instance.TryGetBackpackItem(slot, ref val2)) { CustomWeaponManager.AddEquippedItem(val, ((Il2CppObjectBase)val2.Instance).Cast()); } } [HarmonyPatch(typeof(PlayerSync), "OnSpawn")] [HarmonyWrapSafe] [HarmonyPostfix] private static void SpawnPlayerCallback(PlayerSync __instance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) PlayerAgent agent = __instance.m_agent; PlayerBackpack val = default(PlayerBackpack); if (!PlayerBackpackManager.TryGetBackpack(agent.Owner, ref val)) { return; } InventorySlot[] validSlots = CustomDataManager.ValidSlots; BackpackItem val3 = default(BackpackItem); foreach (InventorySlot val2 in validSlots) { if (val.TryGetBackpackItem(val2, ref val3)) { CustomWeaponManager.AddEquippedItem(agent, ((Il2CppObjectBase)val3.Instance).Cast()); } } } } [HarmonyPatch] internal static class PlayerDamagePatches { private static PlayerDamageType _damageType = PlayerDamageType.Any; private static float _currentDamage = -1f; private static bool _currentImmune = false; public static void SetPlayerDamageType(PlayerDamageType damageType) { _damageType = damageType; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveTentacleAttackDamage")] [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveTentacleAttackDamage")] [HarmonyPrefix] private static void Pre_TentacleDamage() { _damageType = PlayerDamageType.Tentacle; } [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveMeleeDamage")] [HarmonyPrefix] private static void Pre_MeleeDamage() { _damageType = PlayerDamageType.Melee; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveShooterProjectileDamage")] [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveShooterProjectileDamage")] [HarmonyPrefix] private static void Pre_ShooterDamage() { _damageType = PlayerDamageType.Shooter; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveExplosionDamage")] [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveExplosionDamage")] [HarmonyPrefix] private static void Pre_ExplosionDamage() { _damageType = PlayerDamageType.Enemy | PlayerDamageType.Explosive; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveFireDamage")] [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveFireDamage")] [HarmonyPrefix] private static void Pre_BleedDamage() { _damageType = PlayerDamageType.Bleed; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveBulletDamage")] [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveBulletDamage")] [HarmonyPrefix] private static void Pre_BulletDamage() { _damageType = PlayerDamageType.Bullet; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveNoAirDamage")] [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveNoAirDamage")] [HarmonyPrefix] private static void Pre_SyringeDamage() { _damageType = PlayerDamageType.Syringe; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveFallDamage")] [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveFallDamage")] [HarmonyPrefix] private static void Pre_FallDamage() { _damageType = PlayerDamageType.Fall; } [HarmonyPatch(typeof(Dam_PlayerDamageBase), "OnIncomingDamage")] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_TakeDamage(Dam_PlayerDamageBase __instance, ref float damage, ref bool __state) { if (DebuffManager.TryGetArmorModBuff(((Il2CppObjectBase)__instance).Cast(), _damageType, out _currentImmune, out var mod)) { if (_currentImmune) { damage = 0f; } else { damage = ((mod > 0f) ? (damage / mod) : float.PositiveInfinity); } } _currentDamage = damage; SNet_Player owner = __instance.Owner.Owner; __state = damage > 0f && ((Dam_SyncedDamageBase)__instance).Health > 0f && (owner.IsLocal || (owner.IsBot && SNet.IsMaster)); } [HarmonyPatch(typeof(Dam_PlayerDamageBase), "OnIncomingDamage")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_TakeDamage(Dam_PlayerDamageBase __instance, float damage, bool __state) { SNet_Player owner = __instance.Owner.Owner; if (__state) { CustomWeaponManager.InvokeOnGear(owner, new WeaponDamageTakenContext(damage, _damageType)); if (SNet.IsMaster) { CustomWeaponManager.InvokeOnGear(owner, new WeaponHealthContext(__instance)); } } if (!owner.IsLocal) { ResetAttackData(); } } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "Hitreact")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool Pre_Hitreact(ref float damage) { if (_currentDamage < 0f) { return true; } damage = _currentDamage; bool result = !_currentImmune; ResetAttackData(); return result; } private static void ResetAttackData() { _damageType = PlayerDamageType.Any; _currentDamage = -1f; _currentImmune = false; } [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveAddHealth")] [HarmonyPrefix] private static void Pre_ReceiveAddHealth(Dam_PlayerDamageBase __instance, ref float __state) { __state = ((Dam_SyncedDamageBase)__instance).Health; } [HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveAddHealth")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_ReceiveAddHealth(Dam_PlayerDamageBase __instance, ref float __state) { if (SNet.IsMaster && __state != ((Dam_SyncedDamageBase)__instance).Health) { CustomWeaponManager.InvokeOnGear(__instance.Owner.Owner, new WeaponHealthContext(__instance)); } } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveSetHealth")] [HarmonyPrefix] private static void Pre_ReceiveHealth(Dam_PlayerDamageBase __instance, ref float __state) { __state = ((Dam_SyncedDamageBase)__instance).Health; } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveSetHealth")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_ReceiveHealth(Dam_PlayerDamageBase __instance, float __state) { if (__state != ((Dam_SyncedDamageBase)__instance).Health) { CustomWeaponManager.InvokeOnGear(__instance.Owner.Owner, new WeaponHealthContext(__instance)); } } } [HarmonyPatch] internal static class PlayerInventoryPatches { private static bool _allowReload = true; [HarmonyPatch(typeof(PUI_Inventory), "SetSlotAmmo")] [HarmonyWrapSafe] [HarmonyPrefix] private static void SetAmmoUICallback(PUI_Inventory __instance, InventorySlot slot, ref int clipAbs, ref int inPackAbs, ref float inPackRel) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if ((int)slot == 0) { return; } SNet_Player owner = __instance.m_owner; object obj; if (owner == null) { obj = null; } else { SNet_IPlayerAgent playerAgent = owner.PlayerAgent; if (playerAgent == null) { obj = null; } else { PlayerAgent obj2 = ((Il2CppObjectBase)playerAgent).TryCast(); if (obj2 == null) { obj = null; } else { FirstPersonItemHolder fPItemHolder = obj2.FPItemHolder; if (fPItemHolder == null) { obj = null; } else { ItemEquippable wieldedItem = fPItemHolder.WieldedItem; if (wieldedItem == null) { obj = null; } else { BulletWeapon obj3 = ((Il2CppObjectBase)wieldedItem).TryCast(); obj = ((obj3 != null) ? ((Component)obj3).GetComponent() : null); } } } } } CustomWeaponComponent customWeaponComponent = (CustomWeaponComponent)obj; if (!((Object)(object)customWeaponComponent == (Object)null)) { PUI_InventoryItem val = __instance.m_inventorySlots[slot]; WeaponPreAmmoUIContext weaponPreAmmoUIContext = new WeaponPreAmmoUIContext(clipAbs, inPackAbs, inPackRel, val.ShowAmmoClip, val.ShowAmmoPack, val.ShowAmmoTotalRel, val.ShowAmmoInfinite); customWeaponComponent.Invoke(weaponPreAmmoUIContext); clipAbs = weaponPreAmmoUIContext.Clip; inPackAbs = weaponPreAmmoUIContext.Reserve; inPackRel = weaponPreAmmoUIContext.TotalRel; val.ShowAmmoClip = weaponPreAmmoUIContext.ShowClip; val.ShowAmmoPack = weaponPreAmmoUIContext.ShowReserve; val.ShowAmmoTotalRel = weaponPreAmmoUIContext.ShowRel; val.ShowAmmoInfinite = weaponPreAmmoUIContext.ShowInfinite; } } [HarmonyPatch(typeof(PlayerAmmoStorage), "PickupAmmo")] [HarmonyWrapSafe] [HarmonyPrefix] private static void AmmoPackCallback(PlayerAmmoStorage __instance, AmmoType ammoType, ref float ammoAmount) { //IL_0006: 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) BackpackItem val = default(BackpackItem); if (__instance.m_playerBackpack.TryGetBackpackItem(ammoType.ToInventorySlot(), ref val)) { Item instance = val.Instance; CustomWeaponComponent customWeaponComponent = ((instance != null) ? ((Component)instance).GetComponent() : null); if ((Object)(object)customWeaponComponent != (Object)null) { ammoAmount = customWeaponComponent.Invoke(new WeaponPreAmmoPackContext(ammoAmount)).AmmoAmount; } } } [HarmonyPatch(typeof(PlayerAmmoStorage), "PickupAmmo")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostAmmoPackCallback(PlayerAmmoStorage __instance, AmmoType ammoType) { //IL_0006: 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) BackpackItem val = default(BackpackItem); if (__instance.m_playerBackpack.TryGetBackpackItem(ammoType.ToInventorySlot(), ref val)) { Item instance = val.Instance; ((instance != null) ? ((Component)instance).GetComponent() : null)?.Invoke(new WeaponPostAmmoPackContext(__instance)); } } [HarmonyPatch(typeof(PlayerInventoryLocal), "DoReload")] [HarmonyPatch(typeof(PlayerInventoryBase), "DoReload")] [HarmonyWrapSafe] [HarmonyPostfix] private static void ReloadCallback(PlayerInventoryBase __instance) { ItemEquippable wieldedItem = __instance.m_wieldedItem; CustomWeaponComponent customWeaponComponent = ((wieldedItem != null) ? ((Component)wieldedItem).GetComponent() : null); if (!((Object)(object)customWeaponComponent == (Object)null)) { customWeaponComponent.Invoke(StaticContext.Instance); } } [HarmonyPatch(typeof(PlayerInventoryLocal), "TriggerReload")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool ReloadPreStartCallback(PlayerInventoryLocal __instance) { _allowReload = true; ItemEquippable wieldedItem = ((PlayerInventoryBase)__instance).m_wieldedItem; CustomWeaponComponent customWeaponComponent = ((wieldedItem != null) ? ((Component)wieldedItem).GetComponent() : null); if ((Object)(object)customWeaponComponent == (Object)null) { return true; } _allowReload = customWeaponComponent.Invoke(new WeaponPreReloadContext()).Allow; return _allowReload; } [HarmonyPatch(typeof(PlayerInventoryLocal), "TriggerReload")] [HarmonyWrapSafe] [HarmonyPostfix] private static void ReloadStartCallback(PlayerInventoryLocal __instance) { if (_allowReload) { ItemEquippable wieldedItem = ((PlayerInventoryBase)__instance).m_wieldedItem; CustomWeaponComponent customWeaponComponent = ((wieldedItem != null) ? ((Component)wieldedItem).GetComponent() : null); if (!((Object)(object)customWeaponComponent == (Object)null) && ((PlayerInventoryBase)__instance).m_wieldedItem.IsReloading) { customWeaponComponent.Invoke(StaticContext.Instance); } } } [HarmonyPatch(typeof(PlayerInventoryBase), "TriggerReload")] [HarmonyWrapSafe] [HarmonyPostfix] private static void ReloadStartBotsCallback(PlayerInventoryBase __instance) { ItemEquippable wieldedItem = __instance.m_wieldedItem; CustomWeaponComponent customWeaponComponent = ((wieldedItem != null) ? ((Component)wieldedItem).GetComponent() : null); if (!((Object)(object)customWeaponComponent == (Object)null) && __instance.m_wieldedItem.IsReloading) { customWeaponComponent.Invoke(StaticContext.Instance); } } [HarmonyPatch(typeof(PlayerAmmoStorage), "FillAllClips")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostFillAllClipsCallback(PlayerAmmoStorage __instance) { BackpackItem val = default(BackpackItem); if (__instance.m_playerBackpack.TryGetBackpackItem((InventorySlot)1, ref val)) { Item instance = val.Instance; ((instance != null) ? ((Component)instance).GetComponent() : null)?.Invoke(new WeaponPostAmmoInitContext(__instance, __instance.StandardAmmo)); } BackpackItem val2 = default(BackpackItem); if (__instance.m_playerBackpack.TryGetBackpackItem((InventorySlot)2, ref val2)) { Item instance2 = val2.Instance; ((instance2 != null) ? ((Component)instance2).GetComponent() : null)?.Invoke(new WeaponPostAmmoInitContext(__instance, __instance.SpecialAmmo)); } BackpackItem val3 = default(BackpackItem); if (__instance.m_playerBackpack.TryGetBackpackItem((InventorySlot)3, ref val3)) { Item instance3 = val3.Instance; ((instance3 != null) ? ((Component)instance3).GetComponent() : null)?.Invoke(new WeaponPostAmmoInitContext(__instance, __instance.SpecialAmmo)); } } } [HarmonyPatch] internal static class PlayerLocalPatches { [HarmonyPatch(typeof(PUI_LocalPlayerStatus), "UpdateHealth")] [HarmonyWrapSafe] [HarmonyPrefix] private static void UpdateHealth(PUI_LocalPlayerStatus __instance, float health) { if (__instance.m_lastHealthVal <= 0.14f && health > 0.14f && __instance.m_warningRoutine != null) { __instance.m_healthWarningLooping = true; } } } [HarmonyPatch] internal static class PlayerLocomotionPatches { private static bool _inJump; [HarmonyPatch(typeof(PLOC_Crouch), "Enter")] [HarmonyWrapSafe] [HarmonyPostfix] private static void EnterCrouch(PLOC_Crouch __instance) { CustomWeaponManager.InvokeOnGear(((PLOC_Base)__instance).m_owner.Owner, StaticContext.Instance); } [HarmonyPatch(typeof(PLOC_Crouch), "Exit")] [HarmonyWrapSafe] [HarmonyPostfix] private static void ExitCrouch(PLOC_Crouch __instance) { CustomWeaponManager.InvokeOnGear(((PLOC_Base)__instance).m_owner.Owner, StaticContext.Instance); } [HarmonyPatch(typeof(PLOC_Run), "Enter")] [HarmonyWrapSafe] [HarmonyAfter(new string[] { "RunAndGun" })] [HarmonyPostfix] private static void EnterSprint(PLOC_Run __instance) { CustomWeaponManager.InvokeOnGear(((PLOC_Base)__instance).m_owner.Owner, StaticContext.Instance); } [HarmonyPatch(typeof(PLOC_Run), "Exit")] [HarmonyWrapSafe] [HarmonyPostfix] private static void ExitSprint(PLOC_Run __instance) { CustomWeaponManager.InvokeOnGear(((PLOC_Base)__instance).m_owner.Owner, StaticContext.Instance); } [HarmonyPatch(typeof(PLOC_Jump), "Enter")] [HarmonyWrapSafe] [HarmonyPostfix] private static void EnterJump(PLOC_Jump __instance) { if (!_inJump) { _inJump = true; CustomWeaponManager.InvokeOnGear(((PLOC_Base)__instance).m_owner.Owner, StaticContext.Instance); } } [HarmonyPatch(typeof(PLOC_Jump), "CommonExit")] [HarmonyWrapSafe] [HarmonyPostfix] private static void ExitJump(PLOC_Jump __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 if (_inJump) { PlayerAgent owner = ((PLOC_Base)__instance).m_owner; if (((Agent)owner).IsLocallyOwned && (int)owner.Locomotion.m_currentStateEnum != 4) { CustomWeaponManager.InvokeOnGear(owner.Owner, StaticContext.Instance); _inJump = false; } } } [HarmonyPatch(typeof(PLOC_Fall), "Enter")] [HarmonyWrapSafe] [HarmonyPostfix] private static void EnterFall(PLOC_Fall __instance) { if (!_inJump) { CustomWeaponManager.InvokeOnGear(((PLOC_Base)__instance).m_owner.Owner, StaticContext.Instance); _inJump = true; } } [HarmonyPatch(typeof(PLOC_Fall), "Exit")] [HarmonyWrapSafe] [HarmonyPostfix] private static void ExitFall(PLOC_Fall __instance) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if (_inJump) { PlayerAgent owner = ((PLOC_Base)__instance).m_owner; if ((int)owner.Locomotion.m_currentStateEnum != 3) { CustomWeaponManager.InvokeOnGear(owner.Owner, StaticContext.Instance); _inJump = false; } } } } } namespace EWC.Patches.Native { internal static class EnemyDetectionPatches { private unsafe delegate void d_DetectOnNoise(IntPtr _this, IntPtr agentTarget, float movementDetectionDistance, float shootDetectionDistance, float delta, out float output, Il2CppMethodInfo* methodInfo); private static INativeDetour? DetectOnNoiseDetour; private static d_DetectOnNoise? orig_DetectOnNoise; private static readonly Dictionary> s_cachedCWCs = new Dictionary>(); private static readonly InventorySlot[] GunSlots; [InvokeOnLoad] private unsafe static void ApplyNativePatch() { DetectOnNoiseDetour = INativeDetour.CreateAndApply((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod("DetectOnNoiseDistance_Conditional_AnimatedWindow", typeof(void).Name, false, new string[5] { "AgentTarget", typeof(float).Name, typeof(float).Name, typeof(float).Name, typeof(float).MakeByRefType().Name }), (d_DetectOnNoise)DetectOnNoisePatch, ref orig_DetectOnNoise); NativePatchAPI.AddDetectPostfix(Post_DetectAgentNoise); } private unsafe static void DetectOnNoisePatch(IntPtr _this, IntPtr agentTarget, float movementDetectionDistance, float shootDetectionDistance, float delta, out float output, Il2CppMethodInfo* methodInfo) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0044: Expected O, but got Unknown output = 0f; EnemyDetection val = new EnemyDetection(_this); AgentTarget agentTarget2 = new AgentTarget(agentTarget); if (NativePatchAPI.RunDetectPrefix(val, agentTarget2, movementDetectionDistance, shootDetectionDistance, delta, ref output)) { orig_DetectOnNoise(_this, agentTarget, movementDetectionDistance, shootDetectionDistance, delta, out output, methodInfo); } NativePatchAPI.RunDetectPostfix(val, agentTarget2, movementDetectionDistance, shootDetectionDistance, delta, ref output); } private static void UpdateCache() { //IL_008e: 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) if (s_cachedCWCs.Count == PlayerManager.PlayerAgentsInLevel.Count && !s_cachedCWCs.Values.Any((List list) => list.Any((CustomWeaponComponent cwc) => (Object)(object)cwc == (Object)null))) { return; } s_cachedCWCs.Clear(); Enumerator enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator(); PlayerBackpack val = default(PlayerBackpack); BackpackItem val3 = default(BackpackItem); while (enumerator.MoveNext()) { PlayerAgent current = enumerator.Current; if (!PlayerBackpackManager.TryGetBackpack(current.Owner, ref val)) { continue; } List list2 = new List(3); InventorySlot[] gunSlots = GunSlots; foreach (InventorySlot val2 in gunSlots) { if (val.TryGetBackpackItem(val2, ref val3)) { Item instance = val3.Instance; if (instance != null && ((Component)(object)instance).TryGetComp(out var result)) { list2.Add(result); } } } s_cachedCWCs.Add(((Agent)current).GlobalID, list2); } } private static void Post_DetectAgentNoise(EnemyDetection __instance, AgentTarget agentTarget, float _mv, float _wp, float _delta, ref float output) { UpdateCache(); if (!s_cachedCWCs.TryGetValue(agentTarget.m_globalID, out List value)) { return; } WeaponStealthUpdateContext weaponStealthUpdateContext = new WeaponStealthUpdateContext(__instance.m_ai.m_enemyAgent, __instance.m_noiseDetectionOn, output); foreach (CustomWeaponComponent item in value) { item.Invoke(weaponStealthUpdateContext); } output = weaponStealthUpdateContext.Output; } static EnemyDetectionPatches() { InventorySlot[] array = new InventorySlot[3]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); GunSlots = (InventorySlot[])(object)array; } } } namespace EWC.Patches.Melee { [HarmonyPatch] internal static class MeleePatches { public static readonly HitData HitData = new HitData(DamageType.Bullet); private static CustomWeaponComponent? _cachedSwingCWC = null; public static float CachedCharge { get; private set; } = 0f; [HarmonyPatch(typeof(MeleeWeaponFirstPerson), "ChangeState")] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_MeleeChangeState(MeleeWeaponFirstPerson __instance, eMeleeWeaponState newState) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 if (!((Component)(object)__instance).TryGetComp(out var result)) { return; } result.UpdateAttackSpeed(); if ((int)newState == 7 || (int)newState == 9) { result.Invoke(StaticContext.Instance); return; } eMeleeWeaponState currentStateName = __instance.CurrentStateName; if ((int)currentStateName == 7 || (int)currentStateName == 9) { MWS_ChargeUp val = ((Il2CppObjectBase)__instance.CurrentState).Cast(); result.Invoke(new WeaponChargeEndContext(Math.Min(val.m_elapsed / val.m_maxDamageTime, 1f))); } } [HarmonyPatch(typeof(MWS_Push), "Enter")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PrePushCallback(MWS_Push __instance) { _cachedSwingCWC = ((Component)((MWS_Base)__instance).m_weapon).GetComponent(); if (!((Object)(object)_cachedSwingCWC == (Object)null)) { _cachedSwingCWC.Invoke(StaticContext.Instance); HitData.shotInfo.SetToPush(); } } [HarmonyPatch(typeof(MWS_AttackLight), "Enter")] [HarmonyWrapSafe] [HarmonyPostfix] private static void SetLightDamage(MWS_AttackLight __instance) { OnSwingStart(((MWS_Base)__instance).m_weapon, 0f); } [HarmonyPatch(typeof(MWS_AttackHeavy), "Enter")] [HarmonyWrapSafe] [HarmonyPostfix] private static void SetHeavyDamage(MWS_AttackHeavy __instance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 MeleeWeaponFirstPerson weapon = ((MWS_Base)__instance).m_weapon; MWS_ChargeUp val = ((Il2CppObjectBase)(((int)((MWS_Base)__instance).m_data.m_side == 2) ? ((Il2CppArrayBase)(object)weapon.m_states)[7] : ((Il2CppArrayBase)(object)weapon.m_states)[9])).Cast(); OnSwingStart(weapon, Math.Min(val.m_elapsed / val.m_maxDamageTime, 1f)); } private static void OnSwingStart(MeleeWeaponFirstPerson weapon, float charge) { _cachedSwingCWC = ((Component)weapon).GetComponent(); if ((Object)(object)_cachedSwingCWC == (Object)null) { return; } ShotManager.AdvanceGroupMod(_cachedSwingCWC); CachedCharge = charge; if (charge > 0f && charge < 1f) { WeaponChargeContext weaponChargeContext = _cachedSwingCWC.Invoke(new WeaponChargeContext()); if (weaponChargeContext.Exponent != 3f) { weapon.SetNextDamageToDeal((eMeleeWeaponDamage)2, (float)Math.Pow(charge, weaponChargeContext.Exponent)); } } HitData.shotInfo.Reset(weapon.m_damageToDeal, weapon.m_precisionMultiToDeal, weapon.m_staggerMultiToDeal, _cachedSwingCWC); _cachedSwingCWC.Invoke(StaticContext.Instance); } [HarmonyPatch(typeof(MWS_Push), "Exit")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostPushCallback(MWS_Push __instance) { if (!((Object)(object)_cachedSwingCWC == (Object)null)) { _cachedSwingCWC.Invoke(StaticContext.Instance); } } [HarmonyPatch(typeof(MWS_AttackSwingBase), "Exit")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostSwingCallback(MWS_AttackSwingBase __instance) { if (!((Object)(object)_cachedSwingCWC == (Object)null)) { _cachedSwingCWC.Invoke(new WeaponShotEndContext(DamageType.Bullet, HitData.shotInfo, null)); _cachedSwingCWC.Invoke(StaticContext.Instance); } } [HarmonyPatch(typeof(MeleeWeaponFirstPerson), "DoAttackDamage")] [HarmonyWrapSafe] [HarmonyPrefix] private static void HitCallback(MeleeWeaponFirstPerson __instance, MeleeWeaponDamageData data, bool isPush) { if ((Object)(object)_cachedSwingCWC == (Object)null) { return; } HitData.Setup(__instance, data); if (isPush) { if (!HitData.damageType.HasFlag(DamageType.Dead) && HitData.damageType.HasFlag(DamageType.Enemy)) { Dam_EnemyDamageBase val = ((Il2CppObjectBase)HitData.damageable.GetBaseDamagable()).Cast(); if (!val.IsImortal && val.Owner.EnemyBalancingData.CanBePushed && !val.IsStuckInGlue) { HitData.ResetDamage(); _cachedSwingCWC.Invoke(new WeaponPushHitContext(HitData)); } } } else { WeaponPatches.ApplyEWCHit(_cachedSwingCWC, HitData, out var _); } } } } namespace EWC.Patches.Item { [HarmonyPatch] internal class ItemPatches { private static CustomWeaponComponent? _localCWC; private static bool _inRunCheck; [InvokeOnLoad] private static void Init() { CustomWeaponManager.OnResetCWCs += ReloadLocalCWC; } private static void ReloadLocalCWC(bool activate) { _localCWC = null; if (activate && PlayerManager.HasLocalPlayerAgent()) { ItemEquippable wieldedItem = PlayerManager.GetLocalPlayerAgent().Inventory.WieldedItem; if ((Object)(object)wieldedItem != (Object)null && ((Component)(object)wieldedItem).TryGetComp(out var result)) { _localCWC = result; } } } [InvokeOnCleanup(false)] private static void OnCleanup() { _localCWC = null; } [HarmonyPatch(typeof(ItemEquippable), "OnDestroy")] [HarmonyWrapSafe] [HarmonyPostfix] private static void OnGearDestroyed(ItemEquippable __instance) { CustomWeaponManager.RemoveSpawnedItem(__instance); } [HarmonyPatch(typeof(ItemEquippable), "OnWield")] [HarmonyWrapSafe] [HarmonyPostfix] private static void UpdateCurrentWeapon(ItemEquippable __instance) { if (((Component)(object)__instance).TryGetComp(out var result)) { result.OnWield(); if (result.Owner.IsType(OwnerType.Local)) { _localCWC = result; } } } [HarmonyPatch(typeof(ItemEquippable), "OnUnWield")] [HarmonyWrapSafe] [HarmonyPostfix] private static void UpdateWeaponUnwielded(BulletWeapon __instance) { if (((Component)(object)__instance).TryGetComp(out var result)) { result.OnUnWield(); if (result.Owner.IsType(OwnerType.Local)) { _localCWC = null; } } } [HarmonyPatch(typeof(FirstPersonItemHolder), "ItemCanMoveQuick")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool PreGetRunAllowed(ref bool __result) { _inRunCheck = true; if ((Object)(object)_localCWC == (Object)null) { return true; } WeaponPreSprintContext weaponPreSprintContext = _localCWC.Invoke(new WeaponPreSprintContext()); if (!weaponPreSprintContext.Allow) { __result = false; return false; } if (_localCWC.Weapon.IsType(WeaponType.Gun) && weaponPreSprintContext.AllowBurstCancel) { _localCWC.Weapon.ArchetypeData.FireMode = (eWeaponFireMode)0; } return true; } [HarmonyPatch(typeof(FirstPersonItemHolder), "ItemCanMoveQuick")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostGetRunAllowed() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) _inRunCheck = false; if (!((Object)(object)_localCWC == (Object)null) && _localCWC.Weapon.IsType(WeaponType.Gun)) { LocalGunComp localGunComp = (LocalGunComp)_localCWC.Weapon; localGunComp.ArchetypeData.FireMode = localGunComp.FireMode; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostGetRunAllowed(ref bool __result) { if (!_inRunCheck && !((Object)(object)_localCWC == (Object)null)) { __result = _localCWC.Invoke(new WeaponPreSwapContext(__result)).Allow; } } } } namespace EWC.Patches.Gun { [HarmonyPatch] internal static class FPISPatches { private static CustomWeaponComponent? _cachedCWC; [HarmonyPatch(typeof(FPIS_Aim), "Enter")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_AimEnter(FPIS_Aim __instance) { _cachedCWC = ((Component)((FPItemState)__instance).Holder.WieldedItem).GetComponent(); if (!((Object)(object)_cachedCWC == (Object)null)) { _cachedCWC.Invoke(StaticContext.Instance); } } [HarmonyPatch(typeof(FPIS_Aim), "Exit")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_AimExit() { if (!((Object)(object)_cachedCWC == (Object)null)) { _cachedCWC.Invoke(StaticContext.Instance); } } } [HarmonyPatch] internal static class WeaponArchetypePatches { [HarmonyPatch(typeof(BulletWeaponArchetype), "OnStopChargeup")] [HarmonyWrapSafe] [HarmonyPrefix] private static void ChargeEndCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if (!((Object)(object)customGunComponent == (Object)null)) { customGunComponent.Invoke(new WeaponChargeEndContext(Math.Min(1f, 1f - (__instance.m_chargeupTimer - Clock.Time) / __instance.ChargeupDelay()))); } } [HarmonyPatch(typeof(BWA_Burst), "OnStartFiring")] [HarmonyPatch(typeof(BWA_Auto), "OnStartFiring")] [HarmonyPatch(typeof(BulletWeaponArchetype), "OnStartFiring")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool StartFireCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if ((Object)(object)customGunComponent == (Object)null) { return true; } customGunComponent.CancelShot = false; bool allow = customGunComponent.Invoke(new WeaponPreStartFireContext()).Allow; customGunComponent.UpdateStoredFireRate(); if (!allow) { customGunComponent.StoreCancelShot(); } if (__instance.HasChargeup) { customGunComponent.Invoke(new WeaponChargeEndContext(1f)); } return allow; } [HarmonyPatch(typeof(BWA_Burst), "OnStartFiring")] [HarmonyPatch(typeof(BWA_Auto), "OnStartFiring")] [HarmonyPatch(typeof(BulletWeaponArchetype), "OnStartFiring")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostStartFireCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if (!((Object)(object)customGunComponent == (Object)null)) { if (customGunComponent.ResetShotIfCancel(__instance)) { customGunComponent.CancelShot = false; __instance.m_readyToFire = false; } else { customGunComponent.Invoke(StaticContext.Instance); } } } [HarmonyPatch(typeof(BWA_Auto), "OnFireShot")] [HarmonyPatch(typeof(BWA_Burst), "OnFireShot")] [HarmonyPatch(typeof(BWA_Semi), "OnFireShot")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool PreFireCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if ((Object)(object)customGunComponent == (Object)null) { return true; } if (customGunComponent.CancelShot) { return false; } if (!customGunComponent.Invoke(new WeaponFireCancelContext()).Allow) { customGunComponent.StoreCancelShot(); return false; } customGunComponent.Invoke(StaticContext.Instance); ShotManager.AdvanceGroupMod(customGunComponent); return true; } [HarmonyPatch(typeof(BWA_Auto), "OnFireShot")] [HarmonyPatch(typeof(BWA_Burst), "OnFireShot")] [HarmonyPatch(typeof(BWA_Semi), "OnFireShot")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostFireCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if (!((Object)(object)customGunComponent == (Object)null) && !customGunComponent.CancelShot) { customGunComponent.NotifyShotFired(); ShotManager.CancelTracerFX(customGunComponent); customGunComponent.Invoke(new WeaponAmmoContext(__instance.m_weapon.m_clip, ((ItemEquippable)__instance.m_weapon).ClipSize)); customGunComponent.Invoke(StaticContext.Instance); } } [HarmonyPatch(typeof(BulletWeaponArchetype), "PostFireCheck")] [HarmonyWrapSafe] [HarmonyPrefix] private static void PrePostFireCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if (!((Object)(object)customGunComponent == (Object)null)) { customGunComponent.ResetShotIfCancel(__instance); } } [HarmonyPatch(typeof(BulletWeaponArchetype), "PostFireCheck")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostPostFireCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if (!((Object)(object)customGunComponent == (Object)null)) { if (customGunComponent.CancelShot) { customGunComponent.ModifyFireRate(); customGunComponent.CancelShot = false; } else { customGunComponent.UpdateStoredFireRate(); customGunComponent.ModifyFireRate(); } } } [HarmonyPatch(typeof(BWA_Burst), "OnStopFiring")] [HarmonyPatch(typeof(BWA_Auto), "OnStopFiring")] [HarmonyPatch(typeof(BulletWeaponArchetype), "OnStopFiring")] [HarmonyWrapSafe] [HarmonyPostfix] private static void StopFiringCallback(BulletWeaponArchetype __instance) { BulletWeapon weapon = __instance.m_weapon; CustomGunComponent customGunComponent = ((weapon != null) ? ((Component)weapon).GetComponent() : null); if (!((Object)(object)customGunComponent == (Object)null)) { customGunComponent.Invoke(StaticContext.Instance); } } } [HarmonyPatch] internal static class WeaponCachePatches { [HarmonyPatch(typeof(Shotgun), "Fire")] [HarmonyPatch(typeof(ShotgunSynced), "Fire")] [HarmonyPatch(typeof(BulletWeapon), "Fire")] [HarmonyPatch(typeof(BulletWeaponSynced), "Fire")] [HarmonyPriority(600)] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_Fire(BulletWeapon __instance) { ShotManager.CacheFiringGun(__instance); } [HarmonyPatch(typeof(Shotgun), "Fire")] [HarmonyPatch(typeof(ShotgunSynced), "Fire")] [HarmonyPatch(typeof(BulletWeapon), "Fire")] [HarmonyPatch(typeof(BulletWeaponSynced), "Fire")] [HarmonyPriority(200)] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_Fire() { ShotManager.ClearFiringInfo(); } } [HarmonyPatch] internal static class WeaponPatches { [HarmonyPatch(typeof(BulletWeapon), "OnGearSpawnComplete")] [HarmonyWrapSafe] [HarmonyPostfix] private static void OnGearSpawn(BulletWeapon __instance) { CustomWeaponManager.AddSpawnedItem((ItemEquippable)(object)__instance); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostGetReloadTime(BulletWeapon __instance, ref float __result) { if (((Component)(object)__instance).TryGetComp(out var result)) { __result /= result.Invoke(new WeaponReloadContext()).Value; } } [HarmonyPatch(typeof(BulletWeapon), "SetCurrentClip")] [HarmonyWrapSafe] [HarmonyPrefix] private static void UpdateClip(BulletWeapon __instance, int clip, ref bool __state) { if (!((Object)(object)__instance == (Object)null)) { __state = __instance.m_clip != clip; } } [HarmonyPatch(typeof(BulletWeapon), "SetCurrentClip")] [HarmonyWrapSafe] [HarmonyPostfix] private static void UpdateClip(BulletWeapon __instance, bool __state) { if (!((Object)(object)__instance == (Object)null) && __state && ((Component)(object)__instance).TryGetComp(out var result)) { result.Invoke(new WeaponAmmoContext(__instance.m_clip, ((ItemEquippable)__instance).ClipSize)); } } [HarmonyPatch(typeof(BulletWeapon), "BulletHit")] [HarmonyPriority(200)] [HarmonyWrapSafe] [HarmonyPrefix] private static void HitCallback(ref WeaponHitData weaponRayData, bool doDamage, float additionalDis, uint damageSearchID, ref bool allowDirectionalBonus) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!doDamage) { return; } IDamageable damageableFromRayHit = DamageableUtil.GetDamageableFromRayHit(weaponRayData.rayHit); IDamageable val = ((damageableFromRayHit != null) ? damageableFromRayHit.GetBaseDamagable() : damageableFromRayHit); if (damageSearchID == 0 || val == null || val.TempSearchID != damageSearchID) { CustomWeaponComponent cwc = ShotManager.ActiveFiringInfo.cwc; HitData hitData = new HitData(weaponRayData, additionalDis); if ((Object)(object)cwc == (Object)null) { ApplyDebuffs(hitData); } else { ApplyEWCHit(cwc, hitData, out allowDirectionalBonus); } } } private static void ApplyDebuffs(WeaponHitData weaponRayData, float additionalDis) { ApplyDebuffs(new HitData(weaponRayData, additionalDis)); } private static void ApplyDebuffs(HitData data) { if (!data.damageType.HasFlag(DamageType.Dead)) { data.ResetDamage(); if (DebuffManager.TryGetShotModDebuff(data.damageable, StatType.Damage, data.damageType, DebuffManager.DefaultGroupSet, out var mod)) { data.damage *= mod.Value; } if (DebuffManager.TryGetShotModDebuff(data.damageable, StatType.Precision, data.damageType, DebuffManager.DefaultGroupSet, out var mod2)) { data.precisionMulti *= mod2.Value; } if (DebuffManager.TryGetShotModDebuff(data.damageable, StatType.Stagger, data.damageType, DebuffManager.DefaultGroupSet, out var mod3)) { data.staggerMulti *= mod3.Value; } data.Apply(); } } public static void ApplyEWCHit(CustomWeaponComponent cwc, HitData hitData, out bool doBackstab) { ApplyEWCHit(cwc, cwc.GetContextController(), hitData, out doBackstab); } public static void ApplyEWCHit(CustomWeaponComponent cwc, ContextController cc, HitData hitData, out bool doBackstab) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Invalid comparison between Unknown and I4 //IL_008a: 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) hitData.ResetDamage(); EnemyLimbPatches.CacheComponents(cwc, cc); doBackstab = cwc.Weapon.AllowBackstab; IDamageable damageable = hitData.damageable; if (!hitData.damageType.HasFlag(DamageType.Dead)) { float num = 1f; float num2 = 1f; Agent baseAgent = damageable.GetBaseAgent(); Dam_EnemyDamageLimb val = null; int num3; if ((Object)(object)baseAgent != (Object)null && baseAgent.Alive) { num3 = (((int)baseAgent.Type == 1) ? 1 : 0); if (num3 != 0) { val = ((Il2CppObjectBase)damageable).Cast(); if (doBackstab) { num2 = val.ApplyDamageFromBehindBonus(1f, hitData.hitPos, ((Vector3)(ref hitData.fireDir)).normalized, 1f); num = num2.Map(1f, 2f, 1f, cc.Invoke(new WeaponBackstabContext()).Value); } } } else { num3 = 0; } cc.Invoke(new WeaponPreHitDamageableContext(hitData, num, num2)); WeaponStatContext weaponStatContext = new WeaponStatContext(hitData, cwc.DebuffIDs); cc.Invoke(weaponStatContext); hitData.damage = weaponStatContext.Damage; hitData.staggerMulti = weaponStatContext.Stagger; hitData.precisionMulti = weaponStatContext.Precision; bool bypassTumor = (EnemyLimbPatches.CachedBypassTumorCap = weaponStatContext.BypassTumorCap); if (num3 != 0) { WeaponHitDamageableContext weaponHitDamageableContext = new WeaponHitDamageableContext(hitData, bypassTumor, num, num2, val); cc.Invoke(weaponHitDamageableContext); HitTrackerManager.RegisterHit(cwc.Owner, cwc, weaponHitDamageableContext); if (num > 1f) { hitData.damage *= num / num2; } else { doBackstab = false; } } else { cc.Invoke(new WeaponHitDamageableContext(hitData)); } } else { cc.Invoke(new WeaponHitContext(hitData)); } hitData.shotInfo.AddHit(hitData.damageType); hitData.Apply(); } } [HarmonyPatch] internal static class WeaponRayPatches { private static readonly HitData s_hitData = new HitData(DamageType.Bullet); private static IntPtr _cachedData = IntPtr.Zero; [HarmonyTargetMethod] private static MethodBase FindWeaponRayFunc(Harmony harmony) { return AccessTools.Method(typeof(Weapon), "CastWeaponRay", new Type[4] { typeof(Transform), typeof(WeaponHitData).MakeByRefType(), typeof(Vector3), typeof(int) }, (Type[])null); } [HarmonyWrapSafe] [HarmonyPrefix] private static bool PreRayCallback(ref WeaponHitData weaponRayData, Vector3 originPos, ref bool __result) { //IL_004e: 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) if (_cachedData == ((Il2CppObjectBase)weaponRayData).Pointer) { return true; } _cachedData = ((Il2CppObjectBase)weaponRayData).Pointer; CustomWeaponComponent cwc = ShotManager.ActiveFiringInfo.cwc; if ((Object)(object)cwc == (Object)null) { return true; } s_hitData.Setup(weaponRayData); cwc.Invoke(new WeaponPreRayContext(s_hitData, originPos)); float value = cwc.SpreadController.Value; if (value != 1f) { s_hitData.randomSpread *= value; s_hitData.angOffsetX *= value; s_hitData.angOffsetY *= value; } cwc.ShotComponent.FireVanilla(s_hitData, originPos); weaponRayData.maxRayDist = 0f; __result = false; return false; } } [HarmonyPatch] internal static class WeaponRecoilPatches { private static BulletWeapon? _cachedWeapon; private static CustomWeaponComponent? _cachedComponent; [HarmonyPatch(typeof(BulletWeapon), "OnWield")] [HarmonyWrapSafe] [HarmonyPostfix] private static void UpdateCurrentWeapon(BulletWeapon __instance) { PlayerAgent owner = ((Item)__instance).Owner; if (owner != null && ((Agent)owner).IsLocallyOwned) { _cachedWeapon = __instance; _cachedComponent = ((Component)__instance).GetComponent(); } } [HarmonyAfter(new string[] { "Dinorush.ExtraRecoilData" })] [HarmonyPatch(typeof(FPS_RecoilSystem), "ApplyRecoil")] [HarmonyWrapSafe] [HarmonyPostfix] private static void PostApplyRecoilCallback(FPS_RecoilSystem __instance, RecoilDataBlock recoilData) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_cachedComponent == (Object)null)) { WeaponRecoilContext weaponRecoilContext = new WeaponRecoilContext(); _cachedComponent.Invoke(weaponRecoilContext); if (weaponRecoilContext.Value != 1f) { Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(__instance.recoilDir.x * (weaponRecoilContext.Value - 1f), __instance.recoilDir.y * (weaponRecoilContext.Value - 1f)); Vector2 currentRecoilForce = __instance.currentRecoilForce; currentRecoilForce.x -= val.x * (1f - recoilData.worldToViewSpaceBlendVertical); currentRecoilForce.y -= val.y * (1f - recoilData.worldToViewSpaceBlendHorizontal); Vector2 currentRecoilForceVP = __instance.currentRecoilForceVP; currentRecoilForceVP.x -= val.x * recoilData.worldToViewSpaceBlendVertical; currentRecoilForceVP.y -= val.y * recoilData.worldToViewSpaceBlendHorizontal; Vector2 recoilDir = __instance.recoilDir; ((Vector2)(ref recoilDir)).Set(__instance.recoilDir.x * weaponRecoilContext.Value, __instance.recoilDir.y * weaponRecoilContext.Value); __instance.currentRecoilForce = currentRecoilForce; __instance.currentRecoilForceVP = currentRecoilForceVP; } } } } [HarmonyPatch] internal static class WeaponSyncPatches { public static readonly Dictionary _botFireFlags = new Dictionary(3); [InvokeOnCleanup(false)] private static void Cleanup() { _botFireFlags.Clear(); } public static void FlagStartFiring(PlayerAIBot bot) { IntPtr pointer = ((Il2CppObjectBase)bot.Agent).Pointer; if (!_botFireFlags.TryGetValue(pointer, out (bool, bool) value)) { value = (false, false); } _botFireFlags[((Il2CppObjectBase)bot.Agent).Pointer] = (value.Item1, true); } public static void FlagEndFiring(PlayerAIBot bot) { IntPtr pointer = ((Il2CppObjectBase)bot.Agent).Pointer; if (!_botFireFlags.TryGetValue(pointer, out (bool, bool) value)) { value = (false, false); } _botFireFlags[((Il2CppObjectBase)bot.Agent).Pointer] = (true, value.Item2); } [HarmonyPatch(typeof(ShotgunSynced), "Fire")] [HarmonyPatch(typeof(BulletWeaponSynced), "Fire")] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_FireSynced(BulletWeaponSynced __instance) { PlayerAgent owner = ((Item)__instance).Owner; bool flag = owner.Owner.IsBot && SNet.IsMaster; CustomGunComponent component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return; } if (flag) { int num; if (_botFireFlags.TryGetValue(((Il2CppObjectBase)owner).Pointer, out (bool, bool) value)) { num = (value.Item1 ? 1 : 0); if (num != 0) { component.Invoke(StaticContext.Instance); _botFireFlags[((Il2CppObjectBase)owner).Pointer] = (false, value.Item2); } } else { num = 0; } component.UpdateStoredFireRate(); if (num != 0) { component.Invoke(StaticContext.Instance); } component.Invoke(StaticContext.Instance); ShotManager.AdvanceGroupMod(component); } else { component.Invoke(StaticContext.Instance); component.UpdateStoredFireRate(); } } [HarmonyPatch(typeof(ShotgunSynced), "Fire")] [HarmonyPatch(typeof(BulletWeaponSynced), "Fire")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_FireSynced(BulletWeaponSynced __instance) { PlayerAgent owner = ((Item)__instance).Owner; bool flag = owner.Owner.IsBot && SNet.IsMaster; CustomGunComponent component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return; } component.NotifyShotFired(); ShotManager.CancelTracerFX(component); if (flag) { component.Invoke(new WeaponAmmoContext(((BulletWeapon)__instance).m_clip, ((ItemEquippable)__instance).ClipSize)); component.Invoke(StaticContext.Instance); if (_botFireFlags.TryGetValue(((Il2CppObjectBase)((Item)__instance).Owner).Pointer, out (bool, bool) value) && value.Item2) { component.Invoke(StaticContext.Instance); _botFireFlags[((Il2CppObjectBase)owner).Pointer] = (value.Item1, false); } } if (!flag) { component.Invoke(StaticContext.Instance); } component.ModifyFireRate(); } } } namespace EWC.Patches.Enemy { [HarmonyPatch] internal static class EnemyDeathPatches { [HarmonyPatch(typeof(EnemyBehaviour), "ChangeState", new Type[] { typeof(EB_States) })] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_Death(EnemyBehaviour __instance, EB_States state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 if (__instance.m_currentStateName != state && (int)state == 19) { HitTrackerManager.RunKillContexts((Agent?)(object)__instance.m_ai.m_enemyAgent); } } [HarmonyPatch(typeof(Dam_EnemyDamageLimb), "ShowHitIndicator")] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_DeathHitmarker(Dam_EnemyDamageLimb __instance, bool willDie) { if (willDie) { HitTrackerManager.RunKillContexts((Agent?)(object)__instance.m_base.Owner); } } } [HarmonyPatch] internal static class EnemyFoamPatches { [HarmonyPatch(typeof(Dam_EnemyDamageBase), "AddToTotalGlueVolume")] [HarmonyPriority(200)] [HarmonyWrapSafe] [HarmonyPostfix] private static void SyncWithFoamManager(Dam_EnemyDamageBase __instance, GlueGunProjectile? proj, GlueVolumeDesc volume) { //IL_0018: 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) float num = (((Object)(object)proj != (Object)null) ? proj.EffectMultiplier : 1f); FoamManager.AddFoam(__instance, (volume.volume + volume.expandVolume) * num, FoamManager.GetProjProperty(proj)); } } [HarmonyPatch] internal static class EnemyHitreactPatches { [HarmonyPatch(typeof(ES_Hitreact), "DoHitReact")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_DoHitreact(ES_HitreactBase __instance, ES_HitreactType hitreactType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)hitreactType == 3 || (int)hitreactType == 4) { HitTrackerManager.RunStaggerContexts((Agent?)(object)((ES_Base)__instance).m_enemyAgent, (int)hitreactType == 4); } } [HarmonyPatch(typeof(ES_HitreactFlyer), "DoHitReact", new Type[] { typeof(int), typeof(ES_HitreactType), typeof(ImpactDirection), typeof(float), typeof(bool), typeof(Vector3), typeof(Vector3) })] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_DoHitreactFlyer(ES_HitreactBase __instance, ES_HitreactType reactionType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)reactionType == 3 || (int)reactionType == 4) { HitTrackerManager.RunStaggerContexts((Agent?)(object)((ES_Base)__instance).m_enemyAgent, (int)reactionType == 4); } } } [HarmonyPatch] internal static class EnemyLimbPatches { private static float _cachedArmor = -1f; private static CustomWeaponComponent? _cachedCWC = null; private static ContextController? _cachedCC = null; public static bool CachedBypassTumorCap { get; set; } = false; public static void CacheComponents(CustomWeaponComponent cwc, ContextController cc) { _cachedCWC = cwc; _cachedCC = cc; } public static void ShowHitmarker(ContextController cc, Dam_EnemyDamageLimb limb, bool crit, bool willKill, Vector3 hitPos, bool armor) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) ContextController? cachedCC = _cachedCC; _cachedCC = cc; limb.ShowHitIndicator(crit, willKill, hitPos, armor); _cachedCC = cachedCC; } [HarmonyPatch(typeof(Dam_EnemyDamageLimb), "BulletDamage")] [HarmonyPatch(typeof(Dam_EnemyDamageLimb), "MeleeDamage")] [HarmonyWrapSafe] [HarmonyPrefix] private static void Pre_Damage(Dam_EnemyDamageLimb __instance) { if (!(__instance.m_armorDamageMulti >= 1f)) { _cachedArmor = __instance.m_armorDamageMulti; float armorMulti; if (_cachedCC != null) { armorMulti = _cachedCC.Invoke(new WeaponArmorContext(_cachedArmor)).ArmorMulti; DebuffManager.GetAndApplyArmorShredDebuff(ref armorMulti, ((Il2CppObjectBase)__instance).Cast(), _cachedCWC.DebuffIDs); } else { armorMulti = _cachedArmor; DebuffManager.GetAndApplyArmorShredDebuff(ref armorMulti, ((Il2CppObjectBase)__instance).Cast(), DebuffManager.DefaultGroupSet); } if (_cachedArmor == armorMulti) { _cachedArmor = -1f; } else { __instance.m_armorDamageMulti = armorMulti; } } } [HarmonyPatch(typeof(Dam_EnemyDamageLimb), "ShowHitIndicator")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool Pre_ShowHitMarker(Dam_EnemyDamageLimb __instance, bool willDie) { if (willDie) { return true; } if (_cachedCC != null) { return _cachedCC.Invoke(new WeaponHitmarkerContext(__instance.m_base.Owner)).Result; } return true; } [HarmonyPatch(typeof(Dam_EnemyDamageLimb), "BulletDamage")] [HarmonyPatch(typeof(Dam_EnemyDamageLimb), "MeleeDamage")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Post_Damage(Dam_EnemyDamageLimb __instance) { _cachedCC = null; _cachedCWC = null; if (_cachedArmor != -1f) { __instance.m_armorDamageMulti = _cachedArmor; _cachedArmor = -1f; } } [HarmonyPatch(typeof(Dam_EnemyDamageLimb_Custom), "ApplyWeakspotAndArmorModifiers")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool Pre_WeakspotModifiers(Dam_EnemyDamageLimb_Custom __instance, float dam, float precisionMulti, ref float __result) { if (!CachedBypassTumorCap) { return true; } __result = dam * Math.Max(((Dam_EnemyDamageLimb)__instance).m_weakspotDamageMulti * precisionMulti, 1f) * ((Dam_EnemyDamageLimb)__instance).m_armorDamageMulti; CachedBypassTumorCap = false; return false; } } [HarmonyPatch] internal static class FoamSpawnPatches { private const uint VanillaEnemyMergeIDMod = 32768u; [HarmonyPatch(typeof(ProjectileManager), "SpawnGlueGunProjectileIfNeeded")] [HarmonyWrapSafe] [HarmonyPostfix] private static void CachePropertyOnEnemySplitFoam(ProjectileManager __instance, uint syncID, GlueGunProjectile __result) { if ((syncID & 0x8000u) != 0 && __instance.m_glueGunProjectiles.ContainsKey(syncID & 0xFFFF7FFFu)) { GlueGunProjectile val = __instance.m_glueGunProjectiles[syncID & 0xFFFF7FFFu]; Foam projProperty = FoamManager.GetProjProperty(val); if (projProperty != null) { FoamManager.AddFoamBubble(__result, projProperty); } __result.m_glueStrengthMultiplier = val.m_glueStrengthMultiplier; __result.m_owner = val.m_owner; } } [HarmonyPatch(typeof(ProjectileManager), "GetNextSyncID")] [HarmonyPriority(600)] [HarmonyWrapSafe] [HarmonyPostfix] private static void FixSyncIDOverflow(ProjectileManager __instance, ref uint __result) { if ((__result & 0x8000u) != 0) { uint num2 = (__instance.m_nextID += 32768); __result = num2; } } } } namespace EWC.Patches.Checkpoint { [HarmonyPatch] internal static class GS_InLevelPatches { [HarmonyPatch(typeof(GS_InLevel), "Exit")] [HarmonyWrapSafe] [HarmonyPrefix] private static void ClearModifications() { CustomWeaponManager.ResetCWCs(activate: false); } } [HarmonyPatch] internal static class SyncManagerPatches { public static event Action? OnCheckpointReload; [HarmonyPatch(typeof(SNet_SyncManager), "OnRecallDone")] [HarmonyWrapSafe] [HarmonyPostfix] private static void Pre_Reload() { SyncManagerPatches.OnCheckpointReload?.Invoke(); } } } namespace EWC.Patches.Bot { [HarmonyPatch] internal static class BotPatches { [HarmonyPatch(typeof(PlayerBotActionUseFirearm), "StartShooting")] [HarmonyWrapSafe] [HarmonyPrefix] private static void OnStartFiring(PlayerBotActionUseFirearm __instance) { WeaponSyncPatches.FlagStartFiring(((PlayerBotActionBase)__instance).m_bot); } [HarmonyPatch(typeof(PlayerBotActionUseFirearm), "FireOneShot")] [HarmonyWrapSafe] [HarmonyPostfix] private static void OnShotQueued(PlayerBotActionUseFirearm __instance) { if (__instance.m_autoFireBulletsLeft == 1) { WeaponSyncPatches.FlagEndFiring(((PlayerBotActionBase)__instance).m_bot); } } } } namespace EWC.Networking { public abstract class SyncedEvent where T : struct { public delegate void ReceiveHandler(T packet); private bool _isSetup; public abstract string GUID { get; } public bool IsSetup => _isSetup; public string EventName { get; private set; } = string.Empty; public event ReceiveHandler? OnReceive; public event ReceiveHandler? OnReceiveLocal; public void Setup() { if (!_isSetup) { EventName = "EWC" + GUID; NetworkAPI.RegisterEvent(EventName, (Action)ReceiveClient_Callback); _isSetup = true; } } public void Send(T packetData, SNet_Player? target = null, SNet_ChannelType priority = 4) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target != (Object)null) { if (target.IsLocal) { Receive(packetData); } else { NetworkAPI.InvokeEvent(EventName, packetData, target, priority); } } else { NetworkAPI.InvokeEvent(EventName, packetData, priority); } ReceiveLocal_Callback(packetData); } private void ReceiveLocal_Callback(T packet) { ReceiveLocal(packet); this.OnReceiveLocal?.Invoke(packet); } private void ReceiveClient_Callback(ulong sender, T packet) { Receive(packet); this.OnReceive?.Invoke(packet); } protected virtual void ReceiveLocal(T packet) { } protected virtual void Receive(T packet) { } } public abstract class SyncedEventMasterOnly : SyncedEvent where T : struct { public void Send(T packet, SNet_ChannelType priority = 4) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!SNet.IsMaster) { Send(packet, SNet.Master, priority); } else { Receive(packet); } } } } namespace EWC.Networking.Structs { public struct LowResColor { public byte r; public byte g; public byte b; public byte a; private static Color s_color = Color.black; public static implicit operator Color(LowResColor lowResColor) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) s_color.r = (float)(int)lowResColor.r / 255f; s_color.g = (float)(int)lowResColor.g / 255f; s_color.b = (float)(int)lowResColor.b / 255f; s_color.a = (float)(int)lowResColor.a / 255f; return s_color; } public static implicit operator LowResColor(Color color) { //IL_000a: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) LowResColor result = default(LowResColor); result.r = (byte)(color.r * 255f); result.g = (byte)(color.g * 255f); result.b = (byte)(color.b * 255f); result.a = (byte)(color.a * 255f); return result; } } public struct SFloat16b { public ushort internalValue; private const float convOut = 1.5259022E-05f; private const float convIn = 65535f; public float Value { readonly get { return (float)(int)internalValue * 1.5259022E-05f; } set { internalValue = (ushort)(Mathf.Clamp01(value) * 65535f); } } public void Set(float v, float maxSize) { Value = (v + maxSize) / (maxSize * 2f); } public readonly float Get(float maxSize) { return Value * maxSize * 2f - maxSize; } } public struct UFloat16b { public ushort internalValue; private const float convOut = 1.5259022E-05f; private const float convIn = 65535f; public float Value { readonly get { return (float)(int)internalValue * 1.5259022E-05f; } set { internalValue = (ushort)(Mathf.Clamp01(value) * 65535f); } } public void Set(float v, float maxSize) { Value = v / maxSize; } public readonly float Get(float maxSize) { return Value * maxSize; } } public struct UFloat8b { public byte internalValue; private const float convOut = 0.003921569f; private const float convIn = 255f; public float Value { readonly get { return (float)(int)internalValue * 0.003921569f; } set { internalValue = (byte)(Mathf.Clamp01(value) * 255f); } } public void Set(float v, float maxSize) { Value = v / maxSize; } public readonly float Get(float maxSize) { return Value * maxSize; } } public struct Vector3_24b_Normalized { private UFloat8b x; private UFloat8b y; private UFloat8b z; private static Vector3 s_tempVec = Vector3.zero; public Vector3 Value { readonly get { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) ((Vector3)(ref s_tempVec)).Set(x.Value - 0.5f, y.Value - 0.5f, z.Value - 0.5f); s_tempVec *= 2f; return s_tempVec; } set { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_002a: 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) value *= 0.5f; x.Value = value.x + 0.5f; y.Value = value.y + 0.5f; z.Value = value.z + 0.5f; } } } public struct Vector3_32b { private Vector3_24b_Normalized vector; private UFloat8b length; public void Set(Vector3 vec, float maxLength) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) float magnitude = ((Vector3)(ref vec)).magnitude; length.Set(magnitude, maxLength); ((Vector3)(ref vec)).Normalize(); vector.Value = vec; } public readonly Vector3 Get(float maxLength) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) return vector.Value * length.Get(maxLength); } } } namespace EWC.JSON { internal static class CustomWeaponTemplate { internal static CustomWeaponData CreateTemplate() { IEnumerable source = from t in Assembly.GetExecutingAssembly().GetTypes() where t.Namespace?.StartsWith(typeof(WeaponPropertyBase).Namespace) ?? false select t; IOrderedEnumerable orderedEnumerable = from t in source where t.Namespace.EndsWith("Effects") && t.IsAssignableTo(typeof(WeaponPropertyBase)) && !t.IsAbstract orderby t.Name select t; IOrderedEnumerable orderedEnumerable2 = from t in source where t.Namespace.EndsWith("Traits") && t.IsAssignableTo(typeof(WeaponPropertyBase)) && !t.IsAbstract orderby t.Name select t; List list = new List { new ReferenceProperty() }; foreach (Type item in orderedEnumerable) { list.Add((WeaponPropertyBase)Activator.CreateInstance(item)); } foreach (Type item2 in orderedEnumerable2) { list.Add((WeaponPropertyBase)Activator.CreateInstance(item2)); } return new CustomWeaponData { ArchetypeID = 0u, Name = "Example", Properties = new PropertyList(list) }; } } public static class EWCJson { private static readonly JsonSerializerOptions _setting; static EWCJson() { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown _setting = new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip, IncludeFields = true, PropertyNameCaseInsensitive = true, WriteIndented = true, IgnoreReadOnlyProperties = true }; _setting.Converters.Add(new JsonStringEnumConverter()); _setting.Converters.Add(new TriggerConverter()); _setting.Converters.Add(new TriggerCoordinatorConverter()); _setting.Converters.Add(new WeaponPropertyConverter()); _setting.Converters.Add(new PropertyListConverter()); _setting.Converters.Add(new DebuffGroupConverter()); _setting.Converters.Add((JsonConverter)new ColorConverter()); if (PDAPIWrapper.HasPData) { _setting.Converters.Add(PDAPIWrapper.PersistentIDConverter); } } public static T? Deserialize(string json) { return JsonSerializer.Deserialize(json, _setting); } public static T? Deserialize(ref Utf8JsonReader reader) { return JsonSerializer.Deserialize(ref reader, _setting); } public static object? Deserialize(Type type, string json) { return JsonSerializer.Deserialize(json, type, _setting); } public static string Serialize(T value) { return JsonSerializer.Serialize(value, _setting); } public static void Serialize(Utf8JsonWriter writer, T value) { JsonSerializer.Serialize(writer, value, _setting); } public static void Serialize(Utf8JsonWriter writer, string name, T value) { writer.WritePropertyName(name); JsonSerializer.Serialize(writer, value, _setting); } } } namespace EWC.JSON.Converters { public sealed class DebuffGroupConverter : JsonConverter { public override DebuffGroup? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { DebuffGroup debuffGroup = new DebuffGroup(); if (reader.TokenType == JsonTokenType.Null) { debuffGroup.IDs = DebuffManager.DefaultGroupSet; return debuffGroup; } debuffGroup.IDs = new HashSet(); if (reader.TokenType == JsonTokenType.String || reader.TokenType == JsonTokenType.Number) { debuffGroup.IDs.Add(ReadToken(ref reader)); return debuffGroup; } if (reader.TokenType != JsonTokenType.StartArray) { throw new JsonException("Expected DebuffIDs to be string, int, or array"); } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndArray) { return debuffGroup; } debuffGroup.IDs.Add(ReadToken(ref reader)); } throw new JsonException("Expected EndArray token"); } public override void Write(Utf8JsonWriter writer, DebuffGroup? value, JsonSerializerOptions options) { writer.WriteNumberValue(0); } private static uint ReadToken(ref Utf8JsonReader reader) { if (reader.TokenType == JsonTokenType.String) { return DebuffManager.StringIDToInt(reader.GetString()); } if (reader.TokenType == JsonTokenType.Number) { return reader.GetUInt32(); } throw new JsonException("DebuffIDs expected a string or int but got " + reader.TokenType); } } public sealed class PropertyListConverter : JsonConverter { public override PropertyList Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return new PropertyList(EWCJson.Deserialize>(ref reader) ?? throw new JsonException("Unable to deserialize property list")); } public override void Write(Utf8JsonWriter writer, PropertyList value, JsonSerializerOptions options) { EWCJson.Serialize(writer, value.Values); } } public sealed class TriggerConverter : JsonConverter { public override ITrigger? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) { return null; } if (reader.TokenType == JsonTokenType.String) { return ITrigger.GetTrigger(reader.GetString()); } if (reader.TokenType == JsonTokenType.Number) { return new ReferenceCallTrigger(reader.GetUInt32()); } if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException("Expected Trigger to be either a string or object"); } ITrigger trigger = CreateTriggerInstance(reader); if (trigger == null) { return null; } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return trigger; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); trigger.DeserializeProperty(@string.ToLowerInvariant().Replace(" ", ""), ref reader); } throw new JsonException("Expected EndObject token"); } public override void Write(Utf8JsonWriter writer, ITrigger? value, JsonSerializerOptions options) { if (value == null) { writer.WriteNullValue(); } else { writer.WriteStringValue(value.Name.ToString()); } } private static ITrigger? CreateTriggerInstance(Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartObject) { return null; } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject || reader.TokenType == JsonTokenType.StartObject) { throw new JsonException("Trigger object does not contain Name field."); } if (reader.TokenType == JsonTokenType.PropertyName && !(reader.GetString().ToLowerInvariant() != "name")) { reader.Read(); if (reader.TokenType == JsonTokenType.Number) { return new ReferenceCallTrigger(reader.GetUInt32()); } return ITrigger.GetTrigger(reader.GetString() ?? throw new JsonException("Name field cannot be empty in trigger object.")); } } return null; } } public sealed class TriggerCoordinatorConverter : JsonConverter { public override TriggerCoordinator? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) { return null; } TriggerCoordinator triggerCoordinator = new TriggerCoordinator(); if (reader.TokenType == JsonTokenType.String) { ITrigger trigger = EWCJson.Deserialize(ref reader); if (trigger != null) { triggerCoordinator.Activate.Triggers.Add(trigger); return triggerCoordinator; } return null; } if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException("Expected Trigger Coordinator to be either a string or object"); } ITrigger trigger2 = null; try { trigger2 = EWCJson.Deserialize(ref reader); } catch (JsonException) { } if (trigger2 != null) { triggerCoordinator.Activate.Triggers.Add(trigger2); return triggerCoordinator; } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return triggerCoordinator; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); triggerCoordinator.DeserializeProperty(@string.ToLowerInvariant().Replace(" ", ""), ref reader); } throw new JsonException("Expected EndObject token"); } public override void Write(Utf8JsonWriter writer, TriggerCoordinator? value, JsonSerializerOptions options) { if (value == null) { writer.WriteNullValue(); } else { writer.WriteStringValue(value.Activate.Triggers[0].Name.ToString()); } } } public sealed class WeaponPropertyConverter : JsonConverter { private static readonly string PropertyNamespace = typeof(WeaponPropertyBase).Namespace; private static readonly Dictionary LegacyNames = new Dictionary { ["damagemod"] = typeof(ShotMod), ["damagemodpertarget"] = typeof(ShotModPerTarget) }; public override WeaponPropertyBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { WeaponPropertyBase weaponPropertyBase = CreatePropertyInstance(reader); if (weaponPropertyBase == null || reader.TokenType != JsonTokenType.StartObject) { return weaponPropertyBase; } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return weaponPropertyBase; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); weaponPropertyBase.DeserializeProperty(@string.ToLowerInvariant().Replace(" ", ""), ref reader); } throw new JsonException("Expected EndObject token"); } public override void Write(Utf8JsonWriter writer, WeaponPropertyBase value, JsonSerializerOptions options) { value.Serialize(writer); } private static WeaponPropertyBase? CreatePropertyInstance(Utf8JsonReader reader) { if (reader.TokenType == JsonTokenType.String) { return new ReferenceProperty(reader.GetString()); } if (reader.TokenType == JsonTokenType.Number) { return new ReferenceProperty(reader.GetUInt32()); } if (reader.TokenType != JsonTokenType.StartObject) { return null; } int num = 1; while (reader.Read()) { if (reader.TokenType == JsonTokenType.StartObject) { num++; } if (reader.TokenType == JsonTokenType.EndObject && --num == 0) { throw new JsonException("Weapon property does not contain Name field."); } if (num == 1 && reader.TokenType == JsonTokenType.PropertyName && !(reader.GetString().ToLowerInvariant() != "name")) { reader.Read(); return NameToProperty(reader.GetString() ?? throw new JsonException("Name field cannot be empty in weapon property.")); } } return null; } private static WeaponPropertyBase? NameToProperty(string name) { name = name.Replace(" ", ""); string text = name.ToLower(); if (text == "ReferenceProperty".ToLower()) { return new ReferenceProperty(); } if (!LegacyNames.TryGetValue(text, out Type value)) { value = Type.GetType(PropertyNamespace + ".Effects." + name, throwOnError: false, ignoreCase: true) ?? Type.GetType(PropertyNamespace + ".Traits." + name, throwOnError: false, ignoreCase: true); } if (value == null) { throw new JsonException("Unable to find property with name " + name); } return (WeaponPropertyBase)Activator.CreateInstance(value); } } } namespace EWC.Dependencies { internal static class ACAPIWrapper { public const string PLUGIN_GUID = "Dinorush.AccurateCrosshair"; public static readonly bool hasAC; static ACAPIWrapper() { hasAC = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Dinorush.AccurateCrosshair"); } public static void UpdateCrosshairSpread(float mod) { if (hasAC) { UpdateCrosshairSpread_AC(mod); } } public static void ResetCrosshairSpread() { if (hasAC) { ResetCrosshairSpread_AC(); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void UpdateCrosshairSpread_AC(float mod) { SpreadAPI.SetModifier((object)"ExtraWeaponCustomization", mod); } [MethodImpl(MethodImplOptions.NoInlining)] private static void ResetCrosshairSpread_AC() { SpreadAPI.RemoveModifier((object)"ExtraWeaponCustomization"); } } internal static class AmorLibWrapper { public const string PLUGIN_GUID = "com.dak.MTFO"; } internal static class DamageSyncWrapper { public const string PLUGIN_GUID = "randomuserhi.DamageSync"; public static readonly bool hasDS; static DamageSyncWrapper() { hasDS = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("randomuserhi.DamageSync"); } public static void RunDamageSync(EnemyAgent enemy, int limbID) { if (hasDS) { RunDamageSync_Internal(enemy, limbID); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void RunDamageSync_Internal(EnemyAgent enemy, int limbID) { DamageSync.Sync(enemy, limbID); } } internal static class EECAPIWrapper { public const string PLUGIN_GUID = "GTFO.EECustomization"; public static readonly bool HasEEC; static EECAPIWrapper() { HasEEC = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("GTFO.EECustomization"); } public static void StopBleed(PlayerAgent agent) { if (HasEEC) { StopBleed_Internal(agent); } } [MethodImpl(MethodImplOptions.NoInlining)] public static void StopBleed_Internal(PlayerAgent agent) { BleedManager.StopBleed(agent); } } internal static class ERDAPIWrapper { public const string PLUGIN_GUID = "Dinorush.ExtraRecoilData"; public static readonly bool hasERD; static ERDAPIWrapper() { hasERD = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Dinorush.ExtraRecoilData"); } public static void ChangeCustomRecoil(uint archetypeID, BulletWeapon weapon) { if (hasERD) { ERD_ChangeERDComponent(archetypeID, weapon); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void ERD_ChangeERDComponent(uint archetypeID, BulletWeapon weapon) { ChangeAPI.ChangeERDComponent(archetypeID, weapon); } } internal static class ETCWrapper { public const string PLUGIN_GUID = "Dinorush.ExtraToolCustomization"; public static readonly bool hasETC; static ETCWrapper() { hasETC = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Dinorush.ExtraToolCustomization"); } public static bool CanDoBackDamage(uint archetypeID) { if (hasETC) { return ETC_CanDoBackDamage(archetypeID); } return false; } [MethodImpl(MethodImplOptions.NoInlining)] private static bool ETC_CanDoBackDamage(uint archetypeID) { SentryData archData = ToolDataManager.GetArchData(archetypeID); if (archData == null) { return false; } return archData.BackDamage; } } internal static class EXPAPIWrapper { public const string PLUGIN_GUID = "Endskill.GTFuckingXP"; public static readonly bool HasEXP; static EXPAPIWrapper() { HasEXP = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Endskill.GTFuckingXP"); } public static float GetCapacityMod(IOwnerComp owner) { if (!HasEXP) { return 1f; } return EXPGetCapacityMod(owner); } public static float GetExplosionResistanceMod(PlayerAgent player) { if (!HasEXP) { return 1f; } return EXPGetExplosionResistanceMod(player); } public static float GetDamageMod(bool local, WeaponType type) { if (!local || !HasEXP || !PlayerManager.HasLocalPlayerAgent()) { return 1f; } return EXPGetDamageMod(type); } public static float GetHealthRegenMod(PlayerAgent player) { if (!HasEXP) { return 1f; } return EXPGetHealthRegenMod(player); } public static void RegisterDamage(EnemyAgent enemy, PlayerAgent? source, float damage, bool willKill) { if (HasEXP) { EXPDidDamage(enemy, source, damage, willKill); } } [MethodImpl(MethodImplOptions.NoInlining)] private static float EXPGetCapacityMod(IOwnerComp owner) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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) Level val = default(Level); if (!CacheApiWrapper.TryGetActiveLevel(owner.Player, ref val)) { return 1f; } CustomScaling key = (CustomScaling)(owner.IsType(OwnerType.Sentry) ? 15 : 12); CustomScaling key2 = (CustomScaling)(owner.IsType(OwnerType.Sentry) ? 17 : 14); Dictionary customScaling = val.CustomScaling; return customScaling.GetValueOrDefault(key, 1f) * customScaling.GetValueOrDefault(key2, 1f); } [MethodImpl(MethodImplOptions.NoInlining)] private static float EXPGetDamageMod(WeaponType type) { if (type.HasFlag(WeaponType.BulletWeapon)) { return CacheApiWrapper.GetActiveLevel().WeaponDamageMultiplier; } if (type.HasFlag(WeaponType.Melee)) { return CacheApiWrapper.GetActiveLevel().MeleeDamageMultiplier; } return 1f; } [MethodImpl(MethodImplOptions.NoInlining)] private static float EXPGetExplosionResistanceMod(PlayerAgent player) { Level val = default(Level); if (!CacheApiWrapper.TryGetActiveLevel(player, ref val)) { return 1f; } if (!val.CustomScaling.TryGetValue((CustomScaling)18, out var value)) { return 1f; } return 2f - value; } [MethodImpl(MethodImplOptions.NoInlining)] private static float EXPGetHealthRegenMod(PlayerAgent player) { Level val = default(Level); if (!CacheApiWrapper.TryGetActiveLevel(player, ref val)) { return 1f; } if (!val.CustomScaling.TryGetValue((CustomScaling)10, out var value)) { return 1f; } return value; } [MethodImpl(MethodImplOptions.NoInlining)] private static void EXPDidDamage(EnemyAgent enemy, PlayerAgent? source, float damage, bool willKill) { EnemyKillApi.RegisterDamage(enemy, source, damage, willKill); } } internal static class FSFAPIWrapper { public const string PLUGIN_GUID = "Dinorush.FlickShotFix"; public static readonly bool hasFSF; static FSFAPIWrapper() { hasFSF = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Dinorush.FlickShotFix"); } } public static class KillAPIWrapper { public const string PLUGIN_GUID = "randomuserhi.KillIndicatorFix"; public static readonly bool HasKIF; static KillAPIWrapper() { HasKIF = ((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("randomuserhi.KillIndicatorFix"); } public static void TagEnemy(EnemyAgent enemy, ItemEquippable? item = null, Vector3? localHitPosition = null) { if (HasKIF) { TagEnemy_Internal(enemy, item, localHitPosition); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void TagEnemy_Internal(EnemyAgent enemy, ItemEquippable? item, Vector3? localHitPosition) { Kill.TagEnemy(enemy, item, localHitPosition); } } internal static class MTFOAPIWrapper { public const string PLUGIN_GUID = "com.dak.MTFO"; public static string GameDataPath => MTFOPathAPI.RundownPath; public static string CustomPath => MTFOPathAPI.CustomPath; public static bool HasCustomContent => MTFOPathAPI.HasRundownPath; } internal static class PDAPIWrapper { public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks"; public static readonly bool HasPData; public static JsonConverter? PersistentIDConverter { get; private set; } static PDAPIWrapper() { if (!((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("MTFO.Extension.PartialBlocks", out var value)) { return; } try { PersistentIDConverter = (JsonConverter)Activator.CreateInstance((((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? throw new Exception("Assembly is Missing!")).GetTypes().First((Type t) => t.Name == "PersistentIDConverter") ?? throw new Exception("Unable to Find PersistentIDConverter Class")); HasPData = true; } catch (Exception value2) { EWCLogger.Error($"Exception thrown while reading data from MTFO_Extension_PartialData:\n{value2}"); } } } } namespace EWC.CustomWeapon { public sealed class CustomDataManager { public static readonly CustomDataManager Current = new CustomDataManager(); private readonly Dictionary> _fileToGuns = new Dictionary>(); private readonly Dictionary> _fileToMelees = new Dictionary>(); private readonly SortedDictionary _customGunData = new SortedDictionary(); private readonly SortedDictionary _customMeleeData = new SortedDictionary(); private readonly List _syncedProperties = new List(); public static readonly InventorySlot[] ValidSlots; public string DEFINITION_PATH { get; private set; } public static bool TryGetCustomData(IWeaponComp weaponComp, [MaybeNullWhen(false)] out CustomWeaponData data) { if (weaponComp.IsType(WeaponType.Melee)) { return TryGetCustomMeleeData(((GameDataBlockBase)(object)((ItemEquippable)((MeleeComp)weaponComp).Value).MeleeArchetypeData).persistentID, out data); } if (weaponComp.IsType(WeaponType.SentryHolder)) { if (TryGetCustomGunData(((GameDataBlockBase)(object)((IAmmoComp)weaponComp).ArchetypeData).persistentID, out data)) { return !data.IgnoreHeldSentry; } return false; } return TryGetCustomGunData(((GameDataBlockBase)(object)((IAmmoComp)weaponComp).ArchetypeData).persistentID, out data); } public static bool TryGetCustomData(ItemEquippable item, [MaybeNullWhen(false)] out CustomWeaponData data) { if (item.ArchetypeData == null && item.MeleeArchetypeData == null) { data = null; return false; } if ((Object)(object)((Il2CppObjectBase)item).TryCast() != (Object)null) { return TryGetCustomMeleeData(((GameDataBlockBase)(object)item.MeleeArchetypeData).persistentID, out data); } if ((Object)(object)((Il2CppObjectBase)item).TryCast() != (Object)null) { if (TryGetCustomGunData(item.ArchetypeID, out data)) { return !data.IgnoreHeldSentry; } return false; } return TryGetCustomGunData(item.ArchetypeID, out data); } public static bool TryGetCustomGunData(uint id, [MaybeNullWhen(false)] out CustomWeaponData data) { data = GetCustomGunData(id); return data != null; } public static CustomWeaponData? GetCustomGunData(uint id) { return Current._customGunData.GetValueOrDefault(id); } public static bool TryGetCustomMeleeData(uint id, [MaybeNullWhen(false)] out CustomWeaponData data) { data = GetCustomMeleeData(id); return data != null; } public static CustomWeaponData? GetCustomMeleeData(uint id) { return Current._customMeleeData.GetValueOrDefault(id); } public static bool TryGetSyncProperty(ushort id, [MaybeNullWhen(false)] out T property) where T : ISyncProperty { property = GetSyncProperty(id); return property != null; } public static T? GetSyncProperty(ushort id) where T : ISyncProperty { if (id < Current._syncedProperties.Count) { ISyncProperty syncProperty = Current._syncedProperties[id]; if (syncProperty is T) { return (T)syncProperty; } } return default(T); } private void OnReload() { RegisterSyncedProperties(); PrintCustomIDs(); CustomWeaponManager.ResetCWCs(); } private void FileChanged(LiveEditEventArgs e) { LiveEditEventArgs e2 = e; EWCLogger.Warning("LiveEdit File Changed: " + e2.FileName); LiveEdit.TryReadFileContent(e2.FullPath, (Action)delegate(string content) { ReadFileContent(e2.FullPath, content); OnReload(); }); } private void FileDeleted(LiveEditEventArgs e) { EWCLogger.Warning("LiveEdit File Removed: " + e.FileName); if (!_fileToGuns.ContainsKey(e.FullPath)) { PrintCustomIDs(); return; } foreach (uint item in _fileToGuns[e.FullPath]) { _customGunData.Remove(item); } _fileToGuns.Remove(e.FullPath); foreach (uint item2 in _fileToMelees[e.FullPath]) { _customMeleeData.Remove(item2); } _fileToMelees.Remove(e.FullPath); OnReload(); } private void FileCreated(LiveEditEventArgs e) { LiveEditEventArgs e2 = e; EWCLogger.Warning("LiveEdit File Created: " + e2.FileName); LiveEdit.TryReadFileContent(e2.FullPath, (Action)delegate(string content) { ReadFileContent(e2.FullPath, content); OnReload(); }); } private void ReadFileContent(string file, string content) { if (!_fileToGuns.ContainsKey(file)) { _fileToGuns[file] = new HashSet(); _fileToMelees[file] = new HashSet(); } HashSet hashSet = _fileToGuns[file]; foreach (uint item in hashSet) { _customGunData.Remove(item); } hashSet.Clear(); hashSet = _fileToMelees[file]; foreach (uint item2 in hashSet) { _customMeleeData.Remove(item2); } hashSet.Clear(); List list = null; try { list = EWCJson.Deserialize>(content); } catch (JsonException ex) { EWCLogger.Error("Error parsing custom weapon json " + file); EWCLogger.Error(ex.Message); } if (list == null) { return; } foreach (CustomWeaponData item3 in list) { if (item3 != null) { if (item3.ArchetypeID != 0 && _customGunData.ContainsKey(item3.ArchetypeID)) { EWCLogger.Warning("Duplicate archetype ID " + item3.ArchetypeID + " found. Previous name: " + _customGunData[item3.ArchetypeID].Name + ", new name: " + item3.Name); } if (item3.MeleeArchetypeID != 0 && _customMeleeData.ContainsKey(item3.MeleeArchetypeID)) { EWCLogger.Warning("Duplicate melee archetype ID " + item3.MeleeArchetypeID + " found. Previous name: " + _customMeleeData[item3.MeleeArchetypeID].Name + ", new name: " + item3.Name); } AddCustomWeaponData(item3, file); } } } private void AddCustomWeaponData(CustomWeaponData? data, string file) { if (data != null) { if (data.ArchetypeID != 0) { _fileToGuns[file].Add(data.ArchetypeID); _customGunData[data.ArchetypeID] = data; } if (data.MeleeArchetypeID != 0) { _fileToMelees[file].Add(data.MeleeArchetypeID); _customMeleeData[data.MeleeArchetypeID] = data; } } } private void RegisterSyncedProperties() { _syncedProperties.Clear(); foreach (CustomWeaponData value in _customGunData.Values) { RegisterSyncedProperties_Recurse(value.Properties); } foreach (CustomWeaponData value2 in _customMeleeData.Values) { RegisterSyncedProperties_Recurse(value2.Properties); } } private void RegisterSyncedProperties_Recurse(PropertyList list) { foreach (WeaponPropertyBase item in list) { if (item is ISyncProperty syncProperty) { syncProperty.SyncPropertyID = (ushort)_syncedProperties.Count; _syncedProperties.Add(syncProperty); } if (item is IPropertyHolder propertyHolder) { RegisterSyncedProperties_Recurse(propertyHolder.Properties); } } } internal void CreateTemplate() { string path = Path.Combine(DEFINITION_PATH, "Template.json"); if (!Directory.Exists(DEFINITION_PATH)) { EWCLogger.Log("No directory detected. Creating template."); Directory.CreateDirectory(DEFINITION_PATH); } StreamWriter streamWriter = File.CreateText(path); streamWriter.WriteLine(EWCJson.Serialize(new List { CustomWeaponTemplate.CreateTemplate() })); streamWriter.Flush(); streamWriter.Close(); } private void PrintCustomIDs() { StringBuilder stringBuilder = new StringBuilder("Found custom blocks for archetype IDs: "); stringBuilder.AppendJoin(", ", _customGunData.Keys); EWCLogger.Log(stringBuilder.ToString()); stringBuilder.Clear(); stringBuilder.Append("Found custom blocks for melee archetype IDs: "); stringBuilder.AppendJoin(", ", _customMeleeData.Keys); EWCLogger.Log(stringBuilder.ToString()); } private CustomDataManager() { DEFINITION_PATH = Path.Combine(MTFOPathAPI.CustomPath, "ExtraWeaponCustomization"); if (!Directory.Exists(DEFINITION_PATH)) { CreateTemplate(); } else { EWCLogger.Log("Directory detected."); } ReadDirectory(DEFINITION_PATH); } internal void ReadDirectory(string directory, bool liveEdit = true) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown foreach (string item in Directory.EnumerateFiles(directory, "*.json", SearchOption.AllDirectories)) { string content = File.ReadAllText(item); ReadFileContent(item, content); } OnReload(); if (liveEdit) { LiveEditListener obj = LiveEdit.CreateListener(directory, "*.json", true); obj.FileCreated += new LiveEditEventHandler(FileCreated); obj.FileChanged += new LiveEditEventHandler(FileChanged); obj.FileDeleted += new LiveEditEventHandler(FileDeleted); } } static CustomDataManager() { InventorySlot[] array = new InventorySlot[4]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); ValidSlots = (InventorySlot[])(object)array; } } public sealed class CustomGunComponent : CustomWeaponComponent { public readonly IGunComp Gun; private float _lastShotTimer; private float _lastBurstTimer; private float _lastFireRate; private float _lastFireTime; private float _currentChargeSpeed = 1f; private float _baseChargeTime; private float _startChargeTime; private float _burstDelay; private float _cooldownDelay; public bool CancelShot { get; set; } public float CurrentFireRate { get; private set; } public float CurrentBurstDelay { get; private set; } public float CurrentCooldownDelay { get; private set; } public float CurrentChargeMod { get; private set; } public float BaseFireRate { get; private set; } public CustomGunComponent(IntPtr value) : base(value) { Gun = (IGunComp)Weapon; ArchetypeDataBlock archetypeData = Gun.ArchetypeData; CurrentFireRate = (_lastFireRate = (BaseFireRate = 1f / Math.Max(archetypeData.ShotDelay, 0.001953125f))); CurrentBurstDelay = (_burstDelay = archetypeData.BurstDelay); CurrentCooldownDelay = (_cooldownDelay = archetypeData.SpecialCooldownTime); CurrentChargeMod = 1f; _baseChargeTime = archetypeData.SpecialChargetupTime; } [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } public override void OnWield() { RefreshSoundDelay(); base.OnWield(); ArchetypeDataBlock archetypeData = Gun.ArchetypeData; archetypeData.SpecialChargetupTime *= CurrentChargeMod; } public override void OnUnWield() { base.OnUnWield(); Gun.ArchetypeData.SpecialChargetupTime = _baseChargeTime; } protected override void Update() { base.Update(); if (base.Owner.IsType(OwnerType.Local)) { if (!((LocalGunComp)Gun).GunArchetype.m_inChargeup) { _startChargeTime = 0f; } else if (_startChargeTime == 0f) { _startChargeTime = Clock.Time; Invoke(StaticContext.Instance); } } } public override void Clear() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) base.Clear(); CurrentFireRate = BaseFireRate; CurrentBurstDelay = _burstDelay; CurrentCooldownDelay = _cooldownDelay; Gun.ArchetypeData.SpecialChargetupTime = _baseChargeTime; CurrentChargeMod = 1f; _currentChargeSpeed = 1f; if (!_destroyed) { Weapon.Sound.SetRTPCValue(GAME_PARAMETERS.FIREDELAY, 1f / CurrentFireRate); } } public void StoreCancelShot() { if (!CancelShot) { Invoke(StaticContext.Instance); CancelShot = true; } } public bool ResetShotIfCancel(BulletWeaponArchetype archetype) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (CancelShot) { archetype.m_fireHeld = false; archetype.m_nextShotTimer = _lastShotTimer; archetype.m_nextBurstTimer = _lastBurstTimer; CurrentFireRate = _lastFireRate; Weapon.Sound.SetRTPCValue(GAME_PARAMETERS.FIREDELAY, 1f / CurrentFireRate); if (((LocalGunComp)Gun).TryGetBurstArchetype(out BWA_Burst burstArchetype)) { burstArchetype.m_burstCurrentCount = 0; } return true; } return false; } public void RefreshArchetypeCache(ArchetypeDataBlock oldBlock) { ArchetypeDataBlock archetypeData = Gun.ArchetypeData; BaseFireRate = 1f / Math.Max(archetypeData.ShotDelay, 0.001953125f); _burstDelay = archetypeData.BurstDelay; _cooldownDelay = archetypeData.SpecialCooldownTime; if (base.Owner.IsType(OwnerType.Local)) { oldBlock.SpecialChargetupTime = _baseChargeTime; _baseChargeTime = archetypeData.SpecialChargetupTime; if (SpreadController.Active) { archetypeData.SpecialChargetupTime = _baseChargeTime * CurrentChargeMod; } } UpdateStoredFireRate(); } public void RefreshSoundDelay() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) Weapon.Sound.SetRTPCValue(GAME_PARAMETERS.FIREDELAY, 1f / CurrentFireRate); } public void NotifyShotFired() { _lastFireTime = Clock.Time; } public void UpdateChargeTime(bool forceUpdateTime = false) { float num = Math.Max(0.001f, Invoke(new WeaponChargeSpeedContext()).Value); if (num == _currentChargeSpeed) { return; } _currentChargeSpeed = Math.Max(num, 0.001f); CurrentChargeMod = 1f / _currentChargeSpeed; Gun.ArchetypeData.SpecialChargetupTime = _baseChargeTime * CurrentChargeMod; if (forceUpdateTime) { BulletWeaponArchetype gunArchetype = ((LocalGunComp)Gun).GunArchetype; if (gunArchetype.m_inChargeup) { gunArchetype.m_chargeupTimer = _startChargeTime + _baseChargeTime * CurrentChargeMod; } } } public void UpdateStoredFireRate(bool isTagged = false) { _lastFireRate = CurrentFireRate; if (base.Owner.IsType(OwnerType.Local)) { BulletWeaponArchetype gunArchetype = ((LocalGunComp)Gun).GunArchetype; _lastShotTimer = gunArchetype.m_nextShotTimer; _lastBurstTimer = gunArchetype.m_nextBurstTimer; } float num = BaseFireRate; if (base.Owner.IsType(OwnerType.Sentry)) { float num2 = (isTagged ? Gun.ArchetypeData.Sentry_ShotDelayTagMulti : 1f); num2 = AgentModifierManager.ApplyModifier((Agent)(object)base.Owner.Player, (AgentModifier)102, num2); num /= num2; } float value = Invoke(new WeaponFireRateContext(num)).Value; value = Math.Clamp(value, 0.001f, 512f); if (CurrentFireRate != value) { CurrentFireRate = value; CurrentBurstDelay = _burstDelay * num / CurrentFireRate; CurrentCooldownDelay = _cooldownDelay * num / CurrentFireRate; RefreshSoundDelay(); } } public void ModifyFireRate() { float nextShotTime = Gun.ModifyFireRate(_lastFireTime, 1f / CurrentFireRate, CurrentBurstDelay, CurrentCooldownDelay); Invoke(new WeaponShotCooldownContext(nextShotTime)); } } public sealed class CustomMeleeComponent : CustomWeaponComponent { public readonly MeleeComp Melee; private readonly IStatModifier _speedModifier; public float CurrentAttackSpeed => _speedModifier.Mod; public CustomMeleeComponent(IntPtr value) : base(value) { Melee = (MeleeComp)Weapon; _speedModifier = MeleeAttackSpeedAPI.AddModifier(1f, (StackLayer)0, "EWC"); } [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } public override void Clear() { base.Clear(); _speedModifier.Disable(); _speedModifier.Mod = 1f; } public void UpdateAttackSpeed() { _speedModifier.Enable(Invoke(new WeaponFireRateContext(1f)).Value); } } public class CustomWeaponComponent : MonoBehaviour { public readonly IWeaponComp Weapon; public readonly CustomShotComponent ShotComponent; public readonly SpreadController SpreadController; private readonly PropertyController _propertyController; private int _ignoreHitStack; private readonly LinkedList _timeSensitiveCallbacks; private float _lastInvokeTime; private readonly Dictionary _keyWatchers; protected bool _destroyed; [HideFromIl2Cpp] public IOwnerComp Owner { get; private set; } public bool RunHitTriggers { get { return _ignoreHitStack == 0; } set { if (!value) { if (_ignoreHitStack++ == 0) { GetContextController().BlacklistContext(); GetContextController().BlacklistContext(); } } else if (value && _ignoreHitStack > 0 && --_ignoreHitStack == 0) { GetContextController().WhitelistContext(); GetContextController().BlacklistContext(); } } } [HideFromIl2Cpp] public HashSet DebuffIDs { get; private set; } = DebuffGroup.DefaultGroupList; public CustomWeaponComponent(IntPtr value) : base(value) { ItemEquippable component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { PlayerAgent owner = ((Item)component).Owner; BulletWeaponSynced result2; BulletWeapon result3; SentryGunFirstPerson result4; if (((Object)(object)component).TryCastOut(out MeleeWeaponFirstPerson result)) { Weapon = new MeleeComp(result); Owner = new LocalOwnerComp(owner, component.MuzzleAlign); } else if (((Object)(object)component).TryCastOut(out result2)) { Weapon = new SyncedGunComp(result2); Owner = new SyncedOwnerComp(owner, component.MuzzleAlign); } else if (((Object)(object)component).TryCastOut(out result3)) { Weapon = new LocalGunComp(result3); Owner = new LocalOwnerComp(owner, component.MuzzleAlign); } else if (((Object)(object)component).TryCastOut(out result4)) { Weapon = new SentryHolderComp(result4); Owner = new LocalOwnerComp(owner, component.MuzzleAlign); } else { if (!((Object)(object)component).TryCastOut(out SentryGunInstance result5)) { throw new ArgumentException("Custom Weapon Component was added to a non-melee/gun/sentry."); } Weapon = new SentryGunComp(result5); Owner = new SentryOwnerComp(result5); } _propertyController = new PropertyController(Owner.Type, Weapon.Type); ShotComponent = new CustomShotComponent(this); SpreadController = new SpreadController(Owner.Type, Weapon.Type); _timeSensitiveCallbacks = new LinkedList(); _keyWatchers = new Dictionary(); ((Behaviour)this).enabled = false; return; } throw new ArgumentException("Custom Weapon Component was added to a non-melee/gun/sentry."); } [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } public virtual void OnUnWield() { SpreadController.Active = false; ResetKeyWatchers(); Invoke(StaticContext.Instance); } public virtual void OnWield() { SpreadController.Active = true; Invoke(StaticContext.Instance); } protected virtual void Update() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Invoke(StaticContext.Instance); if (_keyWatchers.Count <= 0) { return; } if ((int)FocusStateManager.CurrentState == 4) { KeyValuePair[] array = _keyWatchers.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; var (val2, flag2) = (KeyValuePair)(ref keyValuePair); if (flag2 != Input.GetKey(val2)) { _keyWatchers[val2] = !flag2; Invoke(new WeaponKeyContext(val2, !flag2)); } } } else { ResetKeyWatchers(); } } private void OnEnable() { } private void OnDisable() { } private void OnDestroy() { _destroyed = true; Clear(); } private void ResetKeyWatchers() { //IL_0031: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (_keyWatchers.Count == 0) { return; } KeyValuePair[] array = _keyWatchers.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; var (key, flag2) = (KeyValuePair)(ref keyValuePair); if (flag2) { _keyWatchers[key] = false; Invoke(new WeaponKeyContext(key, isDown: false)); } } } [HideFromIl2Cpp] public TContext Invoke(TContext context) where TContext : IWeaponContext { float time = Clock.Time; if (_lastInvokeTime != time) { _lastInvokeTime = time; LinkedListNode first = _timeSensitiveCallbacks.First; for (LinkedListNode linkedListNode = first; linkedListNode != null; linkedListNode = first) { first = linkedListNode.Next; if (linkedListNode.Value.CheckEnd()) { _timeSensitiveCallbacks.Remove(linkedListNode); } } } return _propertyController.Invoke(context); } [HideFromIl2Cpp] private TContext InvokeAll(TContext context) where TContext : IWeaponContext { return _propertyController.InvokeAll(context); } [HideFromIl2Cpp] public void Register(CustomWeaponData? data = null) { if (!((Behaviour)this).enabled && !_destroyed) { ((Behaviour)this).enabled = true; if (data != null || CustomDataManager.TryGetCustomData(Weapon, out data)) { _propertyController.Init(this, data.Properties.Clone()); DebuffIDs = data.DebuffIDs.IDs; DebuffIDs.Add(0u); InvokeAll(StaticContext.Instance); Invoke(new WeaponInitContext(Owner, Weapon)); TriggerManager.RunQueuedReceives(this); } } } public virtual void Clear() { if (_destroyed) { foreach (DelayedCallback timeSensitiveCallback in _timeSensitiveCallbacks) { timeSensitiveCallback.Cancel(); } _timeSensitiveCallbacks.Clear(); } Invoke(StaticContext.Instance); InvokeAll(StaticContext.Instance); _propertyController.Clear(); SpreadController.Reset(); DebuffIDs = DebuffGroup.DefaultGroupList; _keyWatchers.Clear(); ((Behaviour)this).enabled = false; } public void RefreshOwner() { ItemEquippable component = Weapon.Component; PlayerAgent owner = ((Item)component).Owner; if (!((Object)(object)owner == (Object)null) && !((Object)(object)owner.Owner == (Object)null)) { if (Owner.IsType(OwnerType.Local)) { Owner = new LocalOwnerComp(owner, component.MuzzleAlign); } else if (Owner.IsType(OwnerType.Sentry)) { Owner = new SentryOwnerComp(((SentryGunComp)Weapon).Value); } else { Owner = new SyncedOwnerComp(owner, component.MuzzleAlign); } ShotComponent.RefreshOwner(); } } [HideFromIl2Cpp] internal void ActivateNode(PropertyNode node) { _propertyController.SetActive(node, active: true); } [HideFromIl2Cpp] internal void DeactivateNode(PropertyNode node) { _propertyController.SetActive(node, active: false); } [HideFromIl2Cpp] public bool HasTrait() where T : Trait { return _propertyController.HasTrait(); } [HideFromIl2Cpp] public T? GetTrait() where T : Trait { return _propertyController.GetTrait(); } [HideFromIl2Cpp] public bool TryGetTrait([MaybeNullWhen(false)] out T trait) where T : Trait { return _propertyController.TryGetTrait(out trait); } [HideFromIl2Cpp] public bool TryGetProperty(uint id, [MaybeNullWhen(false)] out WeaponPropertyBase property) { return _propertyController.TryGetProperty(id, out property); } [HideFromIl2Cpp] internal ITriggerCallbackSync GetTriggerSync(ushort id) { return _propertyController.GetTriggerSync(id); } [HideFromIl2Cpp] public ContextController GetContextController() { return _propertyController.GetContextController(); } public bool HasTempProperties() { return _propertyController.HasTempProperties(); } public void RegisterKeyWatcher(KeyCode key) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _keyWatchers.TryAdd(key, value: false); } [HideFromIl2Cpp] public void StartDelayedCallback(DelayedCallback callback, bool checkEnd = false, bool refresh = true) { if (!_timeSensitiveCallbacks.Contains(callback)) { _timeSensitiveCallbacks.AddLast(callback); callback.Start(checkEnd, refresh); } else { callback.Start(checkEnd, refresh); } } } public class CustomWeaponData { public const float MaxFireRate = 512f; public const float MinShotDelay = 0.001953125f; public uint ArchetypeID { get; set; } public uint MeleeArchetypeID { get; set; } public bool IgnoreHeldSentry { get; set; } = true; public string Name { get; set; } = string.Empty; public DebuffGroup DebuffIDs { get; set; } = DebuffGroup.Default; public PropertyList Properties { get; set; } = new PropertyList(); } public sealed class CustomWeaponManager { private struct ListenerInfo { public bool hasSpawned; public PlayerAgent? owner; public readonly Func? addCWC; public readonly bool IsReady() { if (hasSpawned && (Object)(object)owner != (Object)null) { return IsValid(); } return false; } public readonly bool IsValid() { return addCWC != null; } public ListenerInfo(ItemEquippable item) { hasSpawned = false; owner = null; addCWC = null; if ((Object)(object)((Il2CppObjectBase)item).TryCast() != (Object)null) { addCWC = (GameObject go) => go.AddComponent(); hasSpawned = true; } else if ((Object)(object)((Il2CppObjectBase)item).TryCast() != (Object)null) { addCWC = (GameObject go) => go.AddComponent(); } else if ((Object)(object)((Il2CppObjectBase)item).TryCast() != (Object)null) { addCWC = (GameObject go) => go.AddComponent(); } } } public static readonly CustomWeaponManager Current = new CustomWeaponManager(); private static bool s_inLevel; private static bool s_assetsLoaded; private readonly Dictionary, ListenerInfo> _weaponListeners = new Dictionary, ListenerInfo>(); private readonly Dictionary _trackedSentries = new Dictionary(); private static ObjectWrapper TempWrapper => ObjectWrapper.SharedInstance; public static event Action? OnResetCWCs; [InvokeOnAssetLoad] private static void OnAssetsLoaded() { s_assetsLoaded = true; } [InvokeOnEnter] private static void OnEnterLevel() { s_inLevel = true; Current.AddAllEquippedItems(); } [InvokeOnCleanup(false)] private static void OnCleanup() { s_inLevel = false; ResetCWCs(activate: false); } [InvokeOnCheckpoint] private static void OnCheckpoint() { ResetCWCs(); } public static T InvokeOnGear(SNet_Player owner, T context) where T : IWeaponContext { PlayerBackpack val = default(PlayerBackpack); if (!PlayerBackpackManager.TryGetBackpack(owner, ref val)) { return context; } BackpackItem val2 = default(BackpackItem); if (val.TryGetBackpackItem((InventorySlot)1, ref val2)) { Item instance = val2.Instance; ((instance != null) ? ((Component)instance).GetComponent() : null)?.Invoke(context); } BackpackItem val3 = default(BackpackItem); if (val.TryGetBackpackItem((InventorySlot)2, ref val3)) { Item instance2 = val3.Instance; ((instance2 != null) ? ((Component)instance2).GetComponent() : null)?.Invoke(context); } BackpackItem val4 = default(BackpackItem); if (val.TryGetBackpackItem((InventorySlot)10, ref val4)) { Item instance3 = val4.Instance; ((instance3 != null) ? ((Component)instance3).GetComponent() : null)?.Invoke(context); } BackpackItem val5 = default(BackpackItem); if (val.TryGetBackpackItem((InventorySlot)3, ref val5)) { Item instance4 = val5.Instance; ((instance4 != null) ? ((Component)instance4).GetComponent() : null)?.Invoke(context); } if (owner.HasPlayerAgent && Current._trackedSentries.TryGetValue(((Il2CppObjectBase)owner.PlayerAgent).Pointer, out (SentryGunInstance, CustomGunComponent) value)) { value.Item2?.Invoke(context); } return context; } public static void ActivateSentry(SentryGunInstance sentry) { if (!s_inLevel) { return; } CustomGunComponent result = null; if (CustomDataManager.TryGetCustomGunData(((ItemEquippable)sentry).ArchetypeID, out CustomWeaponData data)) { if (!((Component)(object)sentry).TryGetComp(out result)) { result = ((Component)sentry).gameObject.AddComponent(); } result.Register(data); } if ((Object)(object)((Item)sentry).Owner != (Object)null) { Current._trackedSentries.Add(((Il2CppObjectBase)((Item)sentry).Owner).Pointer, (sentry, result)); } } public static void RemoveSentry(SentryGunInstance sentry) { if (s_inLevel) { Current._trackedSentries.Remove(((Il2CppObjectBase)((Item)sentry).Owner).Pointer); } } public static bool TryGetSentry(PlayerAgent player, [MaybeNullWhen(false)] out (SentryGunInstance sentry, CustomGunComponent? cgc) sentryInfo) { return Current._trackedSentries.TryGetValue(((Il2CppObjectBase)player).Pointer, out sentryInfo); } public static void AddSpawnedItem(ItemEquippable item) { if (s_assetsLoaded && (item.ArchetypeData != null || item.MeleeArchetypeData != null) && TryGetInfo(item, out var info)) { info.hasSpawned = true; Current._weaponListeners[TempWrapper] = info; ActivateItem(item); } } public static void RemoveSpawnedItem(ItemEquippable item) { Current._weaponListeners.Remove(TempWrapper.Set(item)); } public static void AddEquippedItem(PlayerAgent owner, ItemEquippable item) { if (TryGetInfo(item, out var info)) { info.owner = owner; Current._weaponListeners[TempWrapper] = info; ActivateItem(item); } } private static bool TryGetInfo(ItemEquippable item, out ListenerInfo info) { Dictionary, ListenerInfo> weaponListeners = Current._weaponListeners; if (!weaponListeners.TryGetValue(TempWrapper.Set(item), out info)) { weaponListeners.Add(new ObjectWrapper(TempWrapper), info = new ListenerInfo(item)); } return info.IsValid(); } private static void ActivateItem(ItemEquippable item) { if (!s_inLevel || !TryGetInfo(item, out var info) || !info.IsReady()) { return; } item.SetOwner(info.owner); if (CustomDataManager.TryGetCustomData(item, out CustomWeaponData data)) { if (!((Component)(object)item).TryGetComp(out var result)) { result = info.addCWC(((Component)item).gameObject); } else { result.RefreshOwner(); } result.Register(data); } } public static void ResetCWCs(bool activate = true) { if (!s_inLevel) { return; } ACAPIWrapper.ResetCrosshairSpread(); List> list = new List>(); Dictionary, ListenerInfo> weaponListeners = Current._weaponListeners; foreach (var (objectWrapper2, listenerInfo2) in weaponListeners) { if ((Object)(object)objectWrapper2.Object != (Object)null) { if (listenerInfo2.IsValid()) { ItemEquippable @object = objectWrapper2.Object; if (((Component)(object)@object).TryGetComp(out var result)) { result.Clear(); } if (activate) { ActivateItem(@object); } } } else { list.Add(objectWrapper2); } } foreach (ObjectWrapper item in list) { weaponListeners.Remove(item); } CustomWeaponManager.OnResetCWCs?.Invoke(activate); } private void AddAllEquippedItems() { //IL_0071: 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) Enumerator enumerator = PlayerBackpackManager.Current.m_backpacks.Values.GetEnumerator(); BackpackItem val3 = default(BackpackItem); while (enumerator.MoveNext()) { PlayerBackpack current = enumerator.Current; if (!current.Owner.HasPlayerAgent) { EWCLogger.Error("Tried to activate CWCs for " + current.Owner.NickName + " but they have no player agent!"); continue; } PlayerAgent val = ((Il2CppObjectBase)current.Owner.PlayerAgent).Cast(); InventorySlot[] validSlots = CustomDataManager.ValidSlots; foreach (InventorySlot val2 in validSlots) { if (current.TryGetBackpackItem(val2, ref val3)) { AddEquippedItem(val, ((Il2CppObjectBase)val3.Instance).Cast()); } } ItemEquippable wieldedItem = val.Inventory.WieldedItem; if ((Object)(object)wieldedItem != (Object)null && ((Component)(object)wieldedItem).TryGetComp(out var result)) { result.OnWield(); } } } static CustomWeaponManager() { CustomWeaponManager.OnResetCWCs = null; s_inLevel = false; s_assetsLoaded = false; } } } namespace EWC.CustomWeapon.WeaponContext { public sealed class ContextController { private interface IContextList { IContextList? ParentContextList { get; set; } bool Add(IWeaponProperty property); bool Remove(IWeaponProperty property); void Clear(); IContextList? CopyTo(ContextController manager); void Invoke(IWeaponContext context, List exceptions); } private sealed class ContextList : IContextList where TContext : IWeaponContext { private readonly List> _entries; public IContextList? ParentContextList { get; set; } public ContextList() { _entries = new List>(); } public bool Add(IWeaponProperty property) { if (!property.IsProperty(out IWeaponProperty contextedProperty)) { return false; } if (property is Trait && _entries.Any((IWeaponProperty containedProperty) => containedProperty.GetType() == contextedProperty.GetType())) { return false; } _entries.Add(contextedProperty); return true; } public bool Remove(IWeaponProperty property) { if (property.IsProperty(out IWeaponProperty castProperty)) { return _entries.Remove(castProperty); } return false; } public void Clear() { _entries.Clear(); } public IContextList? CopyTo(ContextController manager) { Type typeFromHandle = typeof(TContext); if (manager._contextLists.TryGetValue(typeFromHandle, out IContextList value)) { return value; } IContextList parentContextList = ParentContextList?.CopyTo(manager); ContextList contextList = new ContextList(); contextList.ParentContextList = parentContextList; contextList._entries.AddRange(_entries); manager._contextLists.Add(typeFromHandle, contextList); return contextList; } public void Invoke(TContext context, List exceptions) { for (int i = 0; i < _entries.Count; i++) { IWeaponProperty weaponProperty = _entries[i]; try { weaponProperty.Invoke(context); } catch (Exception item) { exceptions.Add(item); } } ParentContextList?.Invoke(context, exceptions); } void IContextList.Invoke(IWeaponContext context, List exceptions) { if (context is TContext) { TContext context2 = (TContext)context; Invoke(context2, exceptions); } } } private static readonly Type[] s_contextTypes; private static readonly Dictionary s_parentContextTypes; private static readonly Dictionary<(OwnerType, WeaponType), List> s_cachedContextTypes; private readonly Dictionary _contextLists = new Dictionary(); private readonly List _blacklist; private readonly HashSet _properties; public IReadOnlySet Properties => _properties; static ContextController() { s_parentContextTypes = new Dictionary(); s_cachedContextTypes = new Dictionary<(OwnerType, WeaponType), List>(); s_contextTypes = (from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsAssignableTo(typeof(IWeaponContext)) && (!t.IsAbstract || t.GetCustomAttribute() != null) select t).ToArray(); Type[] array = s_contextTypes; foreach (Type type in array) { Type type2 = type.GetCustomAttribute()?.Parent; if (type2 != null && type != type2) { s_parentContextTypes.Add(type, type2); } } } public ContextController(ContextController contextController) { foreach (IContextList value in contextController._contextLists.Values) { value.CopyTo(this); } _blacklist = new List(contextController._blacklist); _properties = new HashSet(contextController._properties); } public ContextController(OwnerType ownerType, WeaponType weaponType) { RegisterContexts(ownerType, weaponType); _blacklist = new List(); _properties = new HashSet(); } public void Register(WeaponPropertyBase property) { if (property == null) { throw new ArgumentNullException("property"); } if (!_properties.Add(property)) { return; } foreach (IContextList value in _contextLists.Values) { value.Add(property); } } public void Unregister(WeaponPropertyBase property) { if (!_properties.Remove(property)) { return; } foreach (IContextList value in _contextLists.Values) { value.Remove(property); } } public void Clear() { _properties.Clear(); foreach (IContextList value in _contextLists.Values) { value.Clear(); } } public void BlacklistContext() where T : IWeaponContext { _blacklist.Add(typeof(T)); } public void WhitelistContext() where T : IWeaponContext { _blacklist.Remove(typeof(T)); } public TContext Invoke(TContext context) where TContext : IWeaponContext { Type type = typeof(TContext); if (_blacklist.Count > 0 && _blacklist.Any((Type exclude) => type.IsAssignableTo(exclude))) { return context; } if (!_contextLists.TryGetValue(type, out IContextList value)) { return context; } List list = new List(); value.Invoke(context, list); foreach (Exception item in list) { EWCLogger.Error(item.Message); } return context; } private ContextList RegisterContext(IContextList? baseList = null) where TContext : IWeaponContext { ContextList contextList = new ContextList(); contextList.ParentContextList = baseList; _contextLists.TryAdd(typeof(TContext), contextList); return contextList; } private void RegisterContexts(OwnerType ownerType, WeaponType weaponType) { if (!s_cachedContextTypes.TryGetValue((ownerType, weaponType), out List value)) { value = new List(); Type[] array = s_contextTypes; foreach (Type type in array) { RequireTypeAttribute customAttribute = type.GetCustomAttribute(); if (customAttribute == null || customAttribute.IsValid(ownerType, weaponType)) { value.Add(type); } } } foreach (Type item in value) { IContextList value2 = (IContextList)Activator.CreateInstance(typeof(ContextList<>).MakeGenericType(item)); _contextLists.TryAdd(item, value2); } foreach (var (key, key2) in s_parentContextTypes) { if (_contextLists.TryGetValue(key, out IContextList value3) && _contextLists.TryGetValue(key2, out IContextList value4)) { value3.ParentContextList = value4; } } } } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public interface IWeaponContext { } public static class StaticContext where T : IWeaponContext, new() { public static readonly T Instance = new T(); } } namespace EWC.CustomWeapon.WeaponContext.Contexts { [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Any, WeaponType.SentryHolder | WeaponType.Gun)] public sealed class WeaponPostAmmoInitContext : IWeaponContext { public PlayerAmmoStorage AmmoStorage { get; set; } public InventorySlotAmmo SlotAmmo { get; set; } public WeaponPostAmmoInitContext(PlayerAmmoStorage ammoStorage, InventorySlotAmmo slotAmmo) { AmmoStorage = ammoStorage; SlotAmmo = slotAmmo; } } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Any, WeaponType.SentryHolder | WeaponType.Gun)] public sealed class WeaponPostAmmoPackContext : IWeaponContext { public PlayerAmmoStorage AmmoStorage { get; set; } public WeaponPostAmmoPackContext(PlayerAmmoStorage ammoStorage) { AmmoStorage = ammoStorage; } } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Any, WeaponType.SentryHolder | WeaponType.Gun)] public sealed class WeaponPreAmmoPackContext : IWeaponContext { public float AmmoAmount { get; set; } public WeaponPreAmmoPackContext(float ammoAmount) { AmmoAmount = ammoAmount; } } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPreAmmoUIContext : IWeaponContext { public int Clip { get; set; } public int Reserve { get; set; } public float TotalRel { get; set; } public bool ShowClip { get; set; } public bool ShowReserve { get; set; } public bool ShowRel { get; set; } public bool ShowInfinite { get; set; } public WeaponPreAmmoUIContext(int clip, int reserve, float totalRel, bool showClip, bool showReserve, bool showRel, bool showInfinite) { Clip = clip; Reserve = reserve; TotalRel = totalRel; ShowClip = showClip; ShowReserve = showReserve; ShowRel = showRel; ShowInfinite = showInfinite; } } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponUpdateContext : IWeaponContext { } public sealed class WeaponArmorContext : IWeaponContext { public float ArmorMulti { get; set; } public WeaponArmorContext(float armor) { ArmorMulti = armor; } } [RequireType(OwnerType.Managed, OwnerType.Local | OwnerType.Sentry, WeaponType.Any, WeaponType.Any)] public sealed class WeaponHitmarkerContext : IWeaponContext { public bool Result { get; set; } = true; public EnemyAgent Enemy { get; } public WeaponHitmarkerContext(EnemyAgent enemy) { Enemy = enemy; } } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponStealthUpdateContext : IWeaponContext { private float _output; public EnemyAgent Enemy { get; } public bool Detecting { get; } public float Output { get { return _output; } set { _output = Math.Max(_output, value); } } public WeaponStealthUpdateContext(EnemyAgent enemy, bool detecting, float output) { Enemy = enemy; Detecting = detecting; _output = output; } } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponFireCancelContext : IWeaponContext { public bool Allow { get; set; } public WeaponFireCancelContext() { Allow = true; } } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponFireCanceledContext : IWeaponContext { } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPreRayContext : IWeaponContext { public HitData Data { get; } public Vector3 Position { get; } public WeaponPreRayContext(HitData hitData, Vector3 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Data = hitData; Position = position; } } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPreStartFireContext : IWeaponContext { public bool Allow { get; set; } public WeaponPreStartFireContext() { Allow = true; } } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponShotCooldownContext : IWeaponContext { public float NextShotTime { get; } public WeaponShotCooldownContext(float nextShotTime) { NextShotTime = nextShotTime; } } public sealed class WeaponShotGroupInitContext : IWeaponContext { public ShotInfoMod GroupMod { get; set; } public WeaponShotGroupInitContext(ShotInfoMod mod) { GroupMod = mod; } } public sealed class WeaponShotInitContext : IWeaponContext { public ShotInfoMod Mod { get; set; } public WeaponShotInitContext(ShotInfoMod mod) { Mod = mod; } } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Melee, WeaponType.Any)] public sealed class WeaponChargeContext : IWeaponContext { public float Exponent { get; set; } = 3f; } public sealed class WeaponBackstabContext : WeaponStackModContext { public WeaponBackstabContext() : base(2f) { _stackMod.SetMin(1f); } } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.BulletWeapon, WeaponType.Any)] public sealed class WeaponChargeSpeedContext : WeaponStackModContext { public WeaponChargeSpeedContext() : base(1f) { } } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponFireRateContext : WeaponStackModContext { public WeaponFireRateContext(float fireRate) : base(fireRate) { } } [RequireType(OwnerType.Player, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponPlayerArmorContext : WeaponStackModContext { private readonly float _damage; public float Damage { get { if (!Immune) { if (!(_stackMod.Value > 0f)) { return float.PositiveInfinity; } return _damage / _stackMod.Value; } return 0f; } } public PlayerDamageType DamageType { get; } public bool Immune { get; set; } public WeaponPlayerArmorContext(float damage, PlayerDamageType damageType) : base(1f) { _damage = damage; DamageType = damageType; } } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponRecoilContext : WeaponStackModContext { public WeaponRecoilContext() : base(1f) { _stackMod.SetMin(float.MinValue); } } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponReloadContext : WeaponStackModContext { public WeaponReloadContext() : base(1f) { } } public abstract class WeaponStackModContext : IWeaponContext { protected readonly StackMod _stackMod; public float Value => _stackMod.Value; public WeaponStackModContext(float value) { _stackMod = new StackMod(value); } public void AddMod(float mod, StackType type) { _stackMod.AddMod(mod, type); } } public sealed class WeaponStatContext : IWeaponContext { private readonly StackMod _damageMod; private readonly StackMod _precisionMod; private readonly StackMod _staggerMod; private readonly HashSet _debuffIDs; public float Damage => CalcMod(StatType.Damage); public float Precision => CalcMod(StatType.Precision); public float Stagger => CalcMod(StatType.Stagger); public DamageType DamageType { get; } public bool BypassTumorCap { get; set; } public IDamageable Damageable { get; set; } public ShotInfo ShotInfo { get; } public WeaponStatContext(HitData data, HashSet debuffIDs) : this(data.damage, data.precisionMulti, data.staggerMulti, data.damageType, data.damageable, data.shotInfo, debuffIDs) { } public WeaponStatContext(float damage, float precision, float stagger, DamageType damageType, IDamageable damageable, ShotInfo shotInfo, HashSet debuffIDs) { _damageMod = new StackMod(damage); _precisionMod = new StackMod(precision); _staggerMod = new StackMod(stagger); _debuffIDs = debuffIDs; DamageType = damageType; Damageable = damageable; ShotInfo = shotInfo; BypassTumorCap = false; } public void AddMod(StatType type, float mod, StackType layer) { switch (type) { case StatType.Damage: _damageMod.AddMod(mod, layer); break; case StatType.Precision: _precisionMod.AddMod(mod, layer); break; case StatType.Stagger: _staggerMod.AddMod(mod, layer); break; } } private float CalcMod(StatType type) { StackMod stackMod; ShotStackMod shotStackMod; ShotStackMod shotStackMod2; switch (type) { case StatType.Damage: stackMod = _damageMod; shotStackMod = ShotInfo.Mod.Damage; shotStackMod2 = ShotInfo.GroupMod.Damage; break; case StatType.Precision: stackMod = _precisionMod; shotStackMod = ShotInfo.Mod.Precision; shotStackMod2 = ShotInfo.GroupMod.Precision; break; case StatType.Stagger: stackMod = _staggerMod; shotStackMod = ShotInfo.Mod.Stagger; shotStackMod2 = ShotInfo.GroupMod.Stagger; break; default: EWCLogger.Error($"Invalid stat type in StatContext! {type}"); return 1f; } StackValue stackValue = stackMod.StackValue; if (shotStackMod.HasMod(DamageType, Damageable)) { stackValue.Combine(shotStackMod.StackValue); } if (shotStackMod2.HasMod(DamageType, Damageable)) { stackValue.Combine(shotStackMod2.StackValue); } if (DebuffManager.TryGetShotModDebuff(Damageable, type, DamageType, _debuffIDs, out var mod)) { stackValue.Combine(mod); } return stackValue.Value * stackMod.BaseValue; } } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponClearContext : IWeaponContext { } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponCreatedContext : IWeaponContext { } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponDestroyedContext : IWeaponContext { } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponSetupContext : IWeaponContext { } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPreReloadContext : IWeaponContext { public bool Allow { get; set; } = true; } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponPreSprintContext : IWeaponContext { public bool AllowBurstCancel { get; set; } = true; public bool Allow { get; set; } = true; } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponPreSwapContext : IWeaponContext { private bool _allow = true; public bool AllowBurstCancel { get; set; } public bool Allow { get { if (_allow) { return AllowBurstCancel; } return false; } set { _allow = value; } } public WeaponPreSwapContext(bool allowNormal) { AllowBurstCancel = allowNormal; } } [RequireType(OwnerType.Unmanaged, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPostFireContextSync : IWeaponContext { } [RequireType(OwnerType.Unmanaged, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPreFireContextSync : IWeaponContext { } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponAimContext : WeaponTriggerContext { } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponAimEndContext : WeaponTriggerContext { } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Any, WeaponType.SentryHolder | WeaponType.Gun)] public sealed class WeaponAmmoContext : WeaponTriggerContext { public int Clip { get; } public int ClipMax { get; } public float ClipRel { get; } public WeaponAmmoContext(int clip, int clipMax) { Clip = clip; ClipMax = clipMax; ClipRel = (float)clip / (float)clipMax; } } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponChargeEndContext : WeaponTriggerContext { public float Charge { get; } public WeaponChargeEndContext(float charge) { Charge = charge; } } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponChargeStartContext : WeaponTriggerContext { } public sealed class WeaponCrouchContext : WeaponTriggerContext { } public sealed class WeaponCrouchEndContext : WeaponTriggerContext { } public sealed class WeaponDamageTakenContext : WeaponTriggerContext { public float Damage { get; } public PlayerDamageType DamageType { get; } public WeaponDamageTakenContext(float damage, PlayerDamageType damageType) { Damage = damage; DamageType = damageType; } } public abstract class WeaponDamageTypeContext : WeaponTriggerContext { public DamageType DamageType { get; protected set; } public ShotInfo.Const ShotInfo { get; } public WeaponDamageTypeContext(DamageType flag, ShotInfo.Const info) { DamageType = flag; ShotInfo = info; } } public sealed class WeaponHealthContext : WeaponTriggerContext { public float Health { get; } public float HealthMax { get; } public WeaponHealthContext(Dam_PlayerDamageBase damBase) { Health = ((Dam_SyncedDamageBase)damBase).Health; HealthMax = ((Dam_SyncedDamageBase)damBase).HealthMax; } } public sealed class WeaponHitContext : WeaponHitContextBase { public WeaponHitContext(HitData data) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_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_0021: Unknown result type (might be due to invalid IL or missing references) GameObject? gameObject = data.gameObject; Vector3 hitPos = data.hitPos; Vector3 normalized = ((Vector3)(ref data.fireDir)).normalized; RaycastHit rayHit = data.RayHit; base..ctor(gameObject, hitPos, normalized, ((RaycastHit)(ref rayHit)).normal, data.falloff, data.shotInfo, data.damageType); } } public sealed class WeaponHitDamageableContext : WeaponHitDamageableContextBase { public float Damage { get; } public float DamageClamped { get; } public WeaponHitDamageableContext(float damage, WeaponPreHitDamageableContext context) : base(context) { Damage = damage; Dam_SyncedDamageBase val = ((Il2CppObjectBase)base.Damageable.GetBaseDamagable()).TryCast(); if ((Object)(object)val != (Object)null) { DamageClamped = Math.Min(Damage, val.HealthMax); } else { DamageClamped = Math.Min(Damage, DamageableUtil.LockHealth); } } public WeaponHitDamageableContext(HitData data) : base(data, 1f, 1f) { Damage = data.damage * base.Falloff * data.shotInfo.ExternalDamageMod; Dam_SyncedDamageBase val = ((Il2CppObjectBase)base.Damageable.GetBaseDamagable()).TryCast(); if ((Object)(object)val != (Object)null) { DamageClamped = Math.Min(Damage, val.HealthMax); } else { DamageClamped = Math.Min(Damage, DamageableUtil.LockHealth); } } public WeaponHitDamageableContext(HitData data, bool bypassTumor, float backstab, float origBackstab, Dam_EnemyDamageLimb limb) : base(data, backstab, origBackstab) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Invalid comparison between Unknown and I4 Damage = data.damage * base.Falloff * data.shotInfo.ExternalDamageMod; Damage = limb.ApplyWeakspotAndArmorModifiers(Damage, data.precisionMulti); EnemyLimbPatches.CachedBypassTumorCap = bypassTumor; Damage *= base.Backstab; if (!bypassTumor && (int)limb.DestructionType == 1) { Damage = Math.Min(Damage, limb.m_healthMax); } DamageClamped = Math.Min(Damage, ((Dam_SyncedDamageBase)limb.m_base).HealthMax); } } public sealed class WeaponInitContext : WeaponTriggerContext { public readonly IWeaponComp Weapon; public readonly IOwnerComp Owner; public WeaponInitContext(IOwnerComp owner, IWeaponComp weapon) { Weapon = weapon; Owner = owner; } } public sealed class WeaponJumpContext : WeaponTriggerContext { } public sealed class WeaponJumpEndContext : WeaponTriggerContext { } [RequireType(OwnerType.Local, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponKeyContext : WeaponTriggerContext { public KeyCode Key { get; } public bool IsDown { get; } public WeaponKeyContext(KeyCode key, bool isDown) { //IL_0007: 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) Key = key; IsDown = isDown; } } public sealed class WeaponPostFireContext : WeaponTriggerContext { } public sealed class WeaponPostKillContext : WeaponHitTrackerContextBase { public WeaponPostKillContext(WeaponHitDamageableContext hitContext, float lastTime, bool lastHit) : base(hitContext, lastTime, lastHit) { } } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Melee, WeaponType.Any)] internal class WeaponPostPushContext : WeaponTriggerContext { } [RequireType(OwnerType.Managed | OwnerType.Player, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPostReloadContext : WeaponTriggerContext { } public sealed class WeaponPostStaggerContext : WeaponHitTrackerContextBase { public bool LimbBreak { get; } public WeaponPostStaggerContext(WeaponHitDamageableContext hitContext, float lastTime, bool lastHit, bool limbBreak) : base(hitContext, lastTime, lastHit) { LimbBreak = limbBreak; } } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPostStartFireContext : WeaponTriggerContext { } [RequireType(OwnerType.Managed, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponPostStopFiringContext : WeaponTriggerContext { } public sealed class WeaponPreFireContext : WeaponTriggerContext { } public sealed class WeaponPreHitDamageableContext : WeaponHitDamageableContextBase { public WeaponPreHitDamageableContext(IDamageable damageable, Vector3 position, Vector3 direction, Vector3 normal, float backstab, float origBackstab, float falloff, ShotInfo.Const info, DamageType flag) : base(damageable, position, direction, normal, backstab, origBackstab, falloff, info, flag) { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) public WeaponPreHitDamageableContext(HitData data, float backstab, float origBackstab) : base(data, backstab, origBackstab) { } } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Melee, WeaponType.Any)] internal class WeaponPrePushContext : WeaponTriggerContext { } [RequireType(OwnerType.Any, OwnerType.Any, WeaponType.Melee, WeaponType.Any)] internal class WeaponPushHitContext : WeaponTriggerContext, IPositionContext { public Vector3 Position { get; } public Vector3 Direction { get; } public Vector3 Normal { get; } public float Falloff => 1f; public ShotInfo.Const ShotInfo { get; } public WeaponPushHitContext(HitData data) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0020: 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_0028: 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) Position = data.hitPos; Direction = data.fireDir; RaycastHit rayHit = data.RayHit; Normal = ((RaycastHit)(ref rayHit)).normal; ShotInfo = data.shotInfo; } } public class WeaponReferenceContext : WeaponTriggerContext { public float Mod { get; } public uint ID { get; } public uint CallbackID { get; } public WeaponReferenceContext(uint id, uint callbackID, float mod = 1f) { Mod = mod; ID = id; CallbackID = callbackID; } } public sealed class WeaponReferencePosContext : WeaponReferenceContext, IPositionContext { public Vector3 Position { get; } public Vector3 Direction { get; } public Vector3 Normal { get; } public float Falloff { get; } public ShotInfo.Const ShotInfo { get; } public WeaponReferencePosContext(uint id, uint callbackID, Vector3 position, Vector3 direction, Vector3 normal, float falloff, ShotInfo.Const shotInfo, float mod = 1f) : base(id, callbackID, mod) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) Position = position; Direction = direction; Normal = normal; Falloff = falloff; ShotInfo = shotInfo; } } [RequireType(OwnerType.Managed | OwnerType.Player, OwnerType.Any, WeaponType.Gun, WeaponType.Any)] public sealed class WeaponReloadStartContext : WeaponTriggerContext { } public sealed class WeaponShotEndContext : WeaponDamageTypeContext { public ShotInfo.Const? OldInfo { get; } public WeaponShotEndContext(DamageType baseType, ShotInfo.Const info, ShotInfo.Const? oldInfo) : base(baseType, info) { OldInfo = oldInfo; } public float DiffHits() { return base.ShotInfo.Hits - (OldInfo?.Hits ?? 0); } public float DiffTypeHits(DamageType[] damageTypes, DamageType blacklistType) { return base.ShotInfo.TypeHits(damageTypes, blacklistType) - (OldInfo?.TypeHits(damageTypes, blacklistType) ?? 0); } } public sealed class WeaponSprintContext : WeaponTriggerContext { } public sealed class WeaponSprintEndContext : WeaponTriggerContext { } [ParentContext(typeof(WeaponTriggerContext))] [AllowAbstract] public abstract class WeaponTriggerContext : IWeaponContext { public WeaponTriggerContext() { } } public sealed class WeaponUnWieldContext : WeaponTriggerContext { } [RequireType(OwnerType.Managed | OwnerType.Player, OwnerType.Any, WeaponType.Any, WeaponType.Any)] public sealed class WeaponWieldContext : WeaponTriggerContext { } } namespace EWC.CustomWeapon.WeaponContext.Contexts.Base { internal interface IPositionContext { Vector3 Position { get; } Vector3 Direction { get; } Vector3 Normal { get; } float Falloff { get; } ShotInfo.Const ShotInfo { get; } } public abstract class WeaponHitContextBase : WeaponDamageTypeContext, IPositionContext { private GameObject? _gameObject; public Vector3 Position { get; } public Vector3 Direction { get; } public Vector3 Normal { get; } public float Falloff { get; } public GameObject GameObject => _gameObject ?? (_gameObject = SetGameObject()); protected virtual GameObject SetGameObject() { throw new NotImplementedException(); } public WeaponHitContextBase(GameObject gameObject, Vector3 position, Vector3 direction, Vector3 normal, float falloff, ShotInfo.Const info, DamageType flag) : base(flag, info) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0028: 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) _gameObject = gameObject; Position = position; Direction = ((Vector3)(ref direction)).normalized; Normal = ((Vector3)(ref normal)).normalized; Falloff = falloff; } public WeaponHitContextBase(Vector3 position, Vector3 direction, Vector3 normal, float falloff, ShotInfo.Const info, DamageType flag) : base(flag, info) { //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_0014: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Position = position; Direction = ((Vector3)(ref direction)).normalized; Normal = ((Vector3)(ref normal)).normalized; Falloff = falloff; } } public abstract class WeaponHitDamageableContextBase : WeaponHitContextBase { public Vector3 LocalPosition { get; } public IDamageable Damageable { get; } public float Backstab { get; } public float OrigBackstab { get; } protected override GameObject SetGameObject() { return ((Component)((Il2CppObjectBase)Damageable).Cast()).gameObject; } public WeaponHitDamageableContextBase(IDamageable damageable, Vector3 position, Vector3 direction, Vector3 normal, float backstab, float origBackstab, float falloff, ShotInfo.Const info, DamageType flag) : base(position, direction, normal, falloff, info, flag.WithSubTypes(damageable)) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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_002e: 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_0063: 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_006b: 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_007f: 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) Damageable = damageable ?? throw new ArgumentNullException("damageable"); Agent baseAgent = damageable.GetBaseAgent(); Vector3? val = ((baseAgent != null) ? new Vector3?(baseAgent.Position) : null); LocalPosition = (Vector3)(((??)(val.HasValue ? new Vector3?(position - val.GetValueOrDefault()) : null)) ?? Vector3.zero); Backstab = backstab; OrigBackstab = origBackstab; } public WeaponHitDamageableContextBase(HitData data, float backstab, float origBackstab) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_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_0021: Unknown result type (might be due to invalid IL or missing references) IDamageable? damageable = data.damageable; Vector3 hitPos = data.hitPos; Vector3 normalized = ((Vector3)(ref data.fireDir)).normalized; RaycastHit rayHit = data.RayHit; this..ctor(damageable, hitPos, normalized, ((RaycastHit)(ref rayHit)).normal, backstab, origBackstab, data.falloff, data.shotInfo, data.damageType); } public WeaponHitDamageableContextBase(WeaponHitDamageableContextBase context) : this(context.Damageable, context.Position, context.Direction, context.Normal, context.Backstab, context.OrigBackstab, context.Falloff, context.ShotInfo, context.DamageType) { }//IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) } public abstract class WeaponHitTrackerContextBase : WeaponHitDamageableContextBase { public EnemyAgent Enemy { get; } public float Delay { get; } public bool DidLastHit { get; } public WeaponHitTrackerContextBase(WeaponHitDamageableContext hitContext, float lastTime, bool didKill) : base(hitContext.Damageable, hitContext.LocalPosition + hitContext.Damageable.GetBaseAgent().Position, hitContext.Direction, hitContext.Normal, hitContext.Backstab, hitContext.OrigBackstab, hitContext.Falloff, hitContext.ShotInfo, hitContext.DamageType) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Enemy = ((Il2CppObjectBase)hitContext.Damageable.GetBaseAgent()).Cast(); Delay = Clock.Time - lastTime; DidLastHit = didKill; } } } namespace EWC.CustomWeapon.WeaponContext.Attributes { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)] internal sealed class AllowAbstractAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class, Inherited = true)] internal sealed class ParentContextAttribute : Attribute { private Type _parent; public Type Parent { get { return _parent; } set { _parent = value; ValidateType(); } } public ParentContextAttribute(Type contextType) { _parent = contextType; ValidateType(); } private void ValidateType() { if (!typeof(IWeaponContext).IsAssignableFrom(_parent)) { throw new ArgumentException("Parent Context attribute requires an IWeaponContext type."); } } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = true)] internal sealed class RequireTypeAttribute : Attribute { public OwnerType RequiredOwnerType { get; set; } public OwnerType ValidOwnerType { get; set; } public WeaponType RequiredWeaponType { get; set; } public WeaponType ValidWeaponType { get; set; } public RequireTypeAttribute(OwnerType requiredOwnerType = OwnerType.Any, OwnerType validOwnerType = OwnerType.Any, WeaponType requiredWeaponType = WeaponType.Any, WeaponType validWeaponType = WeaponType.Any) { RequiredOwnerType = requiredOwnerType; ValidOwnerType = validOwnerType; RequiredWeaponType = requiredWeaponType; ValidWeaponType = validWeaponType; } public bool IsValid(OwnerType ownerType, WeaponType weaponType) { if (ownerType.HasFlag(RequiredOwnerType) && ownerType.HasAnyFlag(ValidOwnerType) && weaponType.HasFlag(RequiredWeaponType)) { return weaponType.HasAnyFlag(ValidWeaponType); } return false; } } } namespace EWC.CustomWeapon.UI { internal class UIHandler { } } namespace EWC.CustomWeapon.Structs { public struct pCWC { private pReplicator pRep; public OwnerType ownerType; public InventorySlot slot; public bool IsValid => ((pReplicator)(ref pRep)).IsValid(); public readonly ushort ReplicatorKey => pRep.keyPlusOne; public void Set(CustomWeaponComponent cwc) { //IL_0018: 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) ownerType = cwc.Owner.Type; slot = cwc.Weapon.InventorySlot; if (ownerType.HasFlag(OwnerType.Sentry)) { ((pReplicator)(ref pRep)).SetID(((SentryOwnerComp)cwc.Owner).Value.Replicator); } else { pRep.keyPlusOne = (ushort)(((Agent)cwc.Owner.Player).m_replicator.Key + 1); } } private bool TryGetSupplier([MaybeNullWhen(false)] out IReplicatorSupplier supplier) { IReplicator val = default(IReplicator); if (!((pReplicator)(ref pRep)).TryGetID(ref val) || val == null) { supplier = null; return false; } supplier = val.ReplicatorSupplier; return supplier != null; } public bool TryGet([MaybeNullWhen(false)] out CustomWeaponComponent comp) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!TryGetSupplier(out IReplicatorSupplier supplier)) { comp = null; return false; } if (ownerType.HasFlag(OwnerType.Sentry)) { comp = ((Component)((Il2CppObjectBase)supplier).Cast()).GetComponent(); return (Object)(object)comp != (Object)null; } PlayerBackpack val = default(PlayerBackpack); BackpackItem val2 = default(BackpackItem); if (!PlayerBackpackManager.TryGetBackpack(((Il2CppObjectBase)supplier).Cast().m_agent.Owner, ref val) || !val.TryGetBackpackItem(slot, ref val2)) { comp = null; return false; } comp = ((Component)val2.Instance).GetComponent(); return (Object)(object)comp != (Object)null; } public bool TryGetSentry([MaybeNullWhen(false)] out SentryGunInstance comp) { if (!ownerType.HasFlag(OwnerType.Sentry) || !TryGetSupplier(out IReplicatorSupplier supplier)) { comp = null; return false; } comp = ((Il2CppObjectBase)supplier).Cast(); return true; } public bool TryGetPlayer([MaybeNullWhen(false)] out PlayerAgent comp) { if (!ownerType.HasFlag(OwnerType.Player) || !TryGetSupplier(out IReplicatorSupplier supplier)) { comp = null; return false; } comp = ((Il2CppObjectBase)supplier).Cast().m_agent; return true; } public bool TryGetSource([MaybeNullWhen(false)] out PlayerAgent comp) { if (!TryGetSupplier(out IReplicatorSupplier supplier)) { comp = null; return false; } if (ownerType.HasFlag(OwnerType.Player)) { comp = ((Il2CppObjectBase)supplier).Cast().m_agent; return true; } comp = ((Item)((Il2CppObjectBase)supplier).Cast()).Owner; return true; } } public class StackMod { protected StackValue _stackValue = new StackValue(); private float _min; public float Value => Math.Max(_min, BaseValue * _stackValue.Value); public StackValue StackValue => _stackValue; public float BaseValue { get; private set; } public StackMod(float value, float min = 0f) { Reset(value, min); } public StackMod(StackMod mod) { Copy(mod); } public virtual void Copy(StackMod mod) { BaseValue = mod.BaseValue; _min = mod._min; _stackValue = mod._stackValue; } public void Reset(float value, float min = 0f) { BaseValue = value; _min = min; _stackValue.Reset(); } public void SetMin(float min) { _min = min; } public void AddMod(float mod, StackType type) { _stackValue.Add(mod, type); } } public struct StackValue { private float _value; private bool _isDirty; public bool UseOverride; public float OverrideMod; public float AddMod; public float MultMod; public float MaxMod; private bool _hasMax; public float MinMod; private bool _hasMin; public float Value { get { if (!_isDirty) { return _value; } _value = (UseOverride ? OverrideMod : (AddMod * MultMod * MaxMod * MinMod)); _isDirty = false; return _value; } } public StackValue() { UseOverride = false; OverrideMod = 1f; AddMod = 1f; MultMod = 1f; MaxMod = 1f; _hasMax = false; MinMod = 1f; _hasMin = false; _value = 1f; _isDirty = false; } public StackValue(StackValue other) { UseOverride = other.UseOverride; OverrideMod = other.OverrideMod; AddMod = other.AddMod; MultMod = other.MultMod; MaxMod = other.MaxMod; _hasMax = other._hasMax; MinMod = other.MinMod; _hasMin = other._hasMin; _value = other._value; _isDirty = other._isDirty; } public void Add(float mod, StackType type) { switch (type) { case StackType.Override: OverrideMod = mod; UseOverride = true; break; case StackType.Add: AddMod += mod - 1f; break; case StackType.Multiply: MultMod *= mod; break; case StackType.Max: MaxMod = Math.Max(GetMax(), mod); _hasMax = true; break; case StackType.Min: MinMod = Math.Min(GetMin(), mod); _hasMin = true; break; } _isDirty = true; } public void Reset(StackType type) { switch (type) { case StackType.Override: UseOverride = false; OverrideMod = 1f; break; case StackType.Add: AddMod = 1f; break; case StackType.Multiply: MultMod = 1f; break; case StackType.Max: MaxMod = 1f; _hasMax = false; break; case StackType.Min: MinMod = 1f; _hasMin = false; break; } _isDirty = true; } public void Reset() { UseOverride = false; OverrideMod = 1f; AddMod = 1f; MultMod = 1f; MaxMod = 1f; _hasMax = false; MinMod = 1f; _hasMin = false; _value = 1f; _isDirty = false; } public void Combine(StackValue other) { AddMod += other.AddMod - 1f; MultMod *= other.MultMod; MaxMod = ((_hasMax || other._hasMax) ? Math.Max(GetMax(), other.GetMax()) : 1f); _hasMax |= other._hasMax; MinMod = ((_hasMin || other._hasMin) ? Math.Min(GetMin(), other.GetMin()) : 1f); _hasMin |= other._hasMin; OverrideMod = (UseOverride ? OverrideMod : other.OverrideMod); UseOverride |= other.UseOverride; _isDirty = true; } private readonly float GetMin() { if (!_hasMin) { return float.MaxValue; } return MinMod; } private readonly float GetMax() { if (!_hasMax) { return float.MinValue; } return MaxMod; } } } namespace EWC.CustomWeapon.Properties { public sealed class DebuffGroup { public static readonly DebuffGroup Default = new DebuffGroup(); public static HashSet DefaultGroupList => DebuffManager.DefaultGroupSet; public HashSet IDs { get; set; } = DefaultGroupList; } public interface IPropertyHolder : IWeaponProperty { PropertyList Properties { get; } PropertyNode? Node { get; set; } } public interface IWeaponProperty { CustomWeaponComponent CWC { get; set; } int RefCount { get; set; } bool ShouldRegister(Type contextType) { return true; } WeaponPropertyBase Clone(); void Serialize(Utf8JsonWriter writer); void DeserializeProperty(string property, ref Utf8JsonReader reader); } public interface IWeaponProperty : IWeaponProperty where TContext : IWeaponContext { void Invoke(TContext context); } public interface ISyncProperty : IWeaponProperty { ushort SyncPropertyID { get; set; } } internal sealed class PropertyController { private PropertyNode _root; private bool _hasTempProperties; private readonly ContextController _contextController; private readonly List _properties = new List(); private readonly LinkedList _overrideStack = new LinkedList(); private readonly Dictionary _activeTraits = new Dictionary(); private readonly Dictionary _idToProperty = new Dictionary(); private readonly List _syncList = new List(1); private static readonly List s_subtreePropCache = new List(); private static readonly HashSet s_subtreeKeepCache = new HashSet(); public PropertyController(OwnerType ownerType, WeaponType weaponType) { _contextController = new ContextController(ownerType, weaponType); } public TContext Invoke(TContext context) where TContext : IWeaponContext { return _contextController.Invoke(context); } public TContext InvokeAll(TContext context) where TContext : IWeaponContext { foreach (WeaponPropertyBase property in _properties) { if (((IWeaponProperty)property).IsProperty(out IWeaponProperty castProperty)) { castProperty.Invoke(context); } } return context; } public void Init(CustomWeaponComponent cwc, PropertyList? baseList) { if (baseList == null) { return; } _root = CreateTree(cwc, baseList); ReplaceReferences(_root.List); foreach (WeaponPropertyBase property in _properties) { property.OnPropertiesSetup(); } SetActive(_root, active: true); } private PropertyNode CreateTree(CustomWeaponComponent cwc, PropertyList list, PropertyNode? parent = null, IPropertyHolder? holder = null) { PropertyNode propertyNode = new PropertyNode(list, parent, holder); list.SetCWC(cwc); for (int num = list.Count - 1; num >= 0; num--) { WeaponPropertyBase weaponPropertyBase = list[num]; if (weaponPropertyBase is ITriggerCallbackSync triggerCallbackSync) { triggerCallbackSync.SyncID = (ushort)_syncList.Count; _syncList.Add(triggerCallbackSync); } if (!weaponPropertyBase.ValidProperty()) { list.Values.RemoveAt(num); } else { if (weaponPropertyBase.ID != 0 && !_idToProperty.TryAdd(weaponPropertyBase.ID, weaponPropertyBase)) { EWCLogger.Warning("Duplicate property ID detected: " + weaponPropertyBase.ID); } if (!(weaponPropertyBase is ReferenceProperty)) { _properties.Add(weaponPropertyBase); } if (weaponPropertyBase is IPropertyHolder propertyHolder && !propertyHolder.Properties.Empty) { _hasTempProperties = _hasTempProperties || weaponPropertyBase is TempProperties; CreateTree(cwc, propertyHolder.Properties, propertyNode, propertyHolder); } } } return propertyNode; } private void ReplaceReferences(PropertyList list) { for (int num = list.Count - 1; num >= 0; num--) { if (list[num] is IPropertyHolder propertyHolder) { ReplaceReferences(propertyHolder.Properties); } else if (list[num] is ReferenceProperty referenceProperty) { if (!_idToProperty.TryGetValue(referenceProperty.ReferenceID, out WeaponPropertyBase value)) { list.Values.RemoveAt(num); } else { list.Values[num] = value; } } } } public void Clear() { _properties.Clear(); _contextController.Clear(); _overrideStack.Clear(); _activeTraits.Clear(); _idToProperty.Clear(); _syncList.Clear(); } public ContextController GetContextController() { return _contextController; } public bool HasTempProperties() { return _hasTempProperties; } public bool HasTrait() where T : Trait { return _activeTraits.ContainsKey(typeof(T)); } public T? GetTrait() where T : Trait { if (!_activeTraits.TryGetValueAs(typeof(T), out var valueAs)) { return null; } return valueAs; } public bool TryGetTrait([MaybeNullWhen(false)] out T trait) where T : Trait { return _activeTraits.TryGetValueAs(typeof(T), out trait); } public bool TryGetProperty(uint id, [MaybeNullWhen(false)] out WeaponPropertyBase property) { return _idToProperty.TryGetValue(id, out property); } internal ITriggerCallbackSync GetTriggerSync(ushort id) { if (_syncList.Count <= id) { EWCLogger.Error("Synced property with ID " + id + " was requested but doesn't exist. Filling with blank properties."); while (_syncList.Count <= id) { _syncList.Add(TriggerCallbackSyncDummy.Instance); } } return _syncList[id]; } public void SetActive(PropertyNode node, bool active) { if (node.Active != active) { node.Active = active; if (active) { Activate(node); } else { Deactivate(node); } } } private void Activate(PropertyNode node) { if (node.Override) { if (node.Enabled) { UpdateRoot(node); } else { _overrideStack.AddBefore(_overrideStack.Last, node); } } else { if (!node.Enabled) { return; } foreach (WeaponPropertyBase item in node.List) { if (item.RefCount++ == 0 && (!(item is Trait value) || _activeTraits.TryAdd(item.GetType(), value))) { if (((IWeaponProperty)item).IsProperty(out IWeaponProperty castProperty)) { castProperty.Invoke(StaticContext.Instance); } _contextController.Register(item); } } } } private void Deactivate(PropertyNode node) { if (node.Override) { _overrideStack.Remove(node); if (node.Enabled) { UpdateRoot(); } } else { if (!node.Enabled) { return; } foreach (WeaponPropertyBase item in node.List) { if (--item.RefCount != 0) { continue; } Type type = item.GetType(); if (item is Trait trait) { if (!_activeTraits.TryGetValue(type, out Trait value) || value != trait) { continue; } _activeTraits.Remove(type); } if (((IWeaponProperty)item).IsProperty(out IWeaponProperty castProperty)) { castProperty.Invoke(StaticContext.Instance); } _contextController.Unregister(item); } } } private void UpdateRoot(PropertyNode? node = null) { PropertyNode node2 = node; if (node2 != null) { _overrideStack.AddLast(node2); } else { node2 = _overrideStack.Last?.Value; } foreach (WeaponPropertyBase property in _contextController.Properties) { property.RefCount = 0; } if (node2 == null) { node2 = _root; } SetSubtree(_root); foreach (WeaponPropertyBase property2 in _contextController.Properties) { IWeaponProperty castProperty; if (property2.RefCount != 0) { s_subtreeKeepCache.Add(property2); } else if (((IWeaponProperty)property2).IsProperty(out castProperty)) { castProperty.Invoke(StaticContext.Instance); } } _contextController.Clear(); _activeTraits.Clear(); foreach (WeaponPropertyBase item in s_subtreePropCache) { if (!s_subtreeKeepCache.Contains(item) && ((IWeaponProperty)item).IsProperty(out IWeaponProperty castProperty2)) { castProperty2.Invoke(StaticContext.Instance); } if (item is Trait value) { _activeTraits.TryAdd(item.GetType(), value); } _contextController.Register(item); } s_subtreePropCache.Clear(); s_subtreeKeepCache.Clear(); void SetSubtree(PropertyNode curr, bool enabled = false) { if (curr == node2) { if (curr.Owner != null && curr.Owner.RefCount++ == 0) { s_subtreePropCache.Add((WeaponPropertyBase)curr.Owner); } enabled = true; } else if (curr.Owner != null && curr.Owner.RefCount > 0) { return; } curr.Enabled = enabled; if (enabled && curr.Active) { foreach (WeaponPropertyBase item2 in curr.List) { if (item2.RefCount == 0) { s_subtreePropCache.Add(item2); if (item2 is IPropertyHolder propertyHolder && propertyHolder.Node != null) { SetSubtree(propertyHolder.Node, enabled); } } item2.RefCount++; } } foreach (PropertyNode child in curr.Children) { SetSubtree(child, enabled); } } } } public static class PropertyExtensions { public static bool IsProperty(this IWeaponProperty property) where TContext : IWeaponContext { if (property.ShouldRegister(typeof(TContext))) { return property is IWeaponProperty; } return false; } public static bool IsProperty(this IWeaponProperty property, [MaybeNullWhen(false)] out IWeaponProperty castProperty) where TContext : IWeaponContext { if (property.ShouldRegister(typeof(TContext)) && property is IWeaponProperty weaponProperty) { castProperty = weaponProperty; return true; } castProperty = null; return false; } } public sealed class PropertyList { private static readonly List s_emptyList = new List(0); public readonly List Values; private bool _setup; public int Count => Values.Count; public bool Empty => Values.Count == 0; public WeaponPropertyBase this[int index] => Values[index]; public PropertyList() { Values = s_emptyList; } public PropertyList(List properties) { Values = properties; } public IEnumerator GetEnumerator() { return Values.GetEnumerator(); } public void SetCWC(CustomWeaponComponent cwc) { if (_setup) { EWCLogger.Error("Property list " + string.Join(", ", Values) + " was setup twice! This shouldn't happen!"); return; } _setup = true; foreach (WeaponPropertyBase value in Values) { value.CWC = cwc; } } public PropertyList Clone() { return new PropertyList(Values.ConvertAll((WeaponPropertyBase property) => property.Clone())); } } public sealed class PropertyNode { public readonly PropertyList List; public readonly List Children; public readonly IPropertyHolder? Owner; public bool Active { get; set; } public bool Enabled { get; set; } = true; public bool Override { get; set; } public PropertyNode(PropertyList list, PropertyNode? parent, IPropertyHolder? owner) { List = list; Children = new List(); Owner = owner; if (Owner != null) { Owner.Node = this; } parent?.Children.Add(this); } } public sealed class ReferenceProperty : WeaponPropertyBase { public uint ReferenceID { get; private set; } public ReferenceProperty() { } public ReferenceProperty(uint id) { ReferenceID = id; } public ReferenceProperty(string id) { ReferenceID = WeaponPropertyBase.StringIDToInt(id); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("ID", ReferenceID); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == "referenceid" || property == "id") { if (reader.TokenType == JsonTokenType.String) { ReferenceID = WeaponPropertyBase.StringIDToInt(reader.GetString()); } else { ReferenceID = reader.GetUInt32(); } } } } public abstract class WeaponPropertyBase : IWeaponProperty { private CustomWeaponComponent _cwc; private static readonly Dictionary s_stringToIDDict = new Dictionary(); private static uint s_nextID = uint.MaxValue; public CustomWeaponComponent CWC { get { return _cwc; } set { _cwc = value; CGC = (_cwc.Weapon.IsType(WeaponType.Gun) ? ((Il2CppObjectBase)_cwc).Cast() : null); } } public CustomGunComponent CGC { get; private set; } public uint ID { get; private set; } public int RefCount { get; set; } protected virtual OwnerType RequiredOwnerType => OwnerType.Any; protected virtual OwnerType ValidOwnerType => OwnerType.Any; protected virtual WeaponType RequiredWeaponType => WeaponType.Any; protected virtual WeaponType ValidWeaponType => WeaponType.Any; public virtual bool ShouldRegister(Type contextType) { return true; } public virtual bool ValidProperty() { if (CWC.Owner.IsType(RequiredOwnerType) && CWC.Owner.IsAnyType(ValidOwnerType) && CWC.Weapon.IsType(RequiredWeaponType)) { return CWC.Weapon.IsAnyType(ValidWeaponType); } return false; } public string GetValidTypes() { return $"Required Owner Types [{RequiredOwnerType}], Valid Owner Types [{ValidOwnerType}], Required Weapon Types [{RequiredWeaponType}], Valid Weapon Types [{ValidWeaponType}]"; } public virtual WeaponPropertyBase Clone() { return CopyUtil.Clone(this); } public virtual void OnPropertiesSetup() { if (this is ITriggerCallback triggerCallback) { triggerCallback.Trigger?.OnPropertiesSetup(); } } public abstract void Serialize(Utf8JsonWriter writer); public virtual void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == "id") { if (reader.TokenType == JsonTokenType.String) { ID = StringIDToInt(reader.GetString()); } else { ID = reader.GetUInt32(); } } } public static uint StringIDToInt(string id) { if (!s_stringToIDDict.ContainsKey(id)) { s_stringToIDDict.Add(id, s_nextID--); } return s_stringToIDDict[id]; } } } namespace EWC.CustomWeapon.Properties.Traits { public class AmmoCap : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private const float DefaultPackConv = 5f; public float AmmoCapRel { get; private set; } = 1f; public float AmmopackRefillRel { get; private set; } public float CostOfBullet { get; private set; } public bool ApplyOnDrop { get; private set; } = true; protected override OwnerType RequiredOwnerType => OwnerType.Managed; protected override WeaponType ValidWeaponType => WeaponType.SentryHolder | WeaponType.Gun; public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponPostAmmoInitContext)) { return ApplyOnDrop; } return base.ShouldRegister(contextType); } public void Invoke(WeaponCreatedContext context) { //IL_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected I4, but got Unknown if (AmmopackRefillRel > 0f) { PlayerDataBlock block = GameDataBlockBase.GetBlock(1u); float num = 1f; AmmoType ammoType = base.CWC.Weapon.AmmoType; switch ((int)ammoType) { case 0: num = (float)block.AmmoStandardMaxCap / (float)block.AmmoStandardResourcePackMaxCap; break; case 1: num = (float)block.AmmoSpecialMaxCap / (float)block.AmmoSpecialResourcePackMaxCap; break; case 2: num = (float)block.AmmoClassMaxCap / (float)block.AmmoClassResourcePackMaxCap; break; } AmmoCapRel = AmmopackRefillRel * 5f * num; AmmopackRefillRel = 0f; } if (CostOfBullet > 0f) { AmmoCapRel = ((IAmmoComp)base.CWC.Weapon).ArchetypeData.CostOfBullet / CostOfBullet; CostOfBullet = 0f; } } public void Invoke(WeaponPostAmmoInitContext context) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) InventorySlotAmmo slotAmmo = context.SlotAmmo; IAmmoComp ammoComp = (IAmmoComp)base.CWC.Weapon; slotAmmo.AmmoInPack = ((float)ammoComp.GetCurrentClip() * slotAmmo.CostOfBullet + slotAmmo.AmmoInPack) * AmmoCapRel; ammoComp.SetCurrentClip(context.AmmoStorage.GetClipBulletsFromPack(0, slotAmmo.AmmoType)); } public void Invoke(WeaponPreAmmoPackContext context) { context.AmmoAmount *= AmmoCapRel; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", "AmmoCap"); writer.WriteNumber("AmmoCapRel", AmmoCapRel); writer.WriteNumber("AmmopackRefillRel", AmmopackRefillRel); writer.WriteNumber("CostOfBullet", CostOfBullet); writer.WriteBoolean("ApplyOnDrop", ApplyOnDrop); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } float single; switch (property.Length) { case 10: { char c = property[4]; if (c != 'c') { if (c != 'r' || !(property == "ammorefill")) { break; } goto IL_017c; } if (!(property == "ammocaprel")) { break; } goto IL_014f; } case 6: { char c = property[0]; if (c != 'c') { if (c != 'r' || !(property == "refill")) { break; } goto IL_017c; } if (!(property == "caprel")) { break; } goto IL_014f; } case 12: if (property == "costofbullet") { CostOfBullet = reader.GetSingle(); AmmopackRefillRel = 0f; } break; case 7: if (!(property == "ammocap")) { break; } goto IL_014f; case 3: if (!(property == "cap")) { break; } goto IL_014f; case 17: if (!(property == "ammopackrefillrel")) { break; } goto IL_017c; case 14: if (!(property == "ammopackrefill")) { break; } goto IL_017c; case 13: if (!(property == "ammorefillrel")) { break; } goto IL_017c; case 9: if (!(property == "refillrel")) { break; } goto IL_017c; case 11: if (property == "applyondrop") { ApplyOnDrop = reader.GetBoolean(); } break; case 4: case 5: case 8: case 15: case 16: break; IL_014f: single = reader.GetSingle(); if (single != 1f) { AmmoCapRel = single; CostOfBullet = 0f; AmmopackRefillRel = 0f; } break; IL_017c: AmmopackRefillRel = reader.GetSingle(); CostOfBullet = 0f; break; } } } public sealed class ArmorPierce : Trait, IWeaponProperty, IWeaponProperty { public enum PierceType { Pierce = 0, Multi = 1, Multiply = 1, Override = 2, OverPierce = 3 } public float Pierce { get; private set; } = 1f; public PierceType Type { get; private set; } = PierceType.OverPierce; public void Invoke(WeaponArmorContext context) { context.ArmorMulti = Type switch { PierceType.Pierce => context.ArmorMulti + (1f - context.ArmorMulti) * Pierce, PierceType.Multi => context.ArmorMulti * Pierce, PierceType.Override => Pierce, PierceType.OverPierce => (Pierce < 1f) ? (context.ArmorMulti + (1f - context.ArmorMulti) * Pierce) : Pierce, _ => context.ArmorMulti, }; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Pierce", Pierce); writer.WriteString("Type", Type.ToString()); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (!(property == "pierce")) { if (property == "type") { Type = reader.GetString().ToEnum(PierceType.OverPierce); } } else { Pierce = reader.GetSingle(); } } } public sealed class AutoAim : Trait, ITriggerCallback, IWeaponProperty, IWeaponProperty, ITriggerEvent, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private enum Callback { Locked, Unlocked, NewLock } private TriggerCoordinator? _coordinator; public CrosshairHitIndicator? _reticle; private FPSCamera? _camera; private float _detectionTick; private EnemyAgent? _target; private bool _hasTarget; private Vector3 _lastTargetPos; private bool _reticleActive; private bool _lastAutoAim; private float _progress; private float _lastUpdateTime; private HashSet? _triggerTargets; private HashSet>? _triggerAgents; private static readonly TriggerEventHelper _eventHelper = new TriggerEventHelper(CallbackMap); private float _weakspotDetectionTick; private Collider? _weakspotCollider; private byte _weakspotLimbID; private Transform? _weakspotTarget; private readonly List _bodyList = new List(); private readonly List<(Collider collider, byte limbID)> _weakspotList = new List<(Collider, byte)>(); private static Ray s_ray; private static RaycastHit s_raycastHit; private readonly Color _passiveDetection = new Color(0.5f, 0.5f, 0.5f, 1f); private readonly Vector3 _targetedAngles = new Vector3(0f, 0f, 45f); public bool HipActive { get; private set; } public bool AimActive { get; private set; } = true; public float Angle { get; private set; } public float Range { get; private set; } public bool RequireLOS { get; private set; } = true; public float LockTime { get; private set; } public float LockDecayTime { get; private set; } public bool StayOnTarget { get; private set; } public bool StayRequireLOS { get; private set; } = true; public float StayAngle { get; private set; } = -1f; public float StayRange { get; private set; } = -1f; public bool ResetOnNewTarget { get; private set; } public bool RequireLock { get; private set; } public bool LockWhileEmpty { get; private set; } = true; public bool TagOnly { get; private set; } public bool IgnoreInvisibility { get; private set; } public TargetingMode TargetMode { get; private set; } public TargetingPriority TargetPriority { get; private set; } public bool FavorLookPoint { get; private set; } public bool HomingOnly { get; private set; } public Color LockedColor { get; private set; } = new Color(1.2f, 0.3f, 0.1f, 1f); public Color LockingColor { get; private set; } = new Color(0.8f, 0.3f, 0.2f, 1f); public float LockScale { get; private set; } = 1f; public bool UseTrigger { get; private set; } public TriggerCoordinator? Trigger { get { return _coordinator; } set { _coordinator = value; if (value != null) { value.Parent = this; } } } private static BaseDamageableWrapper TempDamWrapper => BaseDamageableWrapper.SharedInstance; private static ObjectWrapper TempEnemyWrapper => ObjectWrapper.SharedInstance; protected override OwnerType RequiredOwnerType => OwnerType.Local; protected override WeaponType RequiredWeaponType => WeaponType.Gun; private bool HasAmmo { get { if (base.CGC.Gun.GetCurrentClip() > 0) { return !((ItemEquippable)((LocalGunComp)base.CGC.Gun).Value).IsReloading; } return false; } } private bool CanLock { get { if (!LockWhileEmpty) { return HasAmmo; } return true; } } private bool LockedTarget { get { if ((Object)(object)_target != (Object)null) { return _progress == 1f; } return false; } } private bool AutoAimActive { get { if (AimActive != base.CWC.Owner.Player.FPItemHolder.ItemAimTrigger) { return HipActive != base.CWC.Owner.Player.FPItemHolder.ItemAimTrigger; } return true; } } public bool UseAutoAim { get { if (LockedTarget) { return AutoAimActive; } return false; } } public override bool ShouldRegister(Type contextType) { if (!RequireLock && (contextType == typeof(WeaponPreStartFireContext) || contextType == typeof(WeaponFireCancelContext))) { return false; } if ((!UseTrigger || Trigger == null) && contextType == typeof(WeaponTriggerContext)) { return false; } return base.ShouldRegister(contextType); } public void Invoke(WeaponPreStartFireContext context) { context.Allow &= UseAutoAim; } public void Invoke(WeaponFireCancelContext context) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 LocalGunComp localGunComp = (LocalGunComp)base.CWC.Weapon; if ((int)localGunComp.FireMode != 1 || localGunComp.GunArchetype.BurstIsDone()) { context.Allow &= UseAutoAim; } } public void Invoke(WeaponPreRayContext context) { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) if ((Object)(object)_camera == (Object)null || HomingOnly || context.Data.maxRayDist < base.CGC.Gun.MaxRayDist || !UseAutoAim) { return; } if (FavorLookPoint) { ((Ray)(ref s_ray)).origin = _camera.Position; ((Ray)(ref s_ray)).direction = context.Data.fireDir; if (Physics.Raycast(s_ray, ref s_raycastHit, 100f, LayerUtil.MaskEntityAndWorld3P)) { IDamageable? damageableFromRayHit = DamageableUtil.GetDamageableFromRayHit(s_raycastHit); Agent val = ((damageableFromRayHit != null) ? damageableFromRayHit.GetBaseAgent() : null); if ((Object)(object)val != (Object)null && val.Alive && (!RequireLock || (Object)(object)val == (Object)(object)_target)) { return; } } } HitData data = context.Data; Vector3 val2 = GetTargetPos() - _camera.Position; data.fireDir = ((Vector3)(ref val2)).normalized; } public void Invoke(WeaponCreatedContext context) { _reticle = AutoAimReticle.Reticle; _camera = base.CWC.Owner.Player.FPSCamera; } public void Invoke(WeaponUnWieldContext _) { OnDisable(); } public void Invoke(WeaponClearContext _) { OnDisable(); } public void Invoke(WeaponUpdateContext _) { if (!_reticleActive) { _reticleActive = true; OnEnable(); } EnemyAgent target = _target; UpdateDetection(); if (UseAutoAim && !_lastAutoAim) { _eventHelper.Invoke(base.CWC, new WeaponReferenceContext(base.ID, 0u)); _eventHelper.Invoke(base.CWC, new WeaponReferenceContext(base.ID, 2u)); } else if (UseAutoAim && (Object)(object)_target != (Object)(object)target && (Object)(object)_target != (Object)null) { _eventHelper.Invoke(base.CWC, new WeaponReferenceContext(base.ID, 2u)); } else if (!UseAutoAim && _lastAutoAim) { _eventHelper.Invoke(base.CWC, new WeaponReferenceContext(base.ID, 1u)); } _lastAutoAim = UseAutoAim; UpdateAnimate(); } public void Invoke(WeaponTriggerContext context) { Trigger.Invoke(context); } public void TriggerApply(List contexts) { if (!UseTrigger) { return; } foreach (TriggerContext context in contexts) { WeaponHitDamageableContextBase weaponHitDamageableContextBase = (WeaponHitDamageableContextBase)context.context; if (!_triggerTargets.Contains(TempDamWrapper.Set(weaponHitDamageableContextBase.Damageable))) { _triggerTargets.Add(new BaseDamageableWrapper(TempDamWrapper)); _triggerAgents.Add(new ObjectWrapper(((Il2CppObjectBase)TempDamWrapper.Object.GetBaseAgent()).Cast())); } } } public void TriggerReset() { if (UseTrigger) { _triggerTargets.Clear(); _triggerAgents.Clear(); } } public uint GetCallbackID(string callbackName) { return _eventHelper.GetCallbackID(callbackName); } public void OnDisable() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (_progress == 1f) { _eventHelper.Invoke(base.CWC, new WeaponReferenceContext(base.ID, 1u)); } _lastAutoAim = false; _reticleActive = false; _progress = 0f; _target = null; if ((Object)(object)_reticle != (Object)null) { ((Component)_reticle).transform.localScale = Vector3.zero; ((GuiLayerComp)_reticle).SetVisible(false, false); } } public void OnEnable() { CrosshairHitIndicator? reticle = _reticle; if (reticle != null) { ((GuiLayerComp)reticle).SetVisible(true, false); } } private void UpdateDetection() { if ((Object)(object)_target != (Object)null && _progress < 1f) { _progress = Math.Min(1f, _progress + (Clock.Time - _lastUpdateTime) / LockTime); } else if ((Object)(object)_target == (Object)null && _progress > 0f) { _progress = Math.Max(0f, _progress - (Clock.Time - _lastUpdateTime) / LockDecayTime); } _lastUpdateTime = Clock.Time; if (!CanLock) { if (LockDecayTime <= 0f) { _progress = 0f; } _target = null; _hasTarget = false; return; } if (_hasTarget && ((Object)(object)_target == (Object)null || !((Agent)_target).Alive || ((Dam_SyncedDamageBase)_target.Damage).Health <= 0f)) { _target = null; _detectionTick = 0f; } if (_detectionTick >= Time.time) { return; } if (StayOnTarget && (Object)(object)_target != (Object)null && !CheckTargetValid()) { _target = null; } if ((Object)(object)_target == (Object)null || !StayOnTarget) { EnemyAgent target = _target; _target = CheckForTarget(); _hasTarget = (Object)(object)_target != (Object)null; if (_hasTarget && (Object)(object)_target != (Object)(object)target) { if (TargetMode == TargetingMode.Weakspot) { ResetWeakspotLists(); } if (ResetOnNewTarget) { _progress = 0f; } } } if ((Object)(object)_target == (Object)null && LockDecayTime <= 0f) { _progress = 0f; } else if ((Object)(object)_target != (Object)null && LockTime <= 0f) { _progress = 1f; } if (Angle > 0f) { _detectionTick = Time.time + Configuration.AutoAimTickDelay; } } private void UpdateAnimate() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0150: 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) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_target != (Object)null) { _lastTargetPos = GetTargetPos(); } ((Component)_reticle).transform.position = ((CameraController)_camera).m_camera.WorldToScreenPoint(_lastTargetPos); if (UseAutoAim && HasAmmo) { _reticle.m_hitColor = LockedColor; ((Component)_reticle).transform.localScale = Vector3.one * LockScale; ((Component)_reticle).transform.localEulerAngles = _targetedAngles; } else if (LockedTarget) { _reticle.m_hitColor = LockingColor; ((Component)_reticle).transform.localScale = Vector3.one * LockScale; Transform transform = ((Component)_reticle).transform; transform.localEulerAngles += new Vector3(0f, 0f, 1f); } else { float num = _progress * _progress; if ((Object)(object)_target != (Object)null) { Transform transform2 = ((Component)_reticle).transform; transform2.localEulerAngles += new Vector3(0f, 0f, num.Lerp(4f, 1f)); } else { Transform transform3 = ((Component)_reticle).transform; transform3.localEulerAngles += new Vector3(0f, 0f, 5f); } _reticle.m_hitColor = GetLockingColor(num); ((Component)_reticle).transform.localScale = Vector3.one * _progress.Lerp(0f, 1f) * LockScale; } bool flag = AutoAimActive && HasAmmo; Transform transform4 = ((Component)_reticle).transform; transform4.localScale *= (flag ? 1.6f : 1f); _reticle.UpdateColorsWithAlphaMul(flag ? 1f : 0.5f); } private Color GetLockingColor(float frac) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) return new Color(frac.Lerp(_passiveDetection.r, LockingColor.r), frac.Lerp(_passiveDetection.g, LockingColor.g), frac.Lerp(_passiveDetection.b, LockingColor.b), 1f); } public (EnemyAgent?, Collider?, byte) GetTargets() { return (_target, _weakspotCollider, _weakspotLimbID); } private bool CheckTargetValid() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_target == (Object)null || !((Agent)_target).Alive || ((Dam_SyncedDamageBase)_target.Damage).Health <= 0f) { return false; } if (UseTrigger && !_triggerAgents.Contains(TempEnemyWrapper.Set(_target))) { return false; } if (!EnemyIsVisible(_target)) { return false; } float num = ((StayRange >= 0f) ? StayRange : Range); float num2 = ((StayAngle >= 0f) ? StayAngle : Angle); Vector3 targetPos = GetTargetPos(); ((Ray)(ref s_ray)).origin = _camera.Position; ((Ray)(ref s_ray)).direction = _camera.CameraRayDir; if (StayRequireLOS && Physics.Linecast(((Ray)(ref s_ray)).origin, targetPos, LayerUtil.MaskWorldExcProj)) { return false; } RaycastHit val = default(RaycastHit); foreach (Dam_EnemyDamageLimb item in (Il2CppArrayBase)(object)_target.Damage.DamageLimbs) { if (((Component)(object)item).TryGetComp(out var result) && result.enabled) { if (num2 == 0f) { return result.Raycast(s_ray, ref val, num); } Vector3 val2 = result.ClosestPoint(((Ray)(ref s_ray)).origin) - ((Ray)(ref s_ray)).origin; if (((Vector3)(ref val2)).sqrMagnitude < num * num && Vector3.Angle(((Ray)(ref s_ray)).direction, val2) < num2) { return true; } } } return false; } private EnemyAgent? CheckForTarget() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) Ray ray = new Ray(_camera.Position, _camera.CameraRayDir); RaycastHit hit; List list; if (UseTrigger) { if (_triggerAgents.Count == 0) { return null; } if (Angle == 0f) { SearchUtil.SightBlockLayer = LayerUtil.MaskWorld; EnemyAgent enemy3 = null; if (SearchUtil.RaycastFirst(ray, out hit, Range, LayerUtil.MaskEnemy, (IDamageable damageable) => EnemyIsVisible(enemy3 = ((Il2CppObjectBase)damageable.GetBaseAgent()).Cast()) && _triggerAgents.Contains(TempEnemyWrapper.Set(enemy3)), RequireLOS ? SearchSetting.CheckLOS : SearchSetting.None)) { return enemy3; } return null; } list = new List(_triggerAgents.Count); foreach (ObjectWrapper triggerAgent in _triggerAgents) { EnemyAgent @object = triggerAgent.Object; if (SearchUtil.IsAgentInCone(ray, Range, Angle, (Agent)(object)@object, out hit)) { list.Add(@object); } } } else { if (Angle == 0f) { SearchUtil.SightBlockLayer = LayerUtil.MaskWorld; EnemyAgent enemy2 = null; if (SearchUtil.RaycastFirst(ray, out hit, Range, LayerUtil.MaskEnemy, (IDamageable damageable) => EnemyIsVisible(enemy2 = ((Il2CppObjectBase)damageable.GetBaseAgent()).Cast()), RequireLOS ? SearchSetting.CheckLOS : SearchSetting.None)) { return enemy2; } return null; } list = SearchUtil.GetEnemiesInRange(ray, Range, Angle, base.CWC.Owner.CourseNode); } if (list.Count == 0) { return null; } List<(EnemyAgent, float)> list2 = null; switch (TargetPriority) { case TargetingPriority.Distance: { List<(EnemyAgent, float)> list4 = list.ConvertAll(delegate(EnemyAgent enemy) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) Vector3 val2 = GetSearchTargetPos(enemy) - ((Ray)(ref ray)).origin; return (enemy, ((Vector3)(ref val2)).sqrMagnitude); }); list4.Sort(SortUtil.FloatTuple); SortUtil.CopySortedList(list4, list); break; } case TargetingPriority.Health: { List<(EnemyAgent, float, float)> list3 = list.ConvertAll((EnemyAgent enemy) => (enemy, ((Dam_SyncedDamageBase)enemy.Damage).HealthMax, 180f - Vector3.Angle(((Ray)(ref ray)).direction, GetSearchTargetPos(enemy) - ((Ray)(ref ray)).origin))); list3.Sort(SortUtil.FloatTuple); list3.Reverse(); SortUtil.CopySortedList(list3, list); break; } default: list2 = list.ConvertAll((EnemyAgent enemy) => (enemy, Vector3.Angle(((Ray)(ref ray)).direction, GetSearchTargetPos(enemy) - ((Ray)(ref ray)).origin))); list2.Sort(SortUtil.FloatTuple); SortUtil.CopySortedList(list2, list); break; } if (TargetPriority == TargetingPriority.Angle && CheckTargetValid()) { float num = Vector3.Angle(((Ray)(ref ray)).direction, GetTargetPos() - ((Ray)(ref ray)).origin); foreach (var item in list2) { var (val, _) = item; if (item.Item2 >= num) { return _target; } if (EnemyIsVisible(val) && (!RequireLOS || !Physics.Linecast(((Ray)(ref ray)).origin, GetSearchTargetPos(val), LayerUtil.MaskWorldExcProj))) { return val; } } } else { foreach (EnemyAgent item2 in list) { if (EnemyIsVisible(item2) && (!RequireLOS || !Physics.Linecast(((Ray)(ref ray)).origin, GetSearchTargetPos(item2), LayerUtil.MaskWorldExcProj))) { return item2; } } } return null; } private bool EnemyIsVisible(EnemyAgent enemy) { if (!IgnoreInvisibility && (enemy.RequireTagForDetection || TagOnly)) { return enemy.IsTagged; } return true; } private Vector3 GetSearchTargetPos(EnemyAgent enemy) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (TargetMode != TargetingMode.Body) { return ((Agent)enemy).AimTarget.position; } return ((Agent)enemy).AimTargetBody.position; } private Vector3 GetTargetPos() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_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) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_target == (Object)null) { return Vector3.zero; } UpdateWeakspotLimb(); return (Vector3)(TargetMode switch { TargetingMode.Body => ((Agent)_target).AimTargetBody.position, TargetingMode.Weakspot => _weakspotTarget.position, _ => ((Agent)_target).AimTarget.position, }); } private void ResetWeakspotLists() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Invalid comparison between Unknown and I4 _weakspotList.Clear(); _bodyList.Clear(); _weakspotCollider = null; _weakspotLimbID = 0; if ((Object)(object)_target == (Object)null) { return; } _weakspotTarget = ((Agent)_target).AimTarget; foreach (Dam_EnemyDamageLimb item in (Il2CppArrayBase)(object)_target.Damage.DamageLimbs) { if (((Component)(object)item).TryGetComp(out var result) && result.enabled) { if ((int)item.m_type == 1) { _weakspotList.Add((result, (byte)item.m_limbID)); } else { _bodyList.Add(result); } } } } private void UpdateWeakspotLimb() { //IL_00e6: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if (TargetMode != TargetingMode.Weakspot) { return; } if (_weakspotList.Count == 0) { _weakspotTarget = ((Agent)_target).AimTarget; } else { if (_weakspotLimbID != 0 && _weakspotCollider.enabled && Clock.Time < _weakspotDetectionTick) { return; } _weakspotDetectionTick = Clock.Time + Configuration.AutoAimTickDelay; _weakspotList.Sort(WeakspotCompare); _weakspotList.Reverse(); _weakspotCollider = null; _weakspotLimbID = 0; RaycastHit val4 = default(RaycastHit); for (int num = _weakspotList.Count - 1; num >= 0; num--) { var (val, weakspotLimbID) = _weakspotList[num]; if ((Object)(object)val == (Object)null || !val.enabled) { _weakspotList.RemoveAt(num); } else { ((Ray)(ref s_ray)).direction = ((Component)val).transform.position - _camera.Position; ((Ray)(ref s_ray)).origin = _camera.Position; Ray val2 = s_ray; Vector3 val3 = ((Component)val).transform.position - _camera.Position; val.Raycast(val2, ref s_raycastHit, ((Vector3)(ref val3)).magnitude); if (!_bodyList.Any((Collider collider) => collider.Raycast(s_ray, ref val4, ((RaycastHit)(ref s_raycastHit)).distance)) && (!StayRequireLOS || !Physics.Linecast(_camera.Position, ((Component)val).transform.position, LayerUtil.MaskWorldExcProj))) { _weakspotTarget = ((Component)val).transform; _weakspotCollider = val; _weakspotLimbID = weakspotLimbID; return; } } } if (_weakspotList.Count > 0) { _weakspotCollider = _weakspotList[0].collider; _weakspotLimbID = _weakspotList[0].limbID; _weakspotTarget = ((Component)_weakspotCollider).transform; } else { _weakspotTarget = ((Agent)_target).AimTarget; _weakspotCollider = null; _weakspotLimbID = 0; } } } private int WeakspotCompare((Collider? collider, byte) x, (Collider? collider, byte) y) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)x.collider == (Object)null) { return 1; } if ((Object)(object)y.collider == (Object)null) { return -1; } float num = Vector3.Angle(_camera.CameraRayDir, ((Component)x.collider).transform.position - _camera.Position); float num2 = Vector3.Angle(_camera.CameraRayDir, ((Component)y.collider).transform.position - _camera.Position); if (!(num < num2)) { return 1; } return -1; } public override WeaponPropertyBase Clone() { AutoAim autoAim = (AutoAim)base.Clone(); autoAim.Trigger = Trigger?.Clone(); if (UseTrigger) { autoAim._triggerTargets = new HashSet(); autoAim._triggerAgents = new HashSet>(); } return autoAim; } public override void Serialize(Utf8JsonWriter writer) { //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteBoolean("HipActive", HipActive); writer.WriteBoolean("AimActive", AimActive); writer.WriteNumber("Angle", Angle); writer.WriteNumber("Range", Range); writer.WriteBoolean("RequireLOS", RequireLOS); writer.WriteNumber("LockTime", LockTime); writer.WriteNumber("LockDecayTime", LockDecayTime); writer.WriteBoolean("StayOnTarget", StayOnTarget); writer.WriteBoolean("StayRequireLOS", StayRequireLOS); writer.WriteNumber("StayAngle", StayAngle); writer.WriteNumber("StayRange", StayRange); writer.WriteBoolean("ResetOnNewTarget", ResetOnNewTarget); writer.WriteBoolean("RequireLock", RequireLock); writer.WriteBoolean("LockWhileEmpty", LockWhileEmpty); writer.WriteBoolean("TagOnly", TagOnly); writer.WriteBoolean("IgnoreInvisibility", IgnoreInvisibility); writer.WriteString("TargetMode", TargetMode.ToString()); writer.WriteString("TargetPriority", TargetPriority.ToString()); writer.WriteBoolean("FavorLookPoint", FavorLookPoint); writer.WriteBoolean("HomingOnly", HomingOnly); EWCJson.Serialize(writer, "LockedColor", LockedColor); EWCJson.Serialize(writer, "LockingColor", LockingColor); writer.WriteNumber("LockScale", LockScale); writer.WriteBoolean("UseTrigger", UseTrigger); writer.WriteNull("Trigger"); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 9: { char c = property[0]; if ((uint)c <= 104u) { if (c != 'a') { if (c != 'h' || !(property == "hipactive")) { break; } goto IL_03cf; } if (!(property == "aimactive")) { break; } goto IL_03dc; } switch (c) { case 's': if (!(property == "stayangle")) { if (property == "stayrange") { StayRange = reader.GetSingle(); } } else { StayAngle = reader.GetSingle(); } break; case 'l': if (property == "lockscale") { LockScale = reader.GetSingle(); } break; } break; } case 3: { char c = property[0]; if (c != 'a') { if (c != 'h' || !(property == "hip")) { break; } goto IL_03cf; } if (!(property == "aim")) { break; } goto IL_03dc; } case 5: switch (property[0]) { case 'a': if (property == "angle") { Angle = reader.GetSingle(); } break; case 'r': if (property == "range") { Range = reader.GetSingle(); } break; } break; case 10: switch (property[6]) { default: return; case 'e': if (property == "requirelos") { RequireLOS = reader.GetBoolean(); } return; case 'b': if (property == "targetbody" && reader.GetBoolean()) { TargetMode = TargetingMode.Body; } return; case 'm': break; case 'o': if (property == "homingonly") { HomingOnly = reader.GetBoolean(); } return; case 'g': if (property == "usetrigger") { UseTrigger = reader.GetBoolean(); if (UseTrigger) { _triggerTargets = new HashSet(); _triggerAgents = new HashSet>(); } } return; } if (!(property == "targetmode")) { break; } goto IL_04b2; case 13: switch (property[0]) { default: return; case 'l': if (property == "lockdecaytime") { LockDecayTime = reader.GetSingle(); } return; case 't': break; } if (!(property == "targetingmode")) { break; } goto IL_04b2; case 12: switch (property[0]) { case 's': if (property == "stayontarget") { StayOnTarget = reader.GetBoolean(); } break; case 'l': if (property == "lockingcolor") { LockingColor = EWCJson.Deserialize(ref reader); } break; } break; case 14: { char c = property[0]; if ((uint)c <= 108u) { switch (c) { default: return; case 'l': if (property == "lockwhileempty") { LockWhileEmpty = reader.GetBoolean(); } return; case 'f': break; } if (!(property == "favorlookpoint")) { break; } goto IL_04d8; } switch (c) { default: return; case 's': if (property == "stayrequirelos") { StayRequireLOS = reader.GetBoolean(); } return; case 't': break; } if (!(property == "targetpriority")) { break; } goto IL_04c5; } case 11: { char c = property[0]; if ((uint)c <= 108u) { switch (c) { default: return; case 'i': break; case 'l': if (property == "lockedcolor") { LockedColor = EWCJson.Deserialize(ref reader); } return; } if (!(property == "ignoreinvis")) { break; } goto IL_0492; } switch (c) { default: return; case 'r': if (property == "requirelock") { RequireLock = reader.GetBoolean(); } return; case 't': break; } if (!(property == "triggertype")) { break; } goto IL_0544; } case 7: switch (property[1]) { default: return; case 'a': if (property == "tagonly") { TagOnly = reader.GetBoolean(); } return; case 'r': break; } if (!(property == "trigger")) { break; } goto IL_0544; case 8: if (property == "locktime") { LockTime = reader.GetSingle(); } break; case 16: if (property == "resetonnewtarget") { ResetOnNewTarget = reader.GetBoolean(); } break; case 18: if (!(property == "ignoreinvisibility")) { break; } goto IL_0492; case 17: if (!(property == "targetingpriority")) { break; } goto IL_04c5; case 15: if (!(property == "favourlookpoint")) { break; } goto IL_04d8; case 4: case 6: break; IL_04c5: TargetPriority = reader.GetString().ToEnum(TargetingPriority.Angle); break; IL_0492: IgnoreInvisibility = reader.GetBoolean(); break; IL_03dc: AimActive = reader.GetBoolean(); break; IL_03cf: HipActive = reader.GetBoolean(); break; IL_0544: Trigger = TriggerCoordinator.Deserialize(ref reader); VerifyTriggers(); break; IL_04b2: TargetMode = reader.GetString().ToEnum(TargetingMode.Normal); break; IL_04d8: FavorLookPoint = reader.GetBoolean(); break; } } private void VerifyTriggers() { if (Trigger == null) { return; } for (int num = Trigger.Activate.Triggers.Count - 1; num >= 0; num--) { TriggerName name = Trigger.Activate.Triggers[num].Name; if (!ITrigger.HitTriggers.Contains(name)) { EWCLogger.Warning($"{GetType().Name} has an invalid trigger {name}. Only the following are allowed: {string.Join(", ", ITrigger.HitTriggers)}"); Trigger.Activate.Triggers.RemoveAt(num); } } TriggerCoordinator? trigger = Trigger; if (trigger == null || !trigger.Activate.Triggers.Any()) { Trigger = null; } } private static uint CallbackMap(string callback) { return callback switch { "locked" => 0u, "unlocked" => 1u, "newlock" => 2u, _ => 0u, }; } } public enum TargetingMode { Normal, Body, Weakspot, ClosestLimb } public enum TargetingPriority { Angle, Distance, Health } public static class AutoAimReticle { public static readonly CrosshairHitIndicator Reticle; static AutoAimReticle() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) Reticle = Object.Instantiate(GuiManager.CrosshairLayer.m_hitIndicatorFriendly, ((GuiLayer)GuiManager.CrosshairLayer).CanvasTrans); ((Object)Reticle).name = "AutoAimIndicator"; ((Component)Reticle).transform.localScale = Vector3.zero; ((Component)Reticle).transform.localEulerAngles = Vector3.zero; Reticle.m_hitColor = Color.black; Reticle.UpdateColorsWithAlphaMul(0f); } } public sealed class AutoTrigger : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty { private bool _cachedTrigger; protected override OwnerType RequiredOwnerType => OwnerType.Local; protected override WeaponType RequiredWeaponType => WeaponType.Gun; public void Invoke(WeaponSetupContext context) { LocalGunComp localGunComp = (LocalGunComp)base.CWC.Weapon; _cachedTrigger = localGunComp.GunArchetype.m_triggerNeedsPress; localGunComp.GunArchetype.m_triggerNeedsPress = false; } public void Invoke(WeaponClearContext context) { ((LocalGunComp)base.CWC.Weapon).GunArchetype.m_triggerNeedsPress = _cachedTrigger; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteEndObject(); } } public sealed class BackstabMulti : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { public float BackstabDamageMulti { get; private set; } = 1f; public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponSetupContext) || contextType == typeof(WeaponClearContext)) { return base.CWC.Weapon.IsType(WeaponType.Sentry); } return base.ShouldRegister(contextType); } public void Invoke(WeaponSetupContext _) { ((SentryGunComp)base.CWC.Weapon).AllowBackstabOverride = true; } public void Invoke(WeaponClearContext _) { ((SentryGunComp)base.CWC.Weapon).AllowBackstabOverride = false; } public void Invoke(WeaponBackstabContext context) { context.AddMod(BackstabDamageMulti, StackType.Multiply); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("BackstabDamageMulti", BackstabDamageMulti); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property.ToLowerInvariant()) { case "backstabdamagemulti": case "backdamagemulti": case "backstabmulti": case "backmulti": case "multi": BackstabDamageMulti = reader.GetSingle(); break; } } } public sealed class ChargeExponent : Trait, IWeaponProperty, IWeaponProperty { public float Exponent { get; private set; } = 3f; protected override WeaponType RequiredWeaponType => WeaponType.Melee; public void Invoke(WeaponChargeContext context) { context.Exponent = Exponent; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Exponent", Exponent); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property.ToLowerInvariant() == "exponent") { Exponent = reader.GetSingle(); } } } public sealed class DataSwap : Trait, ITriggerCallbackBasicSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private TriggerCoordinator? _coordinator; private ArchetypeDataBlock? _cachedArchBlock; private ArchetypeDataBlock? _archBlock; private BulletWeaponArchetype? _cachedArchetype; private BulletWeaponArchetype? _archetype; private int _magBuffer; private float _costBuffer; private WeaponAudioDataBlock? _cachedAudioBlock; private WeaponAudioDataBlock? _audioBlock; private readonly DelayedCallback _applyCallback; public ushort SyncID { get; set; } public uint ArchetypeID { get; private set; } public uint AudioID { get; private set; } public float Duration { get; private set; } public bool EndBurst { get; private set; } public bool EndCharge { get; private set; } public bool EndFiring { get; private set; } public bool KeepMagCost { get; private set; } public TriggerCoordinator? Trigger { get { return _coordinator; } set { _coordinator = value; if (value != null) { value.Parent = this; } } } protected override WeaponType RequiredWeaponType => WeaponType.Gun; public DataSwap() { _applyCallback = new DelayedCallback(() => Duration, ApplyData, ClearData); } public override bool ShouldRegister(Type contextType) { if (Trigger == null && contextType == typeof(WeaponTriggerContext)) { return false; } return base.ShouldRegister(contextType); } public void Invoke(WeaponTriggerContext context) { Trigger.Invoke(context); } public void Invoke(WeaponCreatedContext context) { BulletWeaponArchetype? archetype = _archetype; if (archetype != null) { archetype.SetOwner(base.CWC.Owner.Player); } BulletWeaponArchetype? cachedArchetype = _cachedArchetype; if (cachedArchetype != null) { cachedArchetype.SetOwner(base.CWC.Owner.Player); } ResetERDComponent(); base.CGC.RefreshSoundDelay(); } public void Invoke(WeaponSetupContext context) { if (GetData() && _applyCallback.Active) { ApplyData(); } } public void Invoke(WeaponClearContext context) { ClearData(); } public void TriggerReset() { TriggerResetSync(); TriggerManager.SendReset(this); } public void TriggerResetSync() { _applyCallback.Stop(); } public void TriggerApply(List contexts) { if (GetData()) { TriggerApplySync(); TriggerManager.SendInstance(this); } } public void TriggerApplySync(float mod = 1f) { if (GetData()) { base.CWC.StartDelayedCallback(_applyCallback); } } private bool GetData() { //IL_0075: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected I4, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Invalid comparison between Unknown and I4 //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if (_archBlock == null) { _archBlock = GameDataBlockBase.GetBlock(ArchetypeID); } if (_audioBlock == null) { _audioBlock = GameDataBlockBase.GetBlock(AudioID); } if (_archBlock != null && base.CWC.Owner.IsType(OwnerType.Local) && _archetype == null) { LocalGunComp localGunComp = (LocalGunComp)base.CWC.Weapon; eWeaponFireMode fireMode = _archBlock.FireMode; switch ((int)fireMode) { case 0: _archetype = (BulletWeaponArchetype?)new BWA_Semi(_archBlock); break; case 1: _archetype = (BulletWeaponArchetype?)new BWA_Burst(_archBlock); break; case 2: _archetype = (BulletWeaponArchetype?)new BWA_Auto(_archBlock); break; case 3: _archetype = (BulletWeaponArchetype?)new BWA_SemiBurst(_archBlock); break; default: throw new NotImplementedException($"DataSwap does not support FireMode {_archBlock.FireMode} for the player (should be one of the standard 4)"); } _archetype.Setup(localGunComp.Value); if ((int)_archBlock.FireMode == 1) { ((Il2CppObjectBase)_archetype).Cast().m_burstMax = _archBlock.BurstShotCount; } if (base.CWC.HasTrait()) { _archetype.m_triggerNeedsPress = false; } _archetype.SetOwner(base.CWC.Owner.Player); ResetERDComponent(); base.CGC.RefreshSoundDelay(); } if (_archBlock == null) { return _audioBlock != null; } return true; } private void ApplyData() { if (_audioBlock != null) { SetLoopingAudio(start: false); } if (_archBlock != null) { ChangeArchetype(); } if (_audioBlock != null) { _cachedAudioBlock = base.CGC.Gun.AudioData; base.CGC.Gun.AudioData = _audioBlock; SetLoopingAudio(start: true); } } private void ClearData() { if (_cachedAudioBlock != null) { SetLoopingAudio(start: false); } if (_cachedArchBlock != null) { ChangeArchetype(); } if (_cachedAudioBlock != null) { base.CGC.Gun.AudioData = _cachedAudioBlock; SetLoopingAudio(start: true); _cachedAudioBlock = null; } } private void ChangeArchetype() { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) LocalGunComp localGunComp = base.CGC.Gun as LocalGunComp; ArchetypeDataBlock val; BulletWeaponArchetype val2; BulletWeaponArchetype oldArch; if (_cachedArchBlock != null) { val = _cachedArchBlock; val2 = _cachedArchetype; oldArch = _archetype; _cachedArchBlock = null; _cachedArchetype = null; } else { val = _archBlock; val2 = _archetype; _cachedArchBlock = base.CGC.Gun.ArchetypeData; _cachedArchetype = localGunComp?.GunArchetype; oldArch = _cachedArchetype; } int currentClip = base.CGC.Gun.GetCurrentClip(); int maxClip = base.CGC.Gun.GetMaxClip(); bool flag = (Object)(object)base.CWC.Owner.Player != (Object)null; PlayerAmmoStorage val3; InventorySlotAmmo val4; float num; if (flag) { val3 = PlayerBackpackManager.GetBackpack(base.CGC.Owner.Player.Owner).AmmoStorage; val4 = val3.GetInventorySlotAmmo(base.CGC.Weapon.AmmoType); num = (float)currentClip * val4.CostOfBullet; } else { if (!base.CWC.Owner.IsType(OwnerType.Sentry)) { return; } val3 = null; val4 = null; num = ((SentryGunComp)base.CWC.Weapon).CostOfBullet; } ArchetypeDataBlock archetypeData = base.CGC.Gun.ArchetypeData; base.CGC.Gun.ArchetypeData = val; if (val2 != null) { CopyArchetypeVars(val2, oldArch); localGunComp.GunArchetype = val2; } base.CGC.RefreshArchetypeCache(archetypeData); ResetERDComponent(); int maxClip2 = base.CGC.Gun.GetMaxClip(); int num2 = maxClip2; float costOfBullet = val.CostOfBullet; if (base.CWC.Weapon.IsType(WeaponType.SentryHolder)) { costOfBullet = ((SentryHolderComp)base.CWC.Weapon).CostOfBullet; } else if (base.CWC.Owner.IsType(OwnerType.Sentry)) { num2 = 0; costOfBullet = ((SentryGunComp)base.CWC.Weapon).CostOfBullet; } if (flag) { val4.Setup(costOfBullet / EXPAPIWrapper.GetCapacityMod(base.CWC.Owner), num2, -1f); costOfBullet = val4.CostOfBullet; } if (KeepMagCost) { float num3 = num; _costBuffer += num3 + 1E-10f; int num4 = Math.Min(maxClip2, (int)(_costBuffer / costOfBullet)); _costBuffer -= (float)num4 * costOfBullet; num3 -= (float)num4 * costOfBullet; if (flag) { InventorySlotAmmo obj = val4; obj.AmmoInPack += num3; } base.CGC.Gun.SetCurrentClip(num4); } else { float num5 = (float)currentClip / (float)maxClip * (float)maxClip2 + (float)_magBuffer; int num6 = Math.Min(maxClip2, (int)num5); float num7 = num + (flag ? val4.AmmoInPack : 0f); if (num7 < (float)num6 * costOfBullet) { num6 = (int)(num7 / costOfBullet); } _magBuffer = Math.Max(0, currentClip - num6 * maxClip / maxClip2); if (flag) { InventorySlotAmmo obj2 = val4; obj2.AmmoInPack += num - (float)num6 * costOfBullet; } base.CGC.Gun.SetCurrentClip(num6); } if (val2 != null) { val2.m_clip = base.CGC.Gun.GetCurrentClip(); } if (base.CGC.SpreadController.Active && (!base.CGC.Gun.IsAiming || ((Item)base.CGC.Gun.Component).ItemDataBlock.ShowCrosshairWhenAiming)) { GuiManager.CrosshairLayer.ShowSpreadCircle(base.CGC.Gun.Component.RecoilData.hipFireCrosshairSizeDefault); } if (flag) { val3.UpdateSlotAmmoUI(val4, base.CGC.Gun.GetCurrentClip()); val3.NeedsSync = true; } } private void CopyArchetypeVars(BulletWeaponArchetype newArch, BulletWeaponArchetype oldArch) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_00a1: Invalid comparison between Unknown and I4 if (oldArch.m_inChargeup) { if (EndCharge) { oldArch.OnStopChargeup(); oldArch.m_nextShotTimer = Clock.Time + oldArch.ShotDelay(); } else if (newArch.HasChargeup) { newArch.m_inChargeup = oldArch.m_inChargeup; newArch.m_chargeupTimer = oldArch.m_chargeupTimer - oldArch.ChargeupDelay() + newArch.ChargeupDelay(); } else { oldArch.OnStopChargeup(); } } if ((int)oldArch.m_archetypeData.FireMode == 1 && !oldArch.BurstIsDone()) { BWA_Burst val = ((Il2CppObjectBase)oldArch).Cast(); if (EndBurst) { val.m_burstCurrentCount = 0; ((BulletWeaponArchetype)val).PostFireCheck(); } else if ((int)newArch.m_archetypeData.FireMode == 1) { BWA_Burst val2 = ((Il2CppObjectBase)newArch).Cast(); val2.m_burstCurrentCount = Math.Min(val.m_burstCurrentCount, val2.m_burstMax); val.m_burstCurrentCount = 0; } } if (oldArch.m_firing && (EndFiring || oldArch.m_archetypeData.FireMode != newArch.m_archetypeData.FireMode)) { oldArch.OnStopFiring(); } newArch.m_nextBurstTimer = oldArch.m_nextBurstTimer; newArch.m_nextShotTimer = oldArch.m_nextShotTimer; newArch.m_fireHeld = oldArch.m_fireHeld; newArch.m_firePressed = oldArch.m_firePressed; newArch.m_firing = oldArch.m_firing; newArch.m_readyToFire = oldArch.m_readyToFire; } private void SetLoopingAudio(bool start) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 if (base.CWC.Weapon is LocalGunComp localGunComp) { if (!localGunComp.GunArchetype.m_firing) { return; } if ((int)localGunComp.FireMode == 2 && !localGunComp.AudioData.TriggerAutoAudioForEachShot) { if (start) { localGunComp.Value.TriggerAutoFireStartAudio(); } else { localGunComp.Value.TriggerAutoFireEndAudio(); } } if ((int)localGunComp.FireMode == 1 && !localGunComp.AudioData.TriggerBurstAudioForEachShot && start) { localGunComp.Value.TriggerBurstFireAudio(); } } else if (base.CWC.Weapon is SentryGunComp sentryGunComp && sentryGunComp.Value.m_isFiring && (int)sentryGunComp.FireMode == 2) { if (start) { sentryGunComp.Firing.TriggerAutoFireStartAudio(); } else { sentryGunComp.Firing.TriggerAutoFireEndAudio(); } } } private void ResetERDComponent() { if (base.CWC.Owner.IsType(OwnerType.Local)) { ERDAPIWrapper.ChangeCustomRecoil(((GameDataBlockBase)(object)base.CGC.Gun.ArchetypeData).persistentID, ((IBulletWeaponComp)base.CWC.Weapon).BulletWeapon); } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("ArchetypeID", ArchetypeID); writer.WriteNumber("AudioID", AudioID); writer.WriteNumber("Duration", Duration); writer.WriteBoolean("EndBurst", EndBurst); writer.WriteBoolean("EndCharge", EndCharge); writer.WriteBoolean("EndFiring", EndFiring); writer.WriteBoolean("KeepMagCost", KeepMagCost); writer.WriteNull("Trigger"); writer.WriteEndObject(); } public override WeaponPropertyBase Clone() { DataSwap obj = (DataSwap)base.Clone(); obj.Trigger = Trigger?.Clone(); return obj; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 11: { char c = property[0]; if ((uint)c <= 107u) { if (c != 'a') { if (c != 'k' || !(property == "keepmagcost")) { return; } goto IL_0243; } if (!(property == "archetypeid")) { return; } goto IL_020f; } if (c != 't') { if (c != 'w' || !(property == "weaponaudio")) { return; } goto IL_01f5; } if (!(property == "triggertype")) { return; } break; } case 7: { char c = property[0]; if (c != 'a') { if (c != 'k') { if (c != 't' || !(property == "trigger")) { return; } break; } if (!(property == "keepmag")) { return; } goto IL_0243; } if (!(property == "audioid")) { return; } goto IL_01f5; } case 8: switch (property[0]) { default: return; case 'd': if (property == "duration") { Duration = reader.GetSingle(); } return; case 'e': if (property == "endburst") { EndBurst = reader.GetBoolean(); } return; case 'k': break; } if (!(property == "keepclip")) { return; } goto IL_0243; case 9: switch (property[3]) { default: return; case 'h': break; case 'c': if (property == "endcharge") { EndCharge = reader.GetBoolean(); } return; case 'f': if (property == "endfiring") { EndFiring = reader.GetBoolean(); } return; } if (!(property == "archetype")) { return; } goto IL_020f; case 13: if (!(property == "weaponaudioid")) { return; } goto IL_01f5; case 5: if (!(property == "audio")) { return; } goto IL_01f5; case 6: if (!(property == "archid")) { return; } goto IL_020f; case 4: if (!(property == "arch")) { return; } goto IL_020f; case 12: if (!(property == "keepclipcost")) { return; } goto IL_0243; case 10: return; IL_01f5: AudioID = EWCJson.Deserialize(ref reader); return; IL_020f: ArchetypeID = EWCJson.Deserialize(ref reader); return; IL_0243: KeepMagCost = reader.GetBoolean(); return; } Trigger = TriggerCoordinator.Deserialize(ref reader); } } public sealed class EnforceFireRate : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private int _lastSyncShotCount; private bool _inExtraShots; private float _nextShotTime; private float _fireShotTime; private float _shotBuffer; private float _fixedTime; private static readonly float FixedDelta; protected override OwnerType ValidOwnerType => OwnerType.Local | OwnerType.Unmanaged; protected override WeaponType RequiredWeaponType => WeaponType.Gun; static EnforceFireRate() { FixedDelta = Time.fixedDeltaTime; } public void Invoke(WeaponSetupContext context) { _nextShotTime = 0f; _shotBuffer = 0f; } public void Invoke(WeaponShotCooldownContext context) { _nextShotTime = context.NextShotTime; } public void Invoke(WeaponPreFireContext context) { _fireShotTime = _nextShotTime; } public void Invoke(WeaponPreFireContextSync context) { _fireShotTime = _nextShotTime; } public void Invoke(WeaponPostFireContextSync context) { BulletWeaponSynced value = ((SyncedGunComp)base.CWC.Weapon).Value; if (_lastSyncShotCount == 0) { _lastSyncShotCount = value.m_shotsToFire; _shotBuffer = 0f; return; } _shotBuffer += (Clock.Time - _fireShotTime) * base.CGC.CurrentFireRate; int num = (int)_shotBuffer; value.m_shotsToFire = Math.Max(0, value.m_shotsToFire - num); _lastSyncShotCount = value.m_shotsToFire; _shotBuffer -= num; } public void Invoke(WeaponPostFireContext context) { if (_inExtraShots) { return; } LocalGunComp localGunComp = (LocalGunComp)base.CWC.Weapon; float num = _fireShotTime + Clock.Delta; if (Clock.Time > num) { _shotBuffer = 0f; return; } _shotBuffer += (Clock.Time - _fireShotTime) * base.CGC.CurrentFireRate; int shotsInBuffer = GetShotsInBuffer(); _nextShotTime = 0f; if (shotsInBuffer == 0) { return; } _inExtraShots = true; _fixedTime = Time.time - Time.fixedTime; FPSCamera fPSCamera = base.CWC.Owner.Player.FPSCamera; FPS_RecoilSystem recoilSystem = fPSCamera.m_recoilSystem; float delta = Clock.Delta; float val = 1f / base.CGC.CurrentFireRate; val = (Clock.Delta = Math.Min(val, delta)); base.CGC.ShotComponent.CancelAllFX = true; for (int i = 0; i < shotsInBuffer; i++) { recoilSystem.FPS_Update(); ((LookCameraController)fPSCamera).RotationUpdate(); if (!FSFAPIWrapper.hasFSF && (_fixedTime += val) > FixedDelta) { fPSCamera.UpdateCameraRay(); _fixedTime -= FixedDelta; } localGunComp.GunArchetype.OnFireShot(); } base.CGC.ShotComponent.CancelAllFX = false; Clock.Delta = delta; _shotBuffer -= shotsInBuffer; _inExtraShots = false; } private int GetShotsInBuffer() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) LocalGunComp obj = (LocalGunComp)base.CWC.Weapon; int num = obj.GetCurrentClip(); if (base.CWC.HasTrait()) { num += PlayerBackpackManager.GetBackpack(base.CWC.Owner.Player.Owner).AmmoStorage.GetBulletsInPack(base.CWC.Weapon.AmmoType); } if (obj.TryGetBurstArchetype(out BWA_Burst burstArchetype)) { num = Math.Min(num, burstArchetype.m_burstCurrentCount); } return Math.Min(num, (int)_shotBuffer); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteEndObject(); } } public sealed class HitmarkerCooldown : Trait, IWeaponProperty, IWeaponProperty { private float _lastHitmarkerTime; private readonly Dictionary, float> _cooldownsPerTarget = new Dictionary, float>(); public float Cooldown { get; private set; } public float CooldownPerTarget { get; private set; } private static ObjectWrapper TempWrapper => ObjectWrapper.SharedInstance; protected override OwnerType RequiredOwnerType => OwnerType.Managed; protected override OwnerType ValidOwnerType => OwnerType.Local | OwnerType.Sentry; public void Invoke(WeaponHitmarkerContext context) { float time = Clock.Time; bool flag = true; if (time - _lastHitmarkerTime >= Cooldown) { TempWrapper.Set(context.Enemy); if (!_cooldownsPerTarget.TryGetValue(TempWrapper, out var value)) { _cooldownsPerTarget.Keys.Where((ObjectWrapper wrapper) => (Object)(object)wrapper.Object == (Object)null || !((Agent)wrapper.Object).Alive).ToList().ForEach(delegate(ObjectWrapper wrapper) { _cooldownsPerTarget.Remove(wrapper); }); _cooldownsPerTarget.Add(new ObjectWrapper(TempWrapper), 0f); } else if (time - value < CooldownPerTarget) { flag = false; } } else { flag = false; } if (flag) { _lastHitmarkerTime = time; if (CooldownPerTarget > 0f) { _cooldownsPerTarget[TempWrapper] = time; } } else { context.Result = false; } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Cooldown", Cooldown); writer.WriteNumber("CooldownPerTarget", CooldownPerTarget); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (!(property == "cooldown")) { if (property == "cooldownpertarget") { CooldownPerTarget = reader.GetSingle(); } } else { Cooldown = reader.GetSingle(); } } } public sealed class HoldBurst : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private int _burstMaxCount; private int _burstCurrentCount; public int ShotsUntilCancel { get; private set; } = 1; public bool RequireHold { get; private set; } = true; public bool CancelConsumeClip { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Local; protected override WeaponType RequiredWeaponType => WeaponType.Gun; public override bool ShouldRegister(Type contextType) { if (!CancelConsumeClip) { if (contextType == typeof(WeaponPostStopFiringContext)) { return false; } if (contextType == typeof(WeaponPostFireContext)) { return false; } } return base.ShouldRegister(contextType); } public void Invoke(WeaponPostStartFireContext context) { if (((LocalGunComp)base.CGC.Gun).TryGetBurstArchetype(out BWA_Burst burstArchetype)) { _burstMaxCount = burstArchetype.m_burstCurrentCount; _burstCurrentCount = 0; } } public void Invoke(WeaponFireCancelContext context) { if (((LocalGunComp)base.CGC.Gun).TryGetBurstArchetype(out BWA_Burst burstArchetype) && _burstMaxCount - burstArchetype.m_burstCurrentCount >= ShotsUntilCancel && !((BulletWeaponArchetype)burstArchetype).m_fireHeld && (RequireHold || !CanShoot())) { ConsumeFromClip(); burstArchetype.m_burstCurrentCount = 0; _burstCurrentCount = 0; context.Allow = false; } } public void Invoke(WeaponPostFireContext context) { if (((LocalGunComp)base.CGC.Gun).TryGetBurstArchetype(out BWA_Burst burstArchetype)) { _burstCurrentCount = burstArchetype.m_burstCurrentCount; } } public void Invoke(WeaponPostStopFiringContext context) { if (((LocalGunComp)base.CGC.Gun).TryGetBurstArchetype(out BWA_Burst _)) { ConsumeFromClip(); } } private void ConsumeFromClip() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (_burstCurrentCount != 0) { int currentClip = base.CGC.Gun.GetCurrentClip(); int num = Math.Min(_burstCurrentCount, currentClip); InventorySlotAmmo inventorySlotAmmo = PlayerBackpackManager.LocalBackpack.AmmoStorage.GetInventorySlotAmmo(base.CGC.Gun.AmmoType); inventorySlotAmmo.AmmoInPack += (float)num * inventorySlotAmmo.CostOfBullet; base.CGC.Gun.SetCurrentClip(currentClip - num); } } public void Invoke(WeaponSprintContext context) { if (base.CGC.Owner.Player.Locomotion.IsRunning && ((LocalGunComp)base.CGC.Gun).TryGetBurstArchetype(out BWA_Burst burstArchetype) && ((BulletWeaponArchetype)burstArchetype).m_firing) { burstArchetype.m_burstCurrentCount = 0; ((BulletWeaponArchetype)burstArchetype).PostFireCheck(); } } public void Invoke(WeaponPreSprintContext context) { if (((LocalGunComp)base.CGC.Gun).TryGetBurstArchetype(out BWA_Burst burstArchetype)) { context.AllowBurstCancel = context.AllowBurstCancel || _burstMaxCount - burstArchetype.m_burstCurrentCount >= ShotsUntilCancel; } } public void Invoke(WeaponPreSwapContext context) { if (((LocalGunComp)base.CGC.Gun).TryGetBurstArchetype(out BWA_Burst burstArchetype)) { context.AllowBurstCancel = context.AllowBurstCancel || _burstMaxCount - burstArchetype.m_burstCurrentCount >= ShotsUntilCancel; } } private bool CanShoot() { if (base.CGC.Gun.Component.FPItemHolder.ItemIsBusy) { return false; } PlayerLocomotion locomotion = base.CGC.Owner.Player.Locomotion; if (!locomotion.IsRunning) { return !locomotion.IsInAir; } return false; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("ShotsUntilCancel", ShotsUntilCancel); writer.WriteBoolean("RequireHold", RequireHold); writer.WriteBoolean("CancelConsumeClip", CancelConsumeClip); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property) { case "shotsuntilcancel": case "shots": ShotsUntilCancel = reader.GetInt32(); break; case "requirehold": case "hold": RequireHold = reader.GetBoolean(); break; case "cancelconsumeclip": case "cancelconsumemag": CancelConsumeClip = reader.GetBoolean(); break; } } } public sealed class MultiShot : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private static Ray s_ray; private static readonly HitData s_hitData = new HitData(DamageType.Bullet); private static float s_initialShotMod = 1f; public float[] Offsets { get; private set; } = Array.Empty(); public float AimOffsetMod { get; private set; } = 1f; public uint Repeat { get; private set; } public bool UseAimDir { get; private set; } public float Spread { get; private set; } public bool IgnoreSpreadMod { get; private set; } public bool CancelShot { get; private set; } public bool ForceSingleBullet { get; private set; } public bool RunHitTriggers { get; private set; } = true; protected override WeaponType RequiredWeaponType => WeaponType.Gun; public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponSetupContext) || contextType == typeof(WeaponClearContext)) { return CancelShot; } return base.ShouldRegister(contextType); } public void Invoke(WeaponPreFireContext context) { s_initialShotMod = 1f; if (base.CWC.Owner.IsType(OwnerType.Local)) { BulletWeapon value = ((LocalGunComp)base.CWC.Weapon).Value; if (Clock.Time - value.m_lastFireTime > value.m_fireRecoilCooldown) { s_initialShotMod = 0.2f; } } } public void Invoke(WeaponSetupContext context) { base.CGC.ShotComponent.CancelNormalShot = true; } public void Invoke(WeaponClearContext context) { base.CGC.ShotComponent.CancelNormalShot = false; } public void Invoke(WeaponPostFireContextSync context) { //IL_002f: 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_0048: Unknown result type (might be due to invalid IL or missing references) if (base.CWC.HasTrait()) { return; } bool isShotgun = base.CGC.Gun.IsShotgun; ((Ray)(ref s_ray)).origin = base.CWC.Owner.FirePos; ((Ray)(ref s_ray)).direction = ((UseAimDir || isShotgun) ? base.CWC.Owner.FireDir : ShotManager.VanillaFireDir); int num = 1; int num2 = 0; float num3 = 0f; if (isShotgun && !ForceSingleBullet) { num = base.CGC.Gun.ArchetypeData.ShotgunBulletCount; num2 = base.CGC.Gun.ArchetypeData.ShotgunConeSize; num3 = (float)Math.PI / 180f * (360f / (float)(num - 1)); } float num4 = Spread; if (num4 < 0f) { num4 = (isShotgun ? ((float)base.CGC.Gun.ArchetypeData.ShotgunBulletSpread) : 0f); } for (uint num5 = 1u; num5 <= Repeat + 1; num5++) { for (int i = 0; i < Offsets.Length; i += 2) { float num6 = Offsets[i] * (float)num5; float num7 = (0f - Offsets[i + 1]) * (float)num5; FireVisual(num6, num7, num4); for (int j = 1; j < num; j++) { float num8 = num3 * (float)j; FireVisual(num6 + (float)num2 * (float)Math.Cos(num8), num7 + (float)num2 * (float)Math.Sin(num8), num4); } } } } public void Invoke(WeaponPostFireContext context) { //IL_0021: 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_003a: Unknown result type (might be due to invalid IL or missing references) bool isShotgun = base.CGC.Gun.IsShotgun; ((Ray)(ref s_ray)).origin = base.CWC.Owner.FirePos; ((Ray)(ref s_ray)).direction = ((UseAimDir || isShotgun) ? base.CWC.Owner.FireDir : ShotManager.VanillaFireDir); int num = 1; float num2 = 0f; float num3 = 0f; ArchetypeDataBlock archetypeData = base.CGC.Gun.ArchetypeData; if (isShotgun && !ForceSingleBullet) { num = archetypeData.ShotgunBulletCount; num2 = archetypeData.ShotgunConeSize; num3 = (float)Math.PI / 180f * (360f / (float)(num - 1)); } bool isAiming = base.CGC.Gun.IsAiming; float num4 = Spread; if (num4 < 0f) { num4 = ((!isShotgun) ? ((isAiming ? archetypeData.AimSpread : archetypeData.HipFireSpread) * s_initialShotMod) : ((float)archetypeData.ShotgunBulletSpread)); } float num5 = (isAiming ? AimOffsetMod : 1f); if (!IgnoreSpreadMod) { float value = base.CGC.SpreadController.Value; num4 *= value; num2 *= value; num5 *= value; } for (uint num6 = 1u; num6 <= Repeat + 1; num6++) { for (int i = 0; i < Offsets.Length; i += 2) { float num7 = Offsets[i] * (float)num6 * num5; float num8 = Offsets[i + 1] * (float)num6 * num5; Fire(num7, num8, num4); for (int j = 1; j < num; j++) { float num9 = num3 * (float)j; Fire(num7 + num2 * (float)Math.Cos(num9), num8 + num2 * (float)Math.Sin(num9), num4); } } } } private void Fire(float x, float y, float spread) { //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_00f8: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) ArchetypeDataBlock archetypeData = base.CGC.Gun.ArchetypeData; s_hitData.owner = base.CWC.Owner.Player; s_hitData.shotInfo.Reset(archetypeData.Damage, archetypeData.PrecisionDamageMulti, archetypeData.StaggerDamageMulti, base.CWC); s_hitData.damage = s_hitData.shotInfo.OrigDamage; s_hitData.damageFalloff = archetypeData.DamageFalloff; s_hitData.pierceLimit = archetypeData.PierceLimit(); s_hitData.staggerMulti = s_hitData.shotInfo.OrigStagger; s_hitData.precisionMulti = archetypeData.PrecisionDamageMulti; s_hitData.maxRayDist = base.CGC.Gun.MaxRayDist; s_hitData.angOffsetX = x; s_hitData.angOffsetY = y; s_hitData.randomSpread = spread; s_hitData.RayHit = default(RaycastHit); ToggleRunTriggers(enable: false); base.CGC.ShotComponent.FireSpread(s_ray, base.CWC.Owner.MuzzleAlign.position, s_hitData, -1, (IntPtr)0); ToggleRunTriggers(enable: true); } private void ToggleRunTriggers(bool enable) { if (!RunHitTriggers) { base.CWC.RunHitTriggers = enable; } } private void FireVisual(float x, float y, float spread) { //IL_0065: 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) s_hitData.owner = base.CWC.Owner.Player; s_hitData.damage = base.CGC.Gun.ArchetypeData.Damage; s_hitData.angOffsetX = x; s_hitData.angOffsetY = y; s_hitData.randomSpread = spread; base.CGC.ShotComponent.FireSpread(s_ray, base.CWC.Owner.MuzzleAlign.position, s_hitData, -1, (IntPtr)0); } public override WeaponPropertyBase Clone() { MultiShot obj = (MultiShot)base.Clone(); obj.Offsets = (float[])Offsets.Clone(); return obj; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); EWCJson.Serialize(writer, "Offsets", Offsets); writer.WriteNumber("AimOffsetMod", AimOffsetMod); writer.WriteNumber("Repeat", Repeat); writer.WriteBoolean("UseAimDir", UseAimDir); writer.WriteNumber("Spread", Spread); writer.WriteBoolean("IgnoreSpreadMod", IgnoreSpreadMod); writer.WriteBoolean("CancelShot", CancelShot); writer.WriteBoolean("ForceSingleBullet", ForceSingleBullet); writer.WriteBoolean("RunHitTriggers", RunHitTriggers); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 7: { char c = property[0]; if (c != 'o') { if (c != 'r' || !(property == "repeats")) { return; } goto IL_01c8; } if (!(property == "offsets")) { return; } goto IL_01ae; } case 6: switch (property[0]) { case 'o': break; case 'a': goto IL_00dd; case 'r': goto IL_00ee; case 's': if (property == "spread") { Spread = reader.GetSingle(); } return; default: return; } if (!(property == "offset")) { return; } goto IL_01ae; case 12: { char c = property[0]; if (c != 'a') { if (c != 'i') { if (c != 's' || !(property == "singlebullet")) { return; } goto IL_0209; } if (!(property == "ignorespread")) { return; } goto IL_01d5; } if (!(property == "aimoffsetmod")) { return; } goto IL_01bb; } case 9: if (!(property == "useaimdir")) { return; } goto IL_01d5; case 15: if (property == "ignorespreadmod") { IgnoreSpreadMod = reader.GetBoolean(); } return; case 16: if (!(property == "cancelnormalshot")) { return; } goto IL_01fc; case 10: if (!(property == "cancelshot")) { return; } goto IL_01fc; case 17: if (!(property == "forcesinglebullet")) { return; } goto IL_0209; case 14: if (!(property == "runhittriggers")) { return; } break; case 11: if (!(property == "hittriggers")) { return; } break; case 8: case 13: return; IL_01fc: CancelShot = reader.GetBoolean(); return; IL_00ee: if (!(property == "repeat")) { return; } goto IL_01c8; IL_00dd: if (!(property == "aimmod")) { return; } goto IL_01bb; IL_01ae: Offsets = JsonUtil.ReadPairs(ref reader); return; IL_01c8: Repeat = reader.GetUInt32(); return; IL_0209: ForceSingleBullet = reader.GetBoolean(); return; IL_01d5: UseAimDir = reader.GetBoolean(); return; IL_01bb: AimOffsetMod = reader.GetSingle(); return; } RunHitTriggers = reader.GetBoolean(); } } public sealed class PierceMulti : Trait, IWeaponProperty, IWeaponProperty { private static readonly DamageType[] BulletType = new DamageType[1] { DamageType.Bullet }; public DamageType[] ModDamageType { get; private set; } = BulletType; public float PierceDamageMulti { get; private set; } = 1f; public void Invoke(WeaponHitDamageableContext context) { if (context.DamageType.HasFlag(DamageType.Bullet)) { context.ShotInfo.Orig.Mod.Add(this, StatType.Damage, PierceDamageMulti, 0f, StackType.Multiply, StackType.Multiply, null, ModDamageType); } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("PierceDamageMulti", PierceDamageMulti); writer.WriteString("ModDamageType", ModDamageType[0].ToString()); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property.ToLowerInvariant()) { case "piercedamagemulti": case "piercemulti": case "multi": PierceDamageMulti = reader.GetSingle(); break; case "moddamagetype": case "damagetype": ModDamageType = reader.GetString().ToDamageTypes(); break; } } } public sealed class Projectile : Trait, ITriggerEvent, ISyncProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { public enum Callback { Alive, Destroyed, TimeOut } private static readonly Random Random = new Random(); private float _accelTime = 0.001f; private Func? _hitFuncOverride; private WallPierce? _wallPierceOverride; private bool _useOverrides; private float _cachedVisualDist; private float _cachedRayDist; private ushort _shotIndex; private static RaycastHit s_rayHit; public readonly TriggerEventHelper EventHelper = new TriggerEventHelper(CallbackMap); public ushort SyncPropertyID { get; set; } public ProjectileType ProjectileType { get; private set; } = (ProjectileType)9; public uint ItemID { get; private set; } public float MinSpeed { get; private set; } public float MaxSpeed { get; private set; } public float AccelScale { get; private set; } = 1f; public float AccelExponent { get; private set; } = 1f; public float AccelTime { get { return _accelTime; } private set { _accelTime = Math.Max(0.001f, value); } } public float Gravity { get; private set; } public float HitSize { get; private set; } public float HitSizeFriendly { get; private set; } public float HitSizeWorld { get; private set; } public float ModelScale { get; private set; } = 1f; public bool EnableTrail { get; private set; } = true; public Color TrailColor { get; private set; } = Color.black; public float TrailWidth { get; private set; } = -1f; public float TrailTime { get; private set; } = -1f; public bool TrailCullOnDie { get; private set; } = true; public Color GlowColor { get; private set; } = Color.black; public float GlowIntensity { get; private set; } = 1f; public float GlowRange { get; private set; } = -1f; public bool DamageFriendly { get; private set; } = true; public bool DamageOwner { get; private set; } public bool HitFromOwnerPos { get; private set; } public float HitCooldown { get; private set; } = -1f; public float HitIgnoreWallsDuration { get; private set; } public DamageType[] HitDestroyDamageType { get; private set; } = DamageTypeConst.Invalid; public float HitDestroyDelay { get; private set; } public int RicochetCount { get; private set; } public float RicochetSpeedMod { get; private set; } = 1f; public float RicochetSpeedAngleFactor { get; private set; } public bool RicochetIgnorePlayers { get; private set; } public bool RicochetResetHits { get; private set; } public bool RicochetOnHit { get; private set; } public bool EnableTerrainHitFX { get; private set; } = true; public float HitCheckCooldown { get; private set; } = 0.05f; public float VisualLerpDist { get; private set; } = 5f; public float Lifetime { get; private set; } = 20f; public float MaxRange { get; private set; } public uint FlyingSoundID { get; private set; } public uint DestroyedSoundID { get; private set; } public bool StopFlyingSoundOnDestroy { get; private set; } public float AliveTriggerDelay { get; private set; } public float AliveTriggerInterval { get; private set; } = 1f; public List DirChanges { get; private set; } = new List(); public List StatChanges { get; private set; } = new List(); public ProjectileHomingSettings HomingSettings { get; private set; } = new ProjectileHomingSettings(); public Func? HitFuncOverride { get { if (!_useOverrides) { return null; } return _hitFuncOverride; } } public WallPierce? WallPierce { get { if (!_useOverrides) { return base.CWC?.GetTrait(); } return _wallPierceOverride; } } public uint GetCallbackID(string callbackName) { return EventHelper.GetCallbackID(callbackName); } public void Invoke(WeaponSetupContext context) { _cachedRayDist = base.CWC.Weapon.MaxRayDist; base.CWC.Weapon.MaxRayDist = 1f; base.CWC.ShotComponent.Projectile = this; } public void Invoke(WeaponClearContext context) { base.CWC.Weapon.MaxRayDist = _cachedRayDist; base.CWC.ShotComponent.Projectile = null; } public void Fire(Ray ray, Vector3 fxPos, HitData hitData, IntPtr ignoreEnt) { //IL_000d: 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_0053: 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_005f: 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) //IL_006b: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if (ItemID != 0) { pItemData val = default(pItemData); val.itemID_gearCRC = ItemID; float num = ((MaxSpeed > MinSpeed) ? Random.NextSingle().Lerp(MinSpeed, MaxSpeed) : MinSpeed); ItemReplicationManager.ThrowItem(val, (delItemCallback)null, (ItemMode)3, ((Ray)(ref ray)).origin, Quaternion.LookRotation(((Ray)(ref ray)).direction), ((Ray)(ref ray)).direction * num, ((Ray)(ref ray)).origin, base.CWC.Owner.CourseNode, base.CWC.Owner.Player); return; } float num2 = ((VisualLerpDist > 0.1f) ? VisualLerpDist : 0.1f); if (Physics.Raycast(ray, ref s_rayHit, num2, LayerUtil.MaskEntityAndWorld3P)) { num2 = ((RaycastHit)(ref s_rayHit)).distance; } Vector3 position = ((Ray)(ref ray)).origin + ((Ray)(ref ray)).direction * Math.Min(num2, 0.1f); EWCProjectileComponentShooter eWCProjectileComponentShooter = EWCProjectileManager.Shooter.CreateAndSendProjectile(this, _shotIndex++, position, fxPos, hitData, ignoreEnt); if ((Object)(object)eWCProjectileComponentShooter == (Object)null) { EWCLogger.Error("Unable to create shooter projectile!"); } else if (VisualLerpDist > 0f && fxPos != Vector3.zero) { eWCProjectileComponentShooter.SetVisualPosition(fxPos, num2); } } internal void SetOverrides(Func? hitFunc, WallPierce? wallPierce, bool disableLerp) { _useOverrides = true; _hitFuncOverride = hitFunc; _wallPierceOverride = wallPierce; if (disableLerp && VisualLerpDist != 0f) { _cachedVisualDist = VisualLerpDist; VisualLerpDist = 0f; } } internal void DisableOverrides() { _useOverrides = false; if (_cachedVisualDist != 0f) { VisualLerpDist = _cachedVisualDist; _cachedVisualDist = 0f; } } public override void Serialize(Utf8JsonWriter writer) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); ProjectileType projectileType = ProjectileType; writer.WriteString("ProjectileType", ((object)(ProjectileType)(ref projectileType)).ToString()); writer.WriteNumber("ItemID", ItemID); writer.WriteNumber("MinSpeed", MinSpeed); writer.WriteNumber("MaxSpeed", MaxSpeed); writer.WriteNumber("AccelScale", AccelScale); writer.WriteNumber("AccelExponent", AccelExponent); writer.WriteNumber("AccelTime", AccelTime); writer.WriteNumber("Gravity", Gravity); writer.WriteNumber("HitSize", HitSize); writer.WriteNumber("HitSizeFriendly", HitSizeFriendly); writer.WriteNumber("HitSizeWorld", HitSizeWorld); writer.WriteNumber("ModelScale", ModelScale); writer.WriteBoolean("EnableTrail", EnableTrail); EWCJson.Serialize(writer, "TrailColor", TrailColor); writer.WriteNumber("TrailWidth", TrailWidth); writer.WriteNumber("TrailTime", TrailTime); writer.WriteBoolean("TrailCullOnDie", TrailCullOnDie); EWCJson.Serialize(writer, "GlowColor", GlowColor); writer.WriteNumber("GlowIntensity", GlowIntensity); writer.WriteNumber("GlowRange", GlowRange); writer.WriteBoolean("DamageFriendly", DamageFriendly); writer.WriteBoolean("DamageOwner", DamageOwner); writer.WriteBoolean("HitFromOwnerPos", HitFromOwnerPos); writer.WriteNumber("HitCooldown", HitCooldown); writer.WriteNumber("HitIgnoreWallsDuration", HitIgnoreWallsDuration); writer.WriteString("HitDestroyDamageType", HitDestroyDamageType[0].ToString()); writer.WriteNumber("HitDestroyDelay", HitDestroyDelay); writer.WriteNumber("RicochetCount", RicochetCount); writer.WriteNumber("RicochetSpeedMod", RicochetSpeedMod); writer.WriteNumber("RicochetSpeedAngleFactor", RicochetSpeedAngleFactor); writer.WriteBoolean("RicochetIgnorePlayers", RicochetIgnorePlayers); writer.WriteBoolean("RicochetResetHits", RicochetResetHits); writer.WriteBoolean("RicochetOnHit", RicochetOnHit); writer.WriteBoolean("EnableTerrainHitFX", EnableTerrainHitFX); writer.WriteNumber("HitCheckCooldown", HitCheckCooldown); writer.WriteNumber("VisualLerpDist", VisualLerpDist); writer.WriteNumber("Lifetime", Lifetime); writer.WriteNumber("MaxRange", MaxRange); writer.WriteNumber("FlyingSoundID", FlyingSoundID); writer.WriteNumber("DestroyedSoundID", DestroyedSoundID); writer.WriteBoolean("StopFlyingSoundOnDestroy", StopFlyingSoundOnDestroy); writer.WriteNumber("AliveTriggerDelay", AliveTriggerDelay); writer.WriteNumber("AliveTriggerInterval", AliveTriggerInterval); writer.WritePropertyName("DirChanges"); ProjectileDirChange.SerializeList(DirChanges, writer); writer.WritePropertyName("StatChanges"); ProjectileStatChange.SerializeList(StatChanges, writer); writer.WritePropertyName("HomingSettings"); HomingSettings.Serialize(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { //IL_07ca: Unknown result type (might be due to invalid IL or missing references) //IL_07d5: Unknown result type (might be due to invalid IL or missing references) //IL_07db: Invalid comparison between Unknown and I4 //IL_08ec: Unknown result type (might be due to invalid IL or missing references) //IL_07de: Unknown result type (might be due to invalid IL or missing references) //IL_07e4: Invalid comparison between Unknown and I4 //IL_08b8: Unknown result type (might be due to invalid IL or missing references) base.DeserializeProperty(property, ref reader); string text = property.ToLowerInvariant(); if (text == null) { return; } switch (text.Length) { case 14: { char c = text[4]; if ((uint)c <= 103u) { if (c != 'a') { if (c != 'e') { if (c != 'g' || !(text == "damagefriendly")) { break; } goto IL_0911; } if (!(text == "projectiletype")) { break; } goto IL_07c1; } if (!(text == "visuallerpdist")) { break; } goto IL_09d9; } if (c != 'l') { if (c != 'n') { if (c != 'r' || !(text == "destroyedsound")) { break; } goto IL_0a28; } if (!(text == "homingsettings")) { break; } goto IL_0a91; } if (!(text == "trailcullondie")) { break; } goto IL_08dd; } case 4: { char c = text[0]; if (c != 'i') { if (c != 's') { if (c != 't' || !(text == "type")) { break; } goto IL_07c1; } if (!(text == "size")) { break; } goto IL_084d; } if (!(text == "item")) { break; } goto IL_07f2; } case 6: { char c = text[0]; if (c != 'h') { if (c != 'i' || !(text == "itemid")) { break; } goto IL_07f2; } if (!(text == "homing")) { break; } goto IL_0a91; } case 8: { char c = text[2]; if ((uint)c <= 102u) { if (c != 'c') { if (c != 'f' || !(text == "lifetime")) { break; } goto IL_09e6; } if (!(text == "ricochet")) { break; } goto IL_0971; } if (c != 'n') { if (c != 'r') { if (c != 'x') { break; } if (!(text == "maxspeed")) { if (!(text == "maxrange")) { break; } goto IL_09f3; } MaxSpeed = reader.GetSingle(); break; } if (!(text == "lerpdist")) { break; } goto IL_09d9; } if (!(text == "minspeed")) { break; } goto IL_07ff; } case 5: switch (text[0]) { default: return; case 's': break; case 'a': goto IL_0460; case 't': goto IL_0471; case 'r': goto IL_0482; } if (text == "speed") { goto IL_07ff; } if (!(text == "scale")) { break; } goto IL_0892; case 10: { char c = text[1]; if ((uint)c <= 99u) { if (c != 'a') { if (c != 'c' || !(text == "accelscale")) { break; } goto IL_0819; } if (!(text == "damageuser")) { break; } goto IL_091e; } switch (c) { default: return; case 'o': break; case 'r': if (!(text == "trailcolor")) { if (text == "trailwidth") { TrailWidth = reader.GetSingle(); } } else { TrailColor = EWCJson.Deserialize(ref reader); } return; case 'i': if (text == "dirchanges") { DirChanges = ProjectileDirChange.DeserializeList(ref reader); } return; } if (!(text == "modelscale")) { break; } goto IL_0892; } case 13: switch (text[10]) { case 'e': break; case 'i': if (text == "glowintensity") { GlowIntensity = reader.GetSingle(); } return; case 'u': goto IL_051a; case 'h': if (text == "ricochetonhit") { RicochetOnHit = reader.GetBoolean(); } return; case 'd': goto IL_053c; default: return; } if (!(text == "accelexponent")) { break; } goto IL_0826; case 9: { char c = text[6]; if ((uint)c <= 110u) { switch (c) { case 'i': if (!(text == "acceltime")) { if (text == "trailtime") { TrailTime = reader.GetSingle(); } } else { AccelTime = reader.GetSingle(); } break; case 'l': if (text == "glowcolor") { GlowColor = EWCJson.Deserialize(ref reader); } break; case 'n': if (text == "glowrange") { GlowRange = reader.GetSingle(); } break; } break; } if (c != 'r') { if (c != 'u') { if (c != 'x' || !(text == "accelexpo")) { break; } goto IL_0826; } if (!(text == "trailcull")) { break; } goto IL_08dd; } if (!(text == "sizeworld")) { break; } goto IL_087b; } case 7: switch (text[0]) { default: return; case 'g': if (text == "gravity") { Gravity = reader.GetSingle(); } return; case 'h': break; } if (!(text == "hitsize")) { break; } goto IL_084d; case 15: switch (text[3]) { case 's': break; case 'f': goto IL_05f6; case 'd': goto IL_0607; case 'b': goto IL_0618; default: return; } if (!(text == "hitsizefriendly")) { break; } goto IL_0864; case 12: switch (text[0]) { case 's': break; case 'h': goto IL_063a; case 'f': goto IL_064b; case 'd': goto IL_065c; default: return; } if (!(text == "sizefriendly")) { break; } goto IL_0864; case 11: switch (text[0]) { case 'e': break; case 'd': goto IL_067e; case 'h': if (text == "hitcooldown") { HitCooldown = reader.GetSingle(); } return; case 'm': goto IL_06a0; case 'f': goto IL_06b1; case 's': if (text == "statchanges") { StatChanges = ProjectileStatChange.DeserializeList(ref reader); } return; default: return; } if (!(text == "enabletrail")) { break; } goto IL_08a9; case 20: { char c = text[3]; if (c != 'd') { switch (c) { default: return; case 'f': break; case 'v': if (text == "alivetriggerinterval") { AliveTriggerInterval = reader.GetSingle(); } return; } if (!(text == "hitfromownerposition")) { break; } goto IL_092b; } if (!(text == "hitdestroydamagetype")) { break; } goto IL_0952; } case 17: switch (text[0]) { default: return; case 'd': break; case 'r': if (text == "ricochetresethits") { RicochetResetHits = reader.GetBoolean(); } return; case 'a': if (text == "alivetriggerdelay") { AliveTriggerDelay = reader.GetSingle(); } return; } if (!(text == "destroydamagetype")) { break; } goto IL_0952; case 16: switch (text[0]) { default: return; case 'r': if (text == "ricochetspeedmod") { RicochetSpeedMod = reader.GetSingle(); } return; case 'h': if (text == "hitcheckcooldown") { HitCheckCooldown = reader.GetSingle(); } return; case 'd': break; } if (!(text == "destroyedsoundid")) { break; } goto IL_0a28; case 24: switch (text[0]) { case 'r': if (text == "ricochetspeedanglefactor") { RicochetSpeedAngleFactor = reader.GetSingle(); } break; case 's': if (text == "stopflyingsoundondestroy") { StopFlyingSoundOnDestroy = reader.GetBoolean(); } break; } break; case 22: if (text == "hitignorewallsduration") { HitIgnoreWallsDuration = reader.GetSingle(); } break; case 21: if (text == "ricochetignoreplayers") { RicochetIgnorePlayers = reader.GetBoolean(); } break; case 18: if (!(text == "enableterrainhitfx")) { break; } goto IL_09bf; case 19: case 23: break; IL_084d: HitSize = Math.Max(0f, reader.GetSingle()); break; IL_091e: DamageOwner = reader.GetBoolean(); break; IL_0a28: if (reader.TokenType == JsonTokenType.String) { DestroyedSoundID = AkSoundEngine.GetIDFromString(reader.GetString()); } else { DestroyedSoundID = reader.GetUInt32(); } break; IL_09d9: VisualLerpDist = reader.GetSingle(); break; IL_0471: if (!(text == "trail")) { break; } goto IL_08a9; IL_0482: if (!(text == "range")) { break; } goto IL_09f3; IL_0952: HitDestroyDamageType = reader.GetString().ToDamageTypes(); break; IL_06b1: if (!(text == "flyingsound")) { break; } goto IL_0a00; IL_06a0: if (!(text == "maxlifetime")) { break; } goto IL_09e6; IL_067e: if (!(text == "damageowner")) { break; } goto IL_091e; IL_08a9: EnableTrail = reader.GetBoolean(); break; IL_065c: if (!(text == "destroydelay")) { break; } goto IL_0964; IL_064b: if (!(text == "friendlyfire")) { break; } goto IL_0911; IL_063a: if (!(text == "hitsizeworld")) { break; } goto IL_087b; IL_0460: if (!(text == "accel")) { break; } goto IL_0819; IL_0618: if (!(text == "enableterrainfx")) { break; } goto IL_09bf; IL_09bf: EnableTerrainHitFX = reader.GetBoolean(); break; IL_0607: if (!(text == "hitdestroydelay")) { break; } goto IL_0964; IL_0964: HitDestroyDelay = reader.GetSingle(); break; IL_05f6: if (!(text == "hitfromownerpos")) { break; } goto IL_092b; IL_092b: HitFromOwnerPos = reader.GetBoolean(); break; IL_0819: AccelScale = reader.GetSingle(); break; IL_0864: HitSizeFriendly = Math.Max(0f, reader.GetSingle()); break; IL_0a91: HomingSettings.Deserialize(ref reader); break; IL_08dd: TrailCullOnDie = reader.GetBoolean(); break; IL_0892: ModelScale = Math.Max(0f, reader.GetSingle()); break; IL_07f2: ItemID = EWCJson.Deserialize(ref reader); break; IL_09e6: Lifetime = reader.GetSingle(); break; IL_07ff: MinSpeed = reader.GetSingle(); break; IL_087b: HitSizeWorld = Math.Max(0f, reader.GetSingle()); break; IL_053c: if (!(text == "flyingsoundid")) { break; } goto IL_0a00; IL_0a00: if (reader.TokenType == JsonTokenType.String) { FlyingSoundID = AkSoundEngine.GetIDFromString(reader.GetString()); } else { FlyingSoundID = reader.GetUInt32(); } break; IL_0971: RicochetCount = reader.GetInt32(); break; IL_051a: if (!(text == "ricochetcount")) { break; } goto IL_0971; IL_07c1: ProjectileType = reader.GetString().ToEnum((ProjectileType)9); if ((int)ProjectileType == 4 || (int)ProjectileType == 5) { ProjectileType = (ProjectileType)9; } break; IL_0826: AccelExponent = reader.GetSingle(); break; IL_0911: DamageFriendly = reader.GetBoolean(); break; IL_09f3: MaxRange = reader.GetSingle(); break; } } private static uint CallbackMap(string callback) { return callback switch { "alive" => 0u, "destroyed" => 1u, "timeout" => 2u, _ => 0u, }; } } public sealed class ReserveClip : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { protected override OwnerType RequiredOwnerType => OwnerType.Managed | OwnerType.Player; protected override WeaponType ValidWeaponType => WeaponType.Gun; public void Invoke(WeaponPostStartFireContext context) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (base.CWC.Owner.IsType(OwnerType.Local)) { LocalGunComp localGunComp = (LocalGunComp)base.CGC.Gun; if (localGunComp.TryGetBurstArchetype(out BWA_Burst burstArchetype)) { int val = localGunComp.GetCurrentClip() + PlayerBackpackManager.GetBulletsInPack(localGunComp.AmmoType, base.CWC.Owner.Player.Owner); burstArchetype.m_burstCurrentCount = Math.Min(burstArchetype.m_burstMax, val); } } } public void Invoke(WeaponPostAmmoPackContext context) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) IBulletWeaponComp bulletWeaponComp = (IBulletWeaponComp)base.CGC.Gun; if ((Object)(object)base.CWC.Owner.Player.Inventory.WieldedItem != (Object)(object)bulletWeaponComp.BulletWeapon) { bulletWeaponComp.SetCurrentClip(context.AmmoStorage.GetClipBulletsFromPack(bulletWeaponComp.GetCurrentClip(), bulletWeaponComp.AmmoType)); ((Weapon)bulletWeaponComp.BulletWeapon).m_wasOutOfAmmo = false; } else { base.CWC.Owner.Player.Inventory.DoReload(); } } public void Invoke(WeaponPostFireContext context) { base.CWC.Owner.Player.Inventory.DoReload(); } public void Invoke(WeaponWieldContext context) { base.CWC.Owner.Player.Inventory.DoReload(); } public void Invoke(WeaponPreAmmoUIContext context) { context.Reserve += context.Clip; context.ShowClip = false; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteEndObject(); } } public sealed class Silence : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private readonly Dictionary, float> _alertProgress = new Dictionary, float>(); private static readonly List s_wakeupList = new List(); private static readonly List s_alertList = new List(); private static readonly List s_fakeAlertList = new List(); private static NoiseType s_cachedNoise; private static float s_cachedTimestamp; private static Ray s_ray = new Ray(Vector3.zero, Vector3.forward); private const SearchSetting SearchSettings = SearchSetting.CheckDoors; private const float InstantWakeupProgress = 1000f; private const float InstantWakeupOutput = 1000f; private const float WakeupOutput = 1.1f; private const float AlertOutput = 0.95f; public float FakeAlertRadius { get; private set; } public float AlertRadius { get; private set; } public float AlertAmount { get; private set; } public float WakeUpRadius { get; private set; } public CrossDoorMode CrossDoorMode { get; private set; } private static ObjectWrapper TempWrapper => ObjectWrapper.SharedInstance; protected override WeaponType RequiredWeaponType => WeaponType.Gun; public override bool ValidProperty() { if (!SNet.IsMaster || (Object)(object)base.CWC.Owner.Player == (Object)null || base.CWC.Owner.Player.Owner.IsBot) { return false; } return base.ValidProperty(); } public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponPreFireContext) || contextType == typeof(WeaponPreFireContextSync)) { return base.CWC.Owner.IsType(OwnerType.Player); } if (contextType == typeof(WeaponSetupContext) || contextType == typeof(WeaponClearContext)) { return base.CWC.Owner.IsType(OwnerType.Sentry); } return base.ShouldRegister(contextType); } public void Invoke(WeaponSetupContext context) { ((SentryOwnerComp)base.CWC.Owner).Value.m_noiseTimer = float.MaxValue; } public void Invoke(WeaponClearContext context) { ((SentryOwnerComp)base.CWC.Owner).Value.m_noiseTimer = Clock.Time; } public void Invoke(WeaponPreFireContext context) { //IL_0010: 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) s_cachedNoise = ((Agent)base.CWC.Owner.Player).Noise; s_cachedTimestamp = base.CWC.Owner.Player.m_noiseTimestamp; } public void Invoke(WeaponPreFireContextSync context) { //IL_0010: 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) s_cachedNoise = ((Agent)base.CWC.Owner.Player).Noise; s_cachedTimestamp = base.CWC.Owner.Player.m_noiseTimestamp; } public void Invoke(WeaponPostFireContext context) { OverrideSound(); } public void Invoke(WeaponPostFireContextSync context) { OverrideSound(); } public void Invoke(WeaponStealthUpdateContext context) { TempWrapper.Set((Agent)(object)context.Enemy); if (!_alertProgress.TryGetValue(TempWrapper, out var value)) { return; } if (value >= 1000f) { context.Output = 1000f; _alertProgress.Remove(TempWrapper); return; } if (!context.Detecting) { _alertProgress.Remove(TempWrapper); return; } float num = ((value >= 1f) ? 1.1f : 0.95f); if (num > context.Output) { context.Output = num; } } private void OverrideSound() { //IL_0023: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) if (!SNet.IsMaster) { return; } IOwnerComp owner = base.CWC.Owner; if (owner.IsType(OwnerType.Player)) { ((Agent)owner.Player).m_noise = s_cachedNoise; owner.Player.m_noiseTimestamp = s_cachedTimestamp; } bool flag = AlertRadius > WakeUpRadius; bool flag2 = FakeAlertRadius > AlertRadius && FakeAlertRadius > WakeUpRadius; ((Ray)(ref s_ray)).origin = owner.FirePos; if (flag2) { s_fakeAlertList.Clear(); s_fakeAlertList.AddRange(SearchUtil.GetEnemiesInRange(s_ray, FakeAlertRadius, 180f, owner.CourseNode, SearchSetting.CheckDoors)); } if (flag) { foreach (ObjectWrapper item in _alertProgress.Keys.Where((ObjectWrapper key) => (Object)(object)key.Object == (Object)null || !key.Object.Alive).ToList()) { _alertProgress.Remove(item); } s_alertList.Clear(); s_alertList.AddRange(SearchUtil.GetEnemiesInRange(s_ray, AlertRadius, 180f, owner.CourseNode, SearchSetting.CheckDoors)); } s_wakeupList.Clear(); s_wakeupList.AddRange(SearchUtil.GetEnemiesInRange(s_ray, WakeUpRadius, 180f, owner.CourseNode, SearchSetting.CheckDoors)); for (int num = s_wakeupList.Count - 1; num >= 0; num--) { EnemyAgent val = s_wakeupList[num]; if (flag) { RemoveFromList(val, s_alertList); } if (flag2) { RemoveFromList(val, s_fakeAlertList); } if (EnemyCanHear(val, WakeUpRadius)) { TempWrapper.Set((Agent)(object)val); if (!_alertProgress.ContainsKey(TempWrapper)) { _alertProgress.Add(new ObjectWrapper((Agent)(object)val), 0f); } _alertProgress[TempWrapper] += 1000f; } } for (int num2 = s_alertList.Count - 1; num2 >= 0; num2--) { EnemyAgent val2 = s_alertList[num2]; if (flag2) { RemoveFromList(val2, s_fakeAlertList); } if (EnemyCanHear(val2, AlertRadius)) { TempWrapper.Set((Agent)(object)val2); if (!_alertProgress.ContainsKey(TempWrapper)) { _alertProgress.Add(new ObjectWrapper((Agent)(object)val2), 0f); } EnemyDetection detection = val2.AI.m_detection; if ((int)detection.m_noiseDetectionStatus == 0) { detection.m_statusTimerEnd = 0f; } else if (detection.m_noiseDetectionOn) { _alertProgress[TempWrapper] += AlertAmount; } } } foreach (EnemyAgent s_fakeAlert in s_fakeAlertList) { if (EnemyCanHear(s_fakeAlert, FakeAlertRadius)) { s_fakeAlert.AI.m_locomotion.Hibernate.Heartbeat(0.5f, owner.FirePos); } } } private bool EnemyCanHear(EnemyAgent enemy, float range) { //IL_008d: 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_0098: 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) if (!enemy.ListenerReady) { return false; } IOwnerComp owner = base.CWC.Owner; float num = ((Agent)enemy).CourseNode.m_playerCoverage.GetNodeDistanceToPlayer_Unblocked(owner.Player); float num2 = default(float); if (!enemy.AI.m_detection.GetWeaponDetectionDistance(num, ref num2)) { return false; } if (CrossDoorMode == CrossDoorMode.None && ((Agent)enemy).CourseNode.NodeID != owner.CourseNode.NodeID) { return false; } float weaponDetectionDistanceMax = enemy.EnemyDetectionData.weaponDetectionDistanceMax; if (CrossDoorMode == CrossDoorMode.Normal) { num2 = Math.Max(0f, range - (weaponDetectionDistanceMax - num2)); } Vector3 val = owner.FirePos - enemy.Position; if (((Vector3)(ref val)).sqrMagnitude >= num2 * num2) { return false; } return true; } private void RemoveFromList(EnemyAgent remove, List list) { for (int num = list.Count - 1; num >= 0; num--) { if (((Il2CppObjectBase)remove).Pointer == ((Il2CppObjectBase)list[num]).Pointer) { list.RemoveAt(num); break; } } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("FakeAlertRadius", FakeAlertRadius); writer.WriteNumber("AlertRadius", AlertRadius); writer.WriteNumber("AlertAmount", AlertAmount); writer.WriteNumber("WakeUpRadius", WakeUpRadius); writer.WriteString("CrossDoorMode", CrossDoorMode.ToString()); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); string text = property.ToLowerInvariant(); if (text == null) { return; } switch (text.Length) { default: return; case 9: { char c = text[0]; if (c != 'c') { if (c != 'f' || !(text == "fakealert")) { return; } goto IL_0109; } if (!(text == "crossdoor")) { return; } break; } case 11: switch (text[5]) { default: return; case 'r': break; case 'a': if (text == "alertamount") { AlertAmount = reader.GetSingle(); } return; } if (!(text == "alertradius")) { return; } goto IL_0116; case 15: if (!(text == "fakealertradius")) { return; } goto IL_0109; case 5: if (!(text == "alert")) { return; } goto IL_0116; case 12: if (!(text == "wakeupradius")) { return; } goto IL_0130; case 6: if (!(text == "wakeup")) { return; } goto IL_0130; case 13: if (!(text == "crossdoormode")) { return; } break; case 10: if (!(text == "crossdoors")) { return; } break; case 7: case 8: case 14: return; IL_0130: WakeUpRadius = reader.GetSingle(); return; IL_0109: FakeAlertRadius = reader.GetSingle(); return; IL_0116: AlertRadius = reader.GetSingle(); return; } CrossDoorMode = reader.GetString().ToEnum(CrossDoorMode.Normal); } } public enum CrossDoorMode { Normal, None, NoPenalty } public sealed class ThickBullet : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty { public float HitSize { get; private set; } public float HitSizeFriendly { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; public void Invoke(WeaponSetupContext context) { base.CWC.ShotComponent.ThickBullet = this; } public void Invoke(WeaponClearContext context) { base.CWC.ShotComponent.ThickBullet = null; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("HitSize", HitSize); writer.WriteNumber("HitSizeFriendly", HitSizeFriendly); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property.ToLowerInvariant()) { case "hitsize": case "size": HitSize = reader.GetSingle(); break; case "hitsizefriendly": case "sizefriendly": HitSizeFriendly = reader.GetSingle(); break; } } } public abstract class Trait : WeaponPropertyBase { } public sealed class TumorMulti : Trait, IWeaponProperty, IWeaponProperty { public float TumorDamageMulti { get; private set; } = 1f; public bool BypassCap { get; private set; } public bool OverrideWeakspotMulti { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; public void Invoke(WeaponStatContext context) { Dam_EnemyDamageLimb_Custom val = ((Il2CppObjectBase)context.Damageable).TryCast(); if ((Object)(object)val != (Object)null) { context.AddMod(StatType.Precision, OverrideWeakspotMulti ? (TumorDamageMulti / ((Dam_EnemyDamageLimb)val).m_weakspotDamageMulti) : TumorDamageMulti, StackType.Multiply); context.BypassTumorCap = BypassCap; } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("TumorDamageMulti", TumorDamageMulti); writer.WriteBoolean("BypassCap", BypassCap); writer.WriteBoolean("OverrideWeakspotMulti", OverrideWeakspotMulti); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); string text = property.ToLowerInvariant(); if (text == null) { return; } switch (text.Length) { case 16: if (!(text == "tumordamagemulti")) { return; } goto IL_00ca; case 10: if (!(text == "tumormulti")) { return; } goto IL_00ca; case 5: if (!(text == "multi")) { return; } goto IL_00ca; case 14: if (!(text == "bypasstumorcap")) { return; } goto IL_00d7; case 9: if (!(text == "bypasscap")) { return; } goto IL_00d7; case 21: if (!(text == "overrideweakspotmulti")) { return; } break; case 13: if (!(text == "overridemulti")) { return; } break; case 8: if (!(text == "override")) { return; } break; default: return; IL_00d7: BypassCap = reader.GetBoolean(); return; IL_00ca: TumorDamageMulti = reader.GetSingle(); return; } OverrideWeakspotMulti = reader.GetBoolean(); } } public sealed class WallPierce : Trait, IWeaponProperty, IWeaponProperty, IWeaponProperty { private static readonly Queue s_nodeQueue = new Queue(); public bool RequireOpenPath { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; public void Invoke(WeaponSetupContext context) { base.CWC.ShotComponent.WallPierce = this; } public void Invoke(WeaponClearContext context) { base.CWC.ShotComponent.WallPierce = null; } public bool IsTargetReachable(AIG_CourseNode? source, AIG_CourseNode? target) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Invalid comparison between Unknown and I4 //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Invalid comparison between Unknown and I4 if (source == null || target == null) { return true; } if (source.NodeID == target.NodeID) { return true; } AIG_SearchID.IncrementSearchID(); ushort searchID = AIG_SearchID.SearchID; s_nodeQueue.Enqueue(source); while (s_nodeQueue.Count > 0) { AIG_CourseNode val = s_nodeQueue.Dequeue(); ((AIG_CourseGraphMember)val).m_searchID = searchID; Enumerator enumerator = val.m_portals.GetEnumerator(); while (enumerator.MoveNext()) { AIG_CoursePortal current = enumerator.Current; iLG_Door_Core val2 = current.m_door; if (!RequireOpenPath && val2 != null && (int)val2.DoorType != 2 && (int)val2.DoorType != 3) { val2 = null; } if (val2 != null && (int)val2.LastStatus != 10 && (int)val2.LastStatus != 16 && (int)val2.LastStatus != 11) { continue; } AIG_CourseNode oppositeNode = current.GetOppositeNode(val); if (((AIG_CourseGraphMember)oppositeNode).m_searchID != searchID) { if (oppositeNode.NodeID == target.NodeID) { s_nodeQueue.Clear(); return true; } s_nodeQueue.Enqueue(oppositeNode); } } } s_nodeQueue.Clear(); return false; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteBoolean("RequireOpenPath", RequireOpenPath); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "requireopenpath") { RequireOpenPath = reader.GetBoolean(); } } } } namespace EWC.CustomWeapon.Properties.Traits.CustomProjectile { public sealed class ProjectileDirChange { public class State { public readonly ProjectileDirChange Settings; private readonly float _startTime; private readonly float _x; private readonly float _y; private readonly Vector3 _right; private readonly Vector3 _up; private bool _isDone; private float _lastX; private float _lastY; public State(Vector3 dir, ushort shotIndex, ProjectileDirChange settings) { //IL_0062: 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_0074: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_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_0098: 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_009e: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) _startTime = Time.time; Settings = settings; _x = settings.Offsets[shotIndex * 2 % settings.Offsets.Length]; _y = settings.Offsets[(shotIndex * 2 + 1) % settings.Offsets.Length]; _lastX = 0f; _lastY = 0f; Vector3 val = ((Math.Abs(dir.y) < 0.99f) ? Vector3.up : Vector3.forward); Vector3 val2 = Vector3.Cross(val, dir); _right = ((Vector3)(ref val2)).normalized; val2 = Vector3.Cross(_right, dir); _up = ((Vector3)(ref val2)).normalized; } public void Update(ref Vector3 dir) { //IL_00a3: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (_isDone) { return; } float num = Time.time - _startTime - Settings.Delay; if (!(num < 0f)) { float num2 = ((Settings.ChangeTime > 0f) ? ((float)Math.Pow(Math.Min(num / Settings.ChangeTime, 1f), Settings.Exponent)) : 1f); float num3 = _x * num2; float num4 = _y * num2; float num5 = num3 - _lastX; float num6 = num4 - _lastY; if (num5 != 0f) { dir = Quaternion.AngleAxis(0f - num5, _up) * dir; } if (num6 != 0f) { dir = Quaternion.AngleAxis(0f - num6, _right) * dir; } _lastX = num3; _lastY = num4; if (num2 == 1f) { _isDone = true; } } } public void Copy(State state) { _lastX = state._lastX; _lastY = state._lastY; _isDone = state._isDone; } } public float[] Offsets { get; private set; } = Array.Empty(); public float Exponent { get; private set; } = 1f; public float Delay { get; private set; } public float ChangeTime { get; private set; } public State CreateState(Vector3 dir, ushort shotIndex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return new State(dir, shotIndex, this); } public void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); EWCJson.Serialize(writer, "Offsets", Offsets); writer.WriteNumber("Exponent", Exponent); writer.WriteNumber("Delay", Delay); writer.WriteNumber("ChangeTime", ChangeTime); writer.WriteEndObject(); } public static void SerializeList(List moveChanges, Utf8JsonWriter writer) { writer.WriteStartArray(); foreach (ProjectileDirChange moveChange in moveChanges) { moveChange.Serialize(writer); } writer.WriteEndArray(); } private void DeserializeProperty(string propertyName, ref Utf8JsonReader reader) { if (propertyName == null) { return; } switch (propertyName.Length) { default: return; case 8: switch (propertyName[0]) { default: return; case 'e': if (propertyName == "exponent") { Exponent = reader.GetSingle(); } return; case 'd': break; } if (!(propertyName == "duration")) { return; } break; case 7: if (!(propertyName == "offsets")) { return; } goto IL_00a7; case 6: if (!(propertyName == "offset")) { return; } goto IL_00a7; case 5: if (propertyName == "delay") { Delay = reader.GetSingle(); } return; case 10: if (!(propertyName == "changetime")) { return; } break; case 4: if (!(propertyName == "time")) { return; } break; case 9: return; IL_00a7: Offsets = JsonUtil.ReadPairs(ref reader); return; } ChangeTime = reader.GetSingle(); } public void Deserialize(ref Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartObject) { throw new Exception("Expected StartObject token"); } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); DeserializeProperty(@string.ToLowerInvariant().Replace(" ", ""), ref reader); } throw new JsonException("Expected EndObject token"); } public static List DeserializeList(ref Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartArray) { throw new Exception("Expected StartArray token"); } List list = new List(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndArray) { return list; } ProjectileDirChange projectileDirChange = new ProjectileDirChange(); projectileDirChange.Deserialize(ref reader); list.Add(projectileDirChange); } throw new JsonException("Expected EndArray token"); } } public sealed class ProjectileHomingSettings { public bool UseSteadyStrength { get; private set; } public float InitialHomingStrength { get; private set; } public float InitialHomingDuration { get; private set; } public float HomingStrength { get; private set; } public float HomingDelay { get; private set; } public float HomingMaxDist { get; private set; } = 50f; public float HomingMinDist { get; private set; } = 15f; public float HomingDistExponent { get; private set; } = 2f; public TargetingMode TargetMode { get; private set; } public TargetingPriority TargetPriority { get; private set; } public float SearchAngle { get; private set; } public float SearchRange { get; private set; } = 50f; public float SearchCooldown { get; private set; } = 0.1f; public SearchMode SearchInitialMode { get; private set; } public StopSearchMode SearchStopMode { get; private set; } public bool SearchStayOnTarget { get; private set; } public bool SearchIgnoreWalls { get; private set; } public bool SearchIgnoreInvisibility { get; private set; } public bool SearchTagOnly { get; private set; } public bool HomingEnabled { get { if (!(HomingStrength > 0f)) { return InitialHomingStrength > 0f; } return true; } } public void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteBoolean("UseSteadyStrength", UseSteadyStrength); writer.WriteNumber("InitialHomingStrength", InitialHomingStrength); writer.WriteNumber("InitialHomingDuration", InitialHomingDuration); writer.WriteNumber("HomingStrength", HomingStrength); writer.WriteNumber("HomingDelay", HomingDelay); writer.WriteNumber("HomingMaxDist", HomingMaxDist); writer.WriteNumber("HomingMinDist", HomingMinDist); writer.WriteNumber("HomingDistExponent", HomingDistExponent); writer.WriteString("TargetMode", TargetMode.ToString()); writer.WriteString("TargetPriority", TargetPriority.ToString()); writer.WriteNumber("SearchAngle", SearchAngle); writer.WriteNumber("SearchRange", SearchRange); writer.WriteNumber("SearchCooldown", SearchCooldown); writer.WriteString("SearchInitialMode", SearchInitialMode.ToString()); writer.WriteString("SearchStopMode", SearchStopMode.ToString()); writer.WriteBoolean("SearchStayOnTarget", SearchStayOnTarget); writer.WriteBoolean("SearchIgnoreWalls", SearchIgnoreWalls); writer.WriteBoolean("SearchIgnoreInvisibility", SearchIgnoreInvisibility); writer.WriteBoolean("SearchTagOnly", SearchTagOnly); writer.WriteEndObject(); } private void DeserializeProperty(string propertyName, ref Utf8JsonReader reader) { if (propertyName == null) { return; } switch (propertyName.Length) { default: return; case 17: { char c = propertyName[12]; if ((uint)c <= 105u) { if (c != 'e') { if (c != 'i' || !(propertyName == "searchignoreinvis")) { return; } goto IL_0594; } if (!(propertyName == "usesteadystrength")) { return; } goto IL_04a0; } if (c != 'l') { if (c != 'o') { if (c != 'w' || !(propertyName == "searchignorewalls")) { return; } goto IL_0587; } if (!(propertyName == "targetingpriority")) { return; } goto IL_051b; } if (!(propertyName == "searchinitialmode")) { return; } goto IL_0555; } case 14: { char c = propertyName[1]; if ((uint)c <= 101u) { if (c != 'a') { if (c != 'e') { return; } if (propertyName == "searchcooldown") { goto IL_0548; } if (!(propertyName == "searchstopmode")) { return; } goto IL_0568; } if (!(propertyName == "targetpriority")) { return; } goto IL_051b; } if (c != 'o') { if (c != 't' || !(propertyName == "steadystrength")) { return; } goto IL_04a0; } if (!(propertyName == "homingstrength")) { return; } goto IL_04c7; } case 21: { char c = propertyName[13]; if (c != 'd') { if (c != 's' || !(propertyName == "initialhomingstrength")) { return; } goto IL_04ad; } if (!(propertyName == "initialhomingduration")) { return; } goto IL_04ba; } case 15: { char c = propertyName[7]; if (c != 'd') { if (c != 's' || !(propertyName == "initialstrength")) { return; } goto IL_04ad; } if (!(propertyName == "initialduration")) { return; } goto IL_04ba; } case 8: { char c = propertyName[3]; if (c != 'e') { if (c != 'l') { if (c != 'p' || !(propertyName == "stopmode")) { return; } goto IL_0568; } if (!(propertyName == "cooldown")) { return; } goto IL_0548; } if (!(propertyName == "strength")) { return; } goto IL_04c7; } case 11: { char c = propertyName[6]; if ((uint)c <= 105u) { if (c != 'a') { if (c != 'd') { if (c != 'i' || !(propertyName == "ignoreinvis")) { return; } goto IL_0594; } if (!(propertyName == "homingdelay")) { return; } goto IL_04d4; } if (!(propertyName == "searchangle")) { return; } goto IL_052e; } if (c != 'l') { if (c != 'r') { if (c != 'w' || !(propertyName == "ignorewalls")) { return; } goto IL_0587; } if (!(propertyName == "searchrange")) { return; } goto IL_053b; } if (!(propertyName == "initialmode")) { return; } goto IL_0555; } case 5: { char c = propertyName[0]; if (c != 'a') { if (c != 'd') { if (c != 'r' || !(propertyName == "range")) { return; } goto IL_053b; } if (!(propertyName == "delay")) { return; } goto IL_04d4; } if (!(propertyName == "angle")) { return; } goto IL_052e; } case 13: { char c = propertyName[0]; if (c != 'h') { if (c != 's') { if (c != 't' || !(propertyName == "targetingmode")) { return; } goto IL_0508; } if (!(propertyName == "searchtagonly")) { return; } break; } if (propertyName == "homingmaxdist") { goto IL_04e1; } if (!(propertyName == "homingmindist")) { return; } goto IL_04ee; } case 7: { char c = propertyName[2]; if (c != 'g') { if (c != 'n') { if (c != 'x' || !(propertyName == "maxdist")) { return; } goto IL_04e1; } if (!(propertyName == "mindist")) { return; } goto IL_04ee; } if (!(propertyName == "tagonly")) { return; } break; } case 18: { char c = propertyName[0]; if (c != 'h') { if (c != 'i') { if (c != 's' || !(propertyName == "searchstayontarget")) { return; } goto IL_057a; } if (!(propertyName == "ignoreinvisibility")) { return; } goto IL_0594; } if (!(propertyName == "homingdistexponent")) { return; } goto IL_04fb; } case 12: { char c = propertyName[0]; if (c != 'd') { if (c != 's' || !(propertyName == "stayontarget")) { return; } goto IL_057a; } if (!(propertyName == "distexponent")) { return; } goto IL_04fb; } case 10: if (!(propertyName == "targetmode")) { return; } goto IL_0508; case 24: if (!(propertyName == "searchignoreinvisibility")) { return; } goto IL_0594; case 6: case 9: case 16: case 19: case 20: case 22: case 23: return; IL_053b: SearchRange = reader.GetSingle(); return; IL_051b: TargetPriority = reader.GetString().ToEnum(TargetingPriority.Angle); return; IL_04ba: InitialHomingDuration = reader.GetSingle(); return; IL_057a: SearchStayOnTarget = reader.GetBoolean(); return; IL_04a0: UseSteadyStrength = reader.GetBoolean(); return; IL_04fb: HomingDistExponent = reader.GetSingle(); return; IL_0587: SearchIgnoreWalls = reader.GetBoolean(); return; IL_0548: SearchCooldown = reader.GetSingle(); return; IL_04d4: HomingDelay = reader.GetSingle(); return; IL_0568: SearchStopMode = ToStopSearchMode(reader.GetString()); return; IL_052e: SearchAngle = reader.GetSingle(); return; IL_0594: SearchIgnoreInvisibility = reader.GetBoolean(); return; IL_0508: TargetMode = reader.GetString().ToEnum(TargetingMode.Normal); return; IL_0555: SearchInitialMode = reader.GetString().ToEnum(SearchMode.Normal); return; IL_04c7: HomingStrength = reader.GetSingle(); return; IL_04ad: InitialHomingStrength = reader.GetSingle(); return; IL_04ee: HomingMinDist = reader.GetSingle(); return; IL_04e1: HomingMaxDist = reader.GetSingle(); return; } SearchTagOnly = reader.GetBoolean(); } public void Deserialize(ref Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartObject) { throw new Exception("Expected StartObject token"); } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); DeserializeProperty(@string.ToLowerInvariant().Replace(" ", ""), ref reader); } throw new JsonException("Expected EndObject token"); } private static StopSearchMode ToStopSearchMode(string value) { value = value.Replace(" ", null).ToLower(); StopSearchMode stopSearchMode = StopSearchMode.None; if (value.Contains("pierce")) { stopSearchMode |= StopSearchMode.Pierce; } if (value.Contains("dead")) { stopSearchMode |= StopSearchMode.Dead; } if (value.Contains("invalid") || value.Contains("novalid")) { stopSearchMode |= StopSearchMode.Invalid; } return stopSearchMode; } } public enum SearchMode { Normal = 0, AimDir = 1, AimDirection = 1, AutoAim = 2 } [Flags] public enum StopSearchMode { None = 0, Pierce = 1, Dead = 2, Invalid = 4, NoValid = 4 } public sealed class ProjectileStatChange { public float EndFrac { get; private set; } = 1f; public float Exponent { get; private set; } = 1f; public StatType StatType { get; private set; } public float Delay { get; private set; } public float ChangeTime { get; private set; } public void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteNumber("EndFrac", EndFrac); writer.WriteNumber("Exponent", Exponent); writer.WriteString("StatType", StatType.ToString()); writer.WriteNumber("Delay", Delay); writer.WriteNumber("ChangeTime", ChangeTime); writer.WriteEndObject(); } public static void SerializeList(List statChanges, Utf8JsonWriter writer) { writer.WriteStartArray(); foreach (ProjectileStatChange statChange in statChanges) { statChange.Serialize(writer); } writer.WriteEndArray(); } private void DeserializeProperty(string propertyName, ref Utf8JsonReader reader) { if (propertyName == null) { return; } switch (propertyName.Length) { default: return; case 4: { char c = propertyName[0]; if (c != 'f') { if (c != 's') { if (c != 't' || !(propertyName == "time")) { return; } break; } if (!(propertyName == "stat")) { return; } goto IL_0115; } if (!(propertyName == "frac")) { return; } goto IL_00fb; } case 8: { char c = propertyName[0]; if (c != 'd') { switch (c) { default: return; case 'e': if (propertyName == "exponent") { Exponent = reader.GetSingle(); } return; case 's': break; } if (!(propertyName == "stattype")) { return; } goto IL_0115; } if (!(propertyName == "duration")) { return; } break; } case 7: if (!(propertyName == "endfrac")) { return; } goto IL_00fb; case 3: if (!(propertyName == "mod")) { return; } goto IL_00fb; case 5: if (propertyName == "delay") { Delay = reader.GetSingle(); } return; case 10: if (!(propertyName == "changetime")) { return; } break; case 6: case 9: return; IL_00fb: EndFrac = reader.GetSingle(); return; IL_0115: StatType = reader.GetString().ToEnum(StatType.Damage); return; } ChangeTime = reader.GetSingle(); } public void Deserialize(ref Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartObject) { throw new Exception("Expected StartObject token"); } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); DeserializeProperty(@string.ToLowerInvariant().Replace(" ", ""), ref reader); } throw new JsonException("Expected EndObject token"); } public static List DeserializeList(ref Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartArray) { throw new Exception("Expected StartArray token"); } List list = new List(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndArray) { return list; } ProjectileStatChange projectileStatChange = new ProjectileStatChange(); projectileStatChange.Deserialize(ref reader); list.Add(projectileStatChange); } throw new JsonException("Expected EndArray token"); } } } namespace EWC.CustomWeapon.Properties.Traits.CustomProjectile.Managers { public static class EWCProjectileManager { internal static readonly Dictionary> PlayerProjectiles = new Dictionary>(); private static readonly Dictionary> _cachedTargets = new Dictionary>(); public static readonly EWCProjectileManagerShooter Shooter = new EWCProjectileManagerShooter(); private static readonly EWCProjectileSyncDestroy _destroySync = new EWCProjectileSyncDestroy(); private static readonly EWCProjectileSyncTarget _targetSync = new EWCProjectileSyncTarget(); private static readonly EWCProjectileSyncBounce _bounceSync = new EWCProjectileSyncBounce(); [InvokeOnAssetLoad] private static void Init() { _destroySync.Setup(); _targetSync.Setup(); _bounceSync.Setup(); } [InvokeOnCleanup(true)] private static void Reset() { Shooter.Reset(); _cachedTargets.Clear(); PlayerProjectiles.Clear(); } internal static ushort GetNextID(ushort playerIndex) { if (!PlayerProjectiles.TryGetValue(playerIndex, out LinkedList<(ushort, EWCProjectileComponentBase)> value) || value.Count == 0) { return 0; } return (ushort)(value.Last.Value.Item1 + 1); } internal static bool TryGetNode(ushort playerIndex, ushort id, [MaybeNullWhen(false)] out LinkedListNode<(ushort id, EWCProjectileComponentBase comp)> node) { node = null; if (!PlayerProjectiles.TryGetValue(playerIndex, out LinkedList<(ushort, EWCProjectileComponentBase)> value)) { return false; } node = value.First; while (node != null && node.Value.id != id) { node = node.Next; } return node != null; } internal static void TryPullCachedTarget(ushort playerIndex, ushort id) { if (_cachedTargets.TryGetValue(playerIndex, out LinkedList<(ushort, EnemyAgent, byte)> value)) { LinkedListNode<(ushort, EnemyAgent, byte)> linkedListNode = value.First; while (linkedListNode != null && linkedListNode.Value.Item1 != id) { linkedListNode = linkedListNode.Next; } if (linkedListNode != null) { value.Remove(linkedListNode); Internal_ReceiveProjectileTarget(playerIndex, id, linkedListNode.Value.Item2, linkedListNode.Value.Item3); } } } internal static void AddProjectile(ushort playerIndex, ushort id, EWCProjectileComponentBase comp) { if (!PlayerProjectiles.TryGetValue(playerIndex, out LinkedList<(ushort, EWCProjectileComponentBase)> value)) { value = (PlayerProjectiles[playerIndex] = new LinkedList<(ushort, EWCProjectileComponentBase)>()); } value.AddLast((id, comp)); } public static void DoProjectileDestroy(ushort playerIndex, ushort id, bool isLocal) { if (isLocal) { ProjectileDataDestroy projectileDataDestroy = default(ProjectileDataDestroy); projectileDataDestroy.playerIndex = playerIndex; projectileDataDestroy.id = id; ProjectileDataDestroy packetData = projectileDataDestroy; _destroySync.Send(packetData, null, (SNet_ChannelType)4); } if (TryGetNode(playerIndex, id, out LinkedListNode<(ushort, EWCProjectileComponentBase)> node)) { PlayerProjectiles[playerIndex].Remove(node); } } internal static void Internal_ReceiveProjectileDestroy(ushort playerIndex, ushort id) { if (TryGetNode(playerIndex, id, out LinkedListNode<(ushort, EWCProjectileComponentBase)> node)) { node.Value.Item2.Die(); } } public static void DoProjectileTarget(ushort playerIndex, ushort id, EnemyAgent? target, byte limbID) { ProjectileDataTarget projectileDataTarget = default(ProjectileDataTarget); projectileDataTarget.playerIndex = playerIndex; projectileDataTarget.id = id; projectileDataTarget.limbID = limbID; ProjectileDataTarget packetData = projectileDataTarget; ((pEnemyAgent)(ref packetData.target)).Set(target); _targetSync.Send(packetData, null, (SNet_ChannelType)4); } internal static void Internal_ReceiveProjectileTarget(ushort playerIndex, ushort id, EnemyAgent? enemy, byte limbID) { if (!TryGetNode(playerIndex, id, out LinkedListNode<(ushort, EWCProjectileComponentBase)> node)) { if (!_cachedTargets.TryGetValue(playerIndex, out LinkedList<(ushort, EnemyAgent, byte)> value)) { _cachedTargets.TryAdd(playerIndex, value = new LinkedList<(ushort, EnemyAgent, byte)>()); } value.AddLast((id, enemy, limbID)); } else { node.Value.Item2.Homing.ReceiveHomingAgent(enemy, limbID); } } public static void DoProjectileBounce(ushort playerIndex, ushort id, Vector3 pos, Vector3 baseVel) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) ProjectileDataBounce projectileDataBounce = default(ProjectileDataBounce); projectileDataBounce.playerIndex = playerIndex; projectileDataBounce.id = id; projectileDataBounce.position = pos; projectileDataBounce.baseVelocity = baseVel; ProjectileDataBounce packetData = projectileDataBounce; _bounceSync.Send(packetData, null, (SNet_ChannelType)4); } internal static void Internal_ReceiveProjectileBounce(ushort playerIndex, ushort id, Vector3 pos, Vector3 baseVel) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (TryGetNode(playerIndex, id, out LinkedListNode<(ushort, EWCProjectileComponentBase)> node)) { node.Value.Item2.ReceivePosition(pos, baseVel); } } } public struct ProjectileDataDestroy { public ushort playerIndex; public ushort id; } public struct ProjectileDataTarget { public ushort playerIndex; public ushort id; public pEnemyAgent target; public byte limbID; } public struct ProjectileDataBounce { public ushort playerIndex; public ushort id; public Vector3 position; public Vector3 baseVelocity; } public class EWCProjectileManagerShooter { private readonly Dictionary> _pools = new Dictionary>(); private static readonly EWCProjectileSyncShooter s_shooterSync = new EWCProjectileSyncShooter(); [InvokeOnAssetLoad] private static void Init() { s_shooterSync.Setup(); } public void Reset() { foreach (Queue value in _pools.Values) { foreach (EWCProjectileComponentShooter item in value) { Object.Destroy((Object)(object)((Component)item).gameObject); } } _pools.Clear(); } public void ReturnToPool(EWCProjectileComponentShooter projectile) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _pools[projectile.Type].Enqueue(projectile); } public EWCProjectileComponentShooter GetFromPool(ProjectileType type) { //IL_0006: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!_pools.ContainsKey(type)) { _pools.Add(type, new Queue()); } if (_pools[type].TryDequeue(out EWCProjectileComponentShooter result)) { return result; } result = ProjectileManager.SpawnProjectileType(type, Vector3.zero, Quaternion.identity).AddComponent(); result.Type = type; return result; } public EWCProjectileComponentShooter CreateAndSendProjectile(Projectile projBase, ushort shotIndex, Vector3 position, Vector3 fxPos, HitData hitData, IntPtr ignoreEnt = default(IntPtr)) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_0076: 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_0095: 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_00bb: Unknown result type (might be due to invalid IL or missing references) PlayerAgent? player = projBase.CWC.Owner.Player; ushort playerIndex = (ushort)((player != null) ? ((uint)player.PlayerSlotIndex) : 0u); ProjectileDataShooter projectileDataShooter = default(ProjectileDataShooter); projectileDataShooter.playerIndex = playerIndex; projectileDataShooter.shotIndex = shotIndex; projectileDataShooter.id = EWCProjectileManager.GetNextID(playerIndex); projectileDataShooter.propertyID = projBase.SyncPropertyID; projectileDataShooter.position = position; ProjectileDataShooter packetData = projectileDataShooter; packetData.dir.Value = hitData.fireDir; packetData.localFXPos.Set(fxPos - position, 10f); s_shooterSync.Send(packetData, null, (SNet_ChannelType)4); EWCProjectileComponentShooter fromPool = GetFromPool(projBase.ProjectileType); EWCProjectileManager.AddProjectile(playerIndex, packetData.id, fromPool); fromPool.Init(playerIndex, shotIndex, packetData.id, projBase, isLocal: true, position, hitData.fireDir, hitData, ignoreEnt); return fromPool; } internal void Internal_ReceiveProjectile(ushort index, ushort shotIndex, ushort id, Projectile projBase, Vector3 position, Vector3 fxPos, Vector3 dir) { //IL_0003: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) EWCProjectileComponentShooter fromPool = GetFromPool(projBase.ProjectileType); EWCProjectileManager.AddProjectile(index, id, fromPool); fromPool.Init(index, shotIndex, id, projBase, isLocal: false, position, dir, null, (IntPtr)0); if (projBase.VisualLerpDist > 0f && fxPos != Vector3.zero) { fromPool.SetVisualPosition(fxPos, projBase.VisualLerpDist); } EWCProjectileManager.TryPullCachedTarget(index, id); } } public struct ProjectileDataShooter { public ushort playerIndex; public ushort shotIndex; public ushort id; public ushort propertyID; public Vector3 position; public Vector3_32b localFXPos; public Vector3_24b_Normalized dir; } internal sealed class EWCProjectileSyncDestroy : SyncedEvent { public override string GUID => "PROJDST"; protected override void Receive(ProjectileDataDestroy packet) { EWCProjectileManager.Internal_ReceiveProjectileDestroy(packet.playerIndex, packet.id); } } internal sealed class EWCProjectileSyncTarget : SyncedEvent { public override string GUID => "PROJTGT"; protected override void Receive(ProjectileDataTarget packet) { EnemyAgent enemy = default(EnemyAgent); if (!((pEnemyAgent)(ref packet.target)).TryGet(ref enemy)) { enemy = null; } EWCProjectileManager.Internal_ReceiveProjectileTarget(packet.playerIndex, packet.id, enemy, packet.limbID); } } internal sealed class EWCProjectileSyncBounce : SyncedEvent { public override string GUID => "PROJBNC"; protected override void Receive(ProjectileDataBounce packet) { //IL_000d: 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) EWCProjectileManager.Internal_ReceiveProjectileBounce(packet.playerIndex, packet.id, packet.position, packet.baseVelocity); } } internal sealed class EWCProjectileSyncShooter : SyncedEvent { public override string GUID => "PROJSHT"; protected override void Receive(ProjectileDataShooter packet) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (CustomDataManager.TryGetSyncProperty(packet.propertyID, out var property)) { EWCProjectileManager.Shooter.Internal_ReceiveProjectile(packet.playerIndex, packet.shotIndex, packet.id, property, packet.position, packet.position + packet.localFXPos.Get(10f), packet.dir.Value); } } } } namespace EWC.CustomWeapon.Properties.Traits.CustomProjectile.Components { public abstract class EWCProjectileComponentBase : MonoBehaviour { private class PhysicsInfo { public Projectile Settings; private Vector3 _baseDir; public float BaseSpeed; public Vector3 BaseVelocity; private Vector3 _dir; public Vector3 Position; public Vector3 Velocity; public float AccelProgress; public float GravityVel; public readonly List DirChanges = new List(); public Vector3 BaseDir { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _baseDir; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0030: 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) _baseDir = value; BaseVelocity = _baseDir * Speed; GravityVel = 0f; Velocity = BaseVelocity; Dir = ((Vector3)(ref Velocity)).normalized; } } public float Speed { get { if (Settings.AccelScale != 1f) { return BaseSpeed * Math.Pow(AccelProgress, Settings.AccelExponent).Lerp(1f, Settings.AccelScale); } return BaseSpeed; } } public Vector3 Dir { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _dir; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) _dir = ((value == Vector3.zero) ? _baseDir : value); } } public void Set(Projectile settings, Vector3 position, Vector3 dir, ushort shotIndex) { //IL_0046: 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_0079: 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) Settings = settings; DirChanges.Clear(); DirChanges.EnsureCapacity(settings.DirChanges.Count); foreach (ProjectileDirChange dirChange in settings.DirChanges) { DirChanges.Add(dirChange.CreateState(dir, shotIndex)); } AccelProgress = 0f; Position = position; BaseSpeed = ((settings.MaxSpeed > settings.MinSpeed) ? Random.NextSingle().Lerp(settings.MinSpeed, settings.MaxSpeed) : settings.MinSpeed); BaseDir = dir; } public void Copy(PhysicsInfo info) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0065: 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_0089: 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_0095: 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) Settings = info.Settings; for (int i = 0; i < DirChanges.Count; i++) { DirChanges[i].Copy(info.DirChanges[i]); } AccelProgress = info.AccelProgress; Position = info.Position; _dir = info._dir; Velocity = info.Velocity; GravityVel = info.GravityVel; BaseSpeed = info.BaseSpeed; BaseVelocity = info.BaseVelocity; _baseDir = info._baseDir; } } private static readonly Random Random = new Random(); public readonly EWCProjectileHitbox Hitbox; public readonly EWCProjectileHoming Homing; private static ContextController? s_currentController; private static float s_lastControllerTime = 0f; private static ushort s_lastControllerIndex = 0; private readonly DelayedCallback _inactiveCallback; private float _startLifetime; private float _endLifetime; private bool _playingEndSound; protected float _inactiveLifetime; private readonly PhysicsInfo _fixedInfo = new PhysicsInfo(); private readonly PhysicsInfo _deltaInfo = new PhysicsInfo(); private float _lastUpdatePhysicsTime; private int _maxRicochetCheck; private float _lerpProgress; private float _lerpTime; private Vector3 _positionVisualDiff; protected Vector3 _positionVisual; protected Vector3 _dirVisual; private float _aliveTriggerTime; protected static Quaternion s_tempRot; private const int MinRicochetCheck = 5; private const float DefaultPhysicsInterval = 0.05f; private const float PhysicsIntervalDelayUntilMax = 1f; [HideFromIl2Cpp] public Projectile Settings { get; private set; } [HideFromIl2Cpp] public ContextController ContextController { get; private set; } public Vector3 Position => _deltaInfo.Position; public Vector3 Dir => _deltaInfo.Dir; public Vector3 Velocity => _deltaInfo.Velocity; public bool IsManaged { get; private set; } public ushort SyncID { get; private set; } public ushort ShotIndex { get; private set; } public ushort PlayerIndex { get; private set; } protected virtual CellSoundPlayer SoundPlayer { get { throw new NotImplementedException("Base projectile component SoundPlayer called - child class should override!"); } } public EWCProjectileComponentBase(IntPtr ptr) : base(ptr) { Hitbox = new EWCProjectileHitbox(this); Homing = new EWCProjectileHoming(this); _inactiveCallback = new DelayedCallback(() => _inactiveLifetime, Cleanup); } [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } protected virtual void Awake() { ((Behaviour)this).enabled = false; } [HideFromIl2Cpp] public virtual void Init(ushort playerIndex, ushort shotIndex, ushort ID, Projectile projBase, bool isManaged, Vector3 position, Vector3 dir, HitData? hitData = null, IntPtr ignoreEnt = default(IntPtr)) { //IL_0043: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) if (((Behaviour)this).enabled) { return; } _inactiveCallback.Cancel(); _playingEndSound = false; SyncID = ID; PlayerIndex = playerIndex; ShotIndex = shotIndex; Settings = projBase; ((Component)this).gameObject.transform.localScale = Vector3.one * projBase.ModelScale; ((Quaternion)(ref s_tempRot)).SetLookRotation(dir); ((Component)this).gameObject.transform.SetPositionAndRotation(position, s_tempRot); ((Component)this).gameObject.active = true; ((Behaviour)this).enabled = true; _startLifetime = Time.time; _endLifetime = _startLifetime + projBase.Lifetime; _lastUpdatePhysicsTime = _startLifetime; _maxRicochetCheck = (int)Math.Ceiling(5f * Math.Max(0.05f, Settings.HitCheckCooldown) / 0.05f); _lerpProgress = 1f; _fixedInfo.Set(projBase, position, dir, shotIndex); _deltaInfo.Set(projBase, position, dir, shotIndex); _aliveTriggerTime = _startLifetime + Settings.AliveTriggerDelay; IsManaged = isManaged; ProjectileAPI.FireProjectileSpawnedCallback(this); if (Settings.FlyingSoundID != 0) { SoundPlayer.Post(Settings.FlyingSoundID, Position); } if (isManaged) { CustomWeaponComponent cWC = projBase.CWC; if (cWC.HasTempProperties()) { if (s_lastControllerTime != Clock.Time || playerIndex != s_lastControllerIndex) { s_currentController = new ContextController(cWC.GetContextController()); s_lastControllerTime = Clock.Time; s_lastControllerIndex = playerIndex; } ContextController = s_currentController; } else { ContextController = cWC.GetContextController(); } } Hitbox.Init(projBase, position, dir, hitData, ignoreEnt, out var bounceHit); if (bounceHit.HasValue) { PhysicsInfo fixedInfo = _fixedInfo; Vector3 baseDir = _fixedInfo.BaseDir; RaycastHit value = bounceHit.Value; fixedInfo.BaseDir = Vector3.Reflect(baseDir, ((RaycastHit)(ref value)).normal); _deltaInfo.Copy(_fixedInfo); } Homing.Init(projBase, position, _fixedInfo.BaseDir); } public virtual void SetVisualPosition(Vector3 positionVisual, float lerpDist) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0079: 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_0083: 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_009a: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref _deltaInfo.BaseVelocity)).sqrMagnitude != 0f) { _lerpProgress = 0f; _lerpTime = lerpDist / ((Vector3)(ref _deltaInfo.BaseVelocity)).magnitude; _positionVisual = positionVisual; if (_lerpTime < 1E-06f) { _dirVisual = _deltaInfo.Dir; _lerpProgress = 1f; return; } _positionVisualDiff = _positionVisual - _deltaInfo.Position; _dirVisual = _deltaInfo.Position + _deltaInfo.BaseVelocity * _lerpTime - _positionVisual; ((Quaternion)(ref s_tempRot)).SetLookRotation(_dirVisual); ((Component)this).gameObject.transform.SetPositionAndRotation(_positionVisual, s_tempRot); SoundPlayer.UpdatePosition(_positionVisual); } } public void ReceivePosition(Vector3 pos, Vector3 baseVelocity) { //IL_0006: 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_0026: Unknown result type (might be due to invalid IL or missing references) _deltaInfo.Position = pos; _deltaInfo.BaseSpeed = ((Vector3)(ref baseVelocity)).magnitude; _deltaInfo.BaseDir = ((Vector3)(ref baseVelocity)).normalized; } private void LerpVisualOffset() { //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_008c: 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_009d: 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) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0025: 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) if (_lerpProgress == 1f) { _positionVisual = _deltaInfo.Position; _dirVisual = Dir; ((Quaternion)(ref s_tempRot)).SetLookRotation(_dirVisual); return; } _lerpProgress = Math.Min(1f, _lerpProgress + Time.deltaTime / _lerpTime); float num = 1f - (1f - _lerpProgress) * (1f - _lerpProgress); Vector3 positionVisual = _positionVisual; _positionVisual = _deltaInfo.Position + Vector3.Lerp(_positionVisualDiff, Vector3.zero, num); Vector3 val = _positionVisual - positionVisual; _dirVisual = ((Vector3)(ref val)).normalized; ((Quaternion)(ref s_tempRot)).SetLookRotation(_dirVisual); } private bool UpdatePhysics() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) if (!IsManaged) { return false; } float time = Time.time; float num = ((!(time > _startLifetime + 1f)) ? ((time - _startLifetime) / 1f * Settings.HitCheckCooldown) : Settings.HitCheckCooldown); if (_lastUpdatePhysicsTime + num >= time) { return false; } float num2 = time - _lastUpdatePhysicsTime; Vector3 dir = _fixedInfo.Dir; Homing.Update(_fixedInfo.Position, num2, ref dir); foreach (ProjectileDirChange.State dirChange in _fixedInfo.DirChanges) { dirChange.Update(ref dir); } if (dir != _fixedInfo.Dir) { _fixedInfo.BaseDir = dir; } Vector3 val = GetDeltaMove(_fixedInfo, num2); Vector3 velocityDelta = ((((Vector3)(ref val)).sqrMagnitude > 0.0025000002f) ? val : (_fixedInfo.Dir * 0.05f)); bool flag = false; for (int i = 0; i < _maxRicochetCheck; i++) { if (!Hitbox.Update(_fixedInfo.Position, velocityDelta, out var bounceHit)) { break; } float num3 = Math.Abs(Vector3.Dot(_fixedInfo.Dir, ((RaycastHit)(ref bounceHit)).normal)); float num4 = (1f - Settings.RicochetSpeedAngleFactor * (1f - num3)).Lerp(1f, Settings.RicochetSpeedMod); _fixedInfo.BaseSpeed *= num4; float magnitude = ((Vector3)(ref velocityDelta)).magnitude; Vector3 val2 = ((RaycastHit)(ref bounceHit)).point - _fixedInfo.Position; float num5 = (magnitude - ((Vector3)(ref val2)).magnitude) * num4; _fixedInfo.BaseDir = Vector3.Reflect(_fixedInfo.Dir, ((RaycastHit)(ref bounceHit)).normal); val = _fixedInfo.Dir * num5; velocityDelta = ((num5 > 0.02f) ? val : (_fixedInfo.Dir * 0.02f)); _fixedInfo.Position = ((RaycastHit)(ref bounceHit)).point; flag = true; } if (!((Behaviour)this).enabled) { return true; } PhysicsInfo fixedInfo = _fixedInfo; fixedInfo.Position += val; _deltaInfo.Copy(_fixedInfo); _lastUpdatePhysicsTime = time; if (flag) { EWCProjectileManager.DoProjectileBounce(PlayerIndex, SyncID, Position, _deltaInfo.BaseVelocity); } return true; } protected virtual void Update() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) if (Settings == null || (IsManaged && (Object)(object)Settings.CWC == (Object)null)) { Die(); return; } bool flag = UpdatePhysics(); if (!((Behaviour)this).enabled) { return; } float time = Time.time; if (time > _endLifetime || (IsManaged && Settings.MaxRange > 0f && Hitbox.GetMoveDist() >= Settings.MaxRange)) { TimeOut(); return; } if (!flag) { float deltaTime = Time.deltaTime; Vector3 dir = _deltaInfo.Dir; Homing.UpdateDir(_deltaInfo.Position, deltaTime, ref dir); foreach (ProjectileDirChange.State dirChange in _deltaInfo.DirChanges) { dirChange.Update(ref dir); } if (dir != _deltaInfo.Dir) { _deltaInfo.BaseDir = dir; } Vector3 deltaMove = GetDeltaMove(_deltaInfo, deltaTime); PhysicsInfo deltaInfo = _deltaInfo; deltaInfo.Position += deltaMove; } if (IsManaged && _aliveTriggerTime <= time) { _aliveTriggerTime = time + Settings.AliveTriggerInterval; Settings.EventHelper.Invoke(ContextController, new WeaponReferencePosContext(Settings.ID, 0u, Position, Dir, Vector3.zero, Hitbox.GetFalloff(), Hitbox.HitData.shotInfo)); } LerpVisualOffset(); SoundPlayer.UpdatePosition(_positionVisual); } [HideFromIl2Cpp] private Vector3 GetDeltaMove(PhysicsInfo info, float delta) { //IL_00fa: 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_0105: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00f6: Unknown result type (might be due to invalid IL or missing references) Vector3 result; if (Settings.AccelScale != 1f && info.AccelProgress != 1f) { float num = Math.Min(info.AccelProgress + delta / Settings.AccelTime, 1f); float num2 = Settings.AccelExponent + 1f; float num3 = (float)((double)Settings.AccelTime * ((double)Settings.AccelScale - 1.0) * (Math.Pow(num, num2) - Math.Pow(info.AccelProgress, num2)) / (double)num2); float num4; if (num < 1f) { num4 = delta + num3; } else { float num5 = (1f - info.AccelProgress) * Settings.AccelTime; num4 = num3 + num5 + Settings.AccelScale * (delta - num5); } info.AccelProgress = num; result = info.BaseDir * info.BaseSpeed * num4; } else { result = info.BaseVelocity * delta; } result.y -= 0.5f * Settings.Gravity * delta * delta + info.GravityVel * delta; info.GravityVel += Settings.Gravity * delta; info.BaseVelocity = info.BaseDir * info.Speed; info.Velocity = info.BaseVelocity; info.Velocity.y -= info.GravityVel; info.Dir = ((Vector3)(ref info.Velocity)).normalized; return result; } public void OnHit(DamageType damageType) { if (damageType.HasFlagIn(Settings.HitDestroyDamageType)) { if (Settings.HitDestroyDelay <= 0f) { Die(); } else { _endLifetime = Math.Min(Time.time + Settings.HitDestroyDelay, _endLifetime); } } } private void TimeOut() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (IsManaged) { Settings.EventHelper.Invoke(ContextController, new WeaponReferencePosContext(Settings.ID, 2u, Position, Dir, -Dir, Hitbox.GetFalloff(), Hitbox.HitData.shotInfo)); } Die(); } public void Die() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if (((Behaviour)this).enabled) { if (IsManaged) { Settings.EventHelper.Invoke(ContextController, new WeaponReferencePosContext(Settings.ID, 1u, Position, Dir, -Dir, Hitbox.GetFalloff(), Hitbox.HitData.shotInfo)); } ((Component)this).gameObject.transform.localScale = Vector3.zero; ((Behaviour)this).enabled = false; if (Settings.StopFlyingSoundOnDestroy) { SoundPlayer.Stop(); } if (Settings.DestroyedSoundID != 0) { _playingEndSound = true; SoundPlayer.PostWithDoneCallback(Settings.DestroyedSoundID, Position, OnEndSoundDone); } _inactiveCallback.Start(); EWCProjectileManager.DoProjectileDestroy(PlayerIndex, SyncID, IsManaged); Hitbox.Die(); Homing.Die(); ProjectileAPI.FireProjectileDestroyedCallback(this); OnDie(); } } protected virtual void OnDie() { } private void OnEndSoundDone() { _playingEndSound = false; Cleanup(); } private void Cleanup() { if (!_inactiveCallback.Active && !_playingEndSound) { ((Component)this).gameObject.active = false; OnCleanup(); } } protected virtual void OnCleanup() { } } public sealed class EWCProjectileComponentShooter : EWCProjectileComponentBase { private ProjectileBase _projectile; private ProjectileTargeting? _targeting; private TrailRenderer? _trailRenderer; public ProjectileType Type; private Color _origTrailColor; private float _origTrailWidth; private float _origTrailDuration; private Color _origGlowColor; private float _origGlowRange; private float _minInactiveLifetime; protected override CellSoundPlayer SoundPlayer => _projectile.m_soundPlayer; public EWCProjectileComponentShooter(IntPtr ptr) : base(ptr) { } [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } [HideFromIl2Cpp] public override void Init(ushort playerIndex, ushort shotIndex, ushort ID, Projectile settings, bool isLocal, Vector3 position, Vector3 dir, HitData? hitData = null, IntPtr ignoreEnt = default(IntPtr)) { //IL_0011: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (((Behaviour)this).enabled) { return; } base.Init(playerIndex, shotIndex, ID, settings, isLocal, position, dir, hitData, ignoreEnt); ((Component)_projectile).transform.SetPositionAndRotation(base.Position, EWCProjectileComponentBase.s_tempRot); Enumerator enumerator = _projectile.m_effectsToStopEmittingOnImpact.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.Play(); } Enumerator enumerator2 = _projectile.m_toDestroyOnImpact.GetEnumerator(); while (enumerator2.MoveNext()) { enumerator2.Current.active = true; } _inactiveLifetime = _minInactiveLifetime; if ((Object)(object)_targeting != (Object)null) { ((Behaviour)_targeting.m_light).enabled = true; ((LightBase)_targeting.m_light).Color = ((settings.GlowColor == Color.black) ? _origGlowColor : settings.GlowColor); ((LightBase)_targeting.m_light).Range = ((settings.GlowRange < 0f) ? _origGlowRange : settings.GlowRange); ((LightBase)_targeting.m_light).Intensity = settings.GlowIntensity; if ((Object)(object)((ProjectileBase)_targeting).m_ricochetEffect != (Object)null) { ((ProjectileBase)_targeting).m_ricochetEffect.active = true; } } if ((Object)(object)_trailRenderer != (Object)null) { _trailRenderer.Clear(); ((Renderer)_trailRenderer).enabled = settings.EnableTrail; _trailRenderer.startColor = ((settings.TrailColor == Color.black) ? _origTrailColor : settings.TrailColor); _trailRenderer.time = ((settings.TrailTime < 0f) ? _origTrailDuration : settings.TrailTime); _trailRenderer.widthMultiplier = ((settings.TrailWidth < 0f) ? _origTrailWidth : settings.TrailWidth); if (!settings.TrailCullOnDie) { _inactiveLifetime = Math.Max(_trailRenderer.time, _inactiveLifetime); } } } protected override void Awake() { //IL_00ce: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) base.Awake(); _projectile = ((Component)this).GetComponent(); _targeting = ((Il2CppObjectBase)_projectile).TryCast(); _projectile.OnFire((Agent)null); _projectile.m_soundPlayer.Stop(); ((Behaviour)_projectile).enabled = false; _trailRenderer = ((Component)this).GetComponentInChildren(); if ((Object)(object)_targeting != (Object)null) { if ((Object)(object)_targeting.m_light != (Object)null) { _origGlowColor = ((LightBase)_targeting.m_light).Color; _origGlowRange = ((LightBase)_targeting.m_light).Range; } else { _targeting.m_light = ((Component)this).gameObject.AddComponent(); ((Behaviour)_targeting.m_light).enabled = false; _origGlowColor = Color.clear; _origGlowRange = 0f; } } if ((Object)(object)_projectile.m_toDestroyOnImpact[0] == (Object)(object)((Component)this).gameObject) { _projectile.m_toDestroyOnImpact.Clear(); IEnumerator enumerator = ((Component)this).transform.GetEnumerator(); try { while (enumerator.MoveNext()) { Transform val = ((Il2CppObjectBase)enumerator.Current).Cast(); if (((Object)val).name != "Sphere" && ((Object)val).name != "Cube") { _projectile.m_toDestroyOnImpact.Add(((Component)val).gameObject); } } } finally { if (enumerator is IDisposable disposable) { disposable.Dispose(); } } } else { _minInactiveLifetime = 1.5f; } if ((Object)(object)_trailRenderer != (Object)null) { _origTrailColor = _trailRenderer.startColor; _origTrailDuration = _trailRenderer.time; _origTrailWidth = _trailRenderer.widthMultiplier; } } public override void SetVisualPosition(Vector3 positionVisual, float lerpDist) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) base.SetVisualPosition(positionVisual, lerpDist); ((Component)_projectile).transform.SetPositionAndRotation(_positionVisual, EWCProjectileComponentBase.s_tempRot); } protected override void Update() { //IL_001b: 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) base.Update(); if (((Behaviour)this).enabled) { ((Component)_projectile).transform.SetPositionAndRotation(_positionVisual, EWCProjectileComponentBase.s_tempRot); } } protected override void OnDie() { Enumerator enumerator = _projectile.m_effectsToStopEmittingOnImpact.GetEnumerator(); while (enumerator.MoveNext()) { enumerator.Current.Stop(); } Enumerator enumerator2 = _projectile.m_toDestroyOnImpact.GetEnumerator(); while (enumerator2.MoveNext()) { enumerator2.Current.active = false; } if (base.Settings.TrailCullOnDie && (Object)(object)_trailRenderer != (Object)null) { _trailRenderer.Clear(); } if ((Object)(object)_targeting != (Object)null) { ((Behaviour)_targeting.m_light).enabled = false; if ((Object)(object)((ProjectileBase)_targeting).m_ricochetEffect != (Object)null) { ((ProjectileBase)_targeting).m_ricochetEffect.active = false; } } } protected override void OnCleanup() { EWCProjectileManager.Shooter.ReturnToPool(this); } } public sealed class EWCProjectileHitbox { private readonly EWCProjectileComponentBase _base; private Projectile _settings; private IOwnerComp _owner; private IntPtr _ownerPtr; private PlayerAgent? _ownerPlayer; private readonly HashSet _initialPlayers = new HashSet(); private ShotInfo.Const _origInfo; private int _friendlyLayer; private WallPierce? _wallPierce; private float _baseFalloff; private float _startLifetime; private eDimensionIndex _dimensionIndex; private bool _runHitTriggers = true; private Func? _hitFuncOverride; private bool _enabled; private int _pierceCount = 1; private int _ricochetCount; private float _distanceMoved; private float _lastFixedTime; private SearchSetting _searchSettings = SearchSetting.ClosestHit | SearchSetting.IgnoreDupes; public readonly HashSet HitEnts = new HashSet(); private readonly Queue<(IntPtr, float)> _hitEntCooldowns = new Queue<(IntPtr, float)>(); private float _ignoreWallsTime; public const float MinCollisionDist = 0.05f; public const float MinCollisionSqrDist = 0.0025000002f; public const float MinRicochetDist = 0.02f; private static Ray s_ray; private static RaycastHit s_rayHit; private static float s_velMagnitude; private static readonly List s_hits = new List(50); private static readonly HashSet s_playerCheck = new HashSet(); private const float SightCheckMinSize = 0.5f; public HitData HitData { get; private set; } = new HitData(DamageType.Bullet); public EWCProjectileHitbox(EWCProjectileComponentBase comp) { _base = comp; } public void Init(Projectile projBase, Vector3 pos, Vector3 dir, HitData? hitData, IntPtr ignoreEnt, out RaycastHit? bounceHit) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) bounceHit = null; if (_enabled || !_base.IsManaged) { return; } CustomWeaponComponent cWC = projBase.CWC; _enabled = true; _settings = projBase; _owner = cWC.Owner; _dimensionIndex = _owner.DimensionIndex; _runHitTriggers = true; _startLifetime = Time.time; if (!cWC.HasTempProperties()) { _runHitTriggers = cWC.RunHitTriggers; } ((Ray)(ref s_ray)).origin = pos; ((Ray)(ref s_ray)).direction = dir; _friendlyLayer = 0; _searchSettings = SearchSetting.ClosestHit | SearchSetting.IgnoreDupes; _ownerPlayer = (_owner.IsType(OwnerType.Player) ? _owner.Player : null); PlayerAgent? ownerPlayer = _ownerPlayer; _ownerPtr = ((ownerPlayer != null) ? ((Il2CppObjectBase)ownerPlayer).Pointer : IntPtr.Zero); if (projBase.DamageFriendly) { if (!_owner.IsType(OwnerType.Local)) { _friendlyLayer |= LayerUtil.MaskLocal; } _searchSettings |= SearchSetting.CheckFriendly; _friendlyLayer |= LayerUtil.MaskFriendly; Enumerator enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator(); while (enumerator.MoveNext()) { PlayerAgent current = enumerator.Current; Vector3 val = ((Agent)current).Position - pos; if (((Il2CppObjectBase)current).Pointer != _ownerPtr && Vector3.Dot(dir, val) < 0f) { _initialPlayers.Add(((Il2CppObjectBase)current).Pointer); } } } if (projBase.DamageOwner && _ownerPtr != IntPtr.Zero) { if (_owner.IsType(OwnerType.Local)) { _friendlyLayer |= LayerUtil.MaskLocal; } else { _friendlyLayer |= LayerUtil.MaskFriendly; } _searchSettings |= SearchSetting.CheckOwner; _initialPlayers.Add(_ownerPtr); _ownerPtr = IntPtr.Zero; } _wallPierce = _settings.WallPierce; _hitFuncOverride = projBase.HitFuncOverride; _pierceCount = hitData.GetPierceOrFallback(cWC.Weapon); _ricochetCount = _settings.RicochetCount; HitData = new HitData(hitData); _baseFalloff = HitData.falloff; _origInfo = HitData.shotInfo.State; if (ignoreEnt != IntPtr.Zero) { HitEnts.Add(ignoreEnt); } _distanceMoved = 0f; _lastFixedTime = Time.fixedTime; DoCollisionInitialWorld(out bounceHit); if (bounceHit.HasValue && _ricochetCount-- <= 0) { _base.Die(); } } public float GetFalloff() { return HitData.CalcRawFalloff(_distanceMoved); } public float GetMoveDist() { return _distanceMoved; } public void Die() { if (_base.IsManaged) { _settings.CWC.Invoke(new WeaponShotEndContext(DamageType.Bullet, HitData.shotInfo, _origInfo)); _initialPlayers.Clear(); HitEnts.Clear(); _hitEntCooldowns.Clear(); _ricochetCount = 0; _pierceCount = 0; _ignoreWallsTime = 0f; } _enabled = false; } public bool Update(Vector3 position, Vector3 velocityDelta, out RaycastHit bounceHit) { //IL_0001: 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_0082: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) bounceHit = default(RaycastHit); RaycastHit? bounceHit2 = null; if (!_enabled) { return false; } ((Ray)(ref s_ray)).origin = position; if (_settings.MaxRange > 0f && _distanceMoved + ((Vector3)(ref velocityDelta)).magnitude >= _settings.MaxRange) { float num = _settings.MaxRange - _distanceMoved; if (num <= 0f) { return false; } velocityDelta = ((Vector3)(ref velocityDelta)).normalized * num; } ((Ray)(ref s_ray)).direction = velocityDelta; s_velMagnitude = Math.Max(((Vector3)(ref velocityDelta)).magnitude, 0.05f); s_playerCheck.Clear(); bool flag = false; if (CheckCollisionWorld(ref bounceHit2)) { flag = true; RaycastHit value = bounceHit2.Value; velocityDelta = ((RaycastHit)(ref value)).point - position; s_velMagnitude = Math.Max(((Vector3)(ref velocityDelta)).magnitude, 0.05f); } DoCollisionEntities(ref bounceHit2); if (_pierceCount <= 0) { return false; } if (flag) { DoCollisionWorld(ref bounceHit2); } if (bounceHit2.HasValue) { if (_ricochetCount-- <= 0) { _base.Die(); } else { if (_settings.RicochetIgnorePlayers) { _friendlyLayer &= ~(LayerUtil.MaskFriendly | LayerUtil.MaskLocal); _searchSettings &= ~(SearchSetting.CheckOwner | SearchSetting.CheckFriendly); } if (_settings.RicochetResetHits) { HitEnts.Clear(); _hitEntCooldowns.Clear(); } } } if (!_enabled) { return false; } if (_lastFixedTime != Time.fixedTime && _initialPlayers.Count != 0) { _initialPlayers.RemoveWhere((IntPtr ptr) => !s_playerCheck.Contains(ptr)); _lastFixedTime = Time.fixedTime; } (IntPtr, float) result; while (_hitEntCooldowns.TryPeek(out result) && result.Item2 < Clock.Time) { HitEnts.Remove(result.Item1); _hitEntCooldowns.Dequeue(); } _distanceMoved += ((Vector3)(ref velocityDelta)).magnitude; if (bounceHit2.HasValue) { bounceHit = bounceHit2.Value; return true; } return false; } private void DoCollisionEntities(ref RaycastHit? bounceHit) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) SearchUtil.DupeCheckSet = HitEnts; if (_settings.HitSize == 0f) { s_hits.AddRange(SearchUtil.RaycastAll(s_ray, s_velMagnitude, LayerUtil.MaskEnemyDynamic, _searchSettings)); } else { foreach (var item3 in SearchUtil.GetEnemyHitsInRange(s_ray, _settings.HitSize, 180f, CourseNodeUtil.GetCourseNode(((Ray)(ref s_ray)).origin, _dimensionIndex), _searchSettings)) { RaycastHit item = item3.hit; s_hits.Add(item); } s_hits.AddRange(SearchUtil.GetLockHitsInRange(s_ray, _settings.HitSize, 180f, _searchSettings)); RaycastHit[] array = Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)Physics.SphereCastAll(s_ray, _settings.HitSize, s_velMagnitude, LayerUtil.MaskEnemyDynamic)); for (int i = 0; i < array.Length; i++) { if (((RaycastHit)(ref array[i])).distance > 0f) { ref RaycastHit reference = ref array[i]; ((RaycastHit)(ref reference)).distance = ((RaycastHit)(ref reference)).distance + _settings.HitSize; s_hits.Add(array[i]); } } } if (_friendlyLayer != 0) { if (_settings.HitSizeFriendly == 0f) { s_hits.AddRange(SearchUtil.RaycastAll(s_ray, s_velMagnitude, _friendlyLayer, _searchSettings)); } else { foreach (var item4 in SearchUtil.GetPlayerHitsInRange(s_ray, _settings.HitSizeFriendly, 180f, _ownerPlayer, _searchSettings)) { RaycastHit item2 = item4.hit; s_hits.Add(item2); } RaycastHit[] array2 = Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)Physics.SphereCastAll(s_ray, _settings.HitSizeFriendly, s_velMagnitude, _friendlyLayer)); for (int j = 0; j < array2.Length; j++) { if (((RaycastHit)(ref array2[j])).distance > 0f) { ref RaycastHit reference2 = ref array2[j]; ((RaycastHit)(ref reference2)).distance = ((RaycastHit)(ref reference2)).distance + _settings.HitSize; s_hits.Add(array2[j]); } } } } int pierceCount = _pierceCount; bool flag = _settings.HitSize >= 0.5f; if (_settings.HitSize > 0f) { SortUtil.SortWithWeakspotBuffer(s_hits); } else { s_hits.Sort(SortUtil.Rayhit); } foreach (RaycastHit s_hit in s_hits) { RaycastHit current = s_hit; IDamageable damageableFromRayHit = DamageableUtil.GetDamageableFromRayHit(current); if (damageableFromRayHit != null && !AlreadyHit(damageableFromRayHit) && (!flag || _wallPierce != null || !Physics.Linecast(((RaycastHit)(ref current)).point, ((Ray)(ref s_ray)).origin, ref s_rayHit, LayerUtil.MaskWorld) || !(((Il2CppObjectBase)((Component)((RaycastHit)(ref s_rayHit)).collider).gameObject).Pointer != ((Il2CppObjectBase)((Component)((RaycastHit)(ref current)).collider).gameObject).Pointer))) { s_rayHit = current; if (damageableFromRayHit != null) { DoDamage(damageableFromRayHit); } if (_pierceCount <= 0) { break; } } } if (_pierceCount > 0 && _pierceCount != pierceCount) { if (_settings.RicochetOnHit) { ((RaycastHit)(ref s_rayHit)).point = ((RaycastHit)(ref s_rayHit)).point + (((Ray)(ref s_ray)).origin - ((RaycastHit)(ref s_rayHit)).point) * _settings.HitSize; bounceHit = s_rayHit; } _base.Homing.UpdateOnPierce(); } s_hits.Clear(); } private bool CheckCollisionWorld([NotNullWhen(true)] ref RaycastHit? bounceHit) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0103: 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_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_00a1: Unknown result type (might be due to invalid IL or missing references) if (_wallPierce != null || Clock.Time < _ignoreWallsTime) { return false; } bool flag; if (_settings.HitSizeWorld == 0f) { flag = Physics.Raycast(s_ray, ref s_rayHit, s_velMagnitude, LayerUtil.MaskWorld); } else { flag = Physics.SphereCast(s_ray, _settings.HitSizeWorld, ref s_rayHit, s_velMagnitude, LayerUtil.MaskWorld); if (flag && ((RaycastHit)(ref s_rayHit)).distance == 0f) { ((Ray)(ref s_ray)).direction = ((RaycastHit)(ref s_rayHit)).point - ((Ray)(ref s_ray)).origin; flag = Physics.Raycast(s_ray, ref s_rayHit, _settings.HitSizeWorld, LayerUtil.MaskWorld); } } if (flag) { ((RaycastHit)(ref s_rayHit)).point = ((RaycastHit)(ref s_rayHit)).point + (((Ray)(ref s_ray)).origin - ((RaycastHit)(ref s_rayHit)).point) * _settings.HitSizeWorld; bounceHit = s_rayHit; } return flag; } private void DoCollisionWorld(ref RaycastHit? bounceHit) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (bounceHit.HasValue) { s_rayHit = bounceHit.Value; BulletHit(DamageableUtil.GetDamageableFromRayHit(s_rayHit), terrain: true); } } private void DoCollisionInitialWorld(out RaycastHit? bounceHit) { //IL_001f: 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_0025: 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_0072: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) bounceHit = null; if (_settings.HitSizeWorld == 0f) { return; } Vector3 origin = ((Ray)(ref s_ray)).origin; Collider[] array = Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)Physics.OverlapSphere(origin, _settings.HitSizeWorld, LayerUtil.MaskWorld)); if (array.Length == 0) { return; } ((RaycastHit)(ref s_rayHit)).distance = float.MaxValue; Collider[] array2 = array; RaycastHit val2 = default(RaycastHit); foreach (Collider val in array2) { ((Ray)(ref s_ray)).direction = ((Component)val).transform.position - origin; if (val.Raycast(s_ray, ref val2, _settings.HitSizeWorld) && ((RaycastHit)(ref val2)).distance < ((RaycastHit)(ref s_rayHit)).distance) { s_rayHit = val2; } } if (((RaycastHit)(ref s_rayHit)).distance != float.MaxValue && BulletHit(DamageableUtil.GetDamageableFromRayHit(s_rayHit), terrain: true)) { bounceHit = s_rayHit; } } private void DoDamage(IDamageable damageable) { if (ShouldDamage(damageable)) { IntPtr pointer = ((Il2CppObjectBase)damageable.GetBaseDamagable()).Pointer; HitEnts.Add(pointer); if (_settings.HitCooldown >= 0f) { _hitEntCooldowns.Enqueue((pointer, Clock.Time + _settings.HitCooldown)); } if ((Object)(object)damageable.GetBaseAgent() != (Object)null) { _ignoreWallsTime = Clock.Time + _settings.HitIgnoreWallsDuration; } if (BulletHit(damageable, terrain: false) && --_pierceCount <= 0) { _base.Die(); } } } private bool ShouldDamage(IDamageable damageable) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (damageable.GetBaseDamagable().GetHealthRel() <= 0f) { return false; } Agent baseAgent = damageable.GetBaseAgent(); if ((Object)(object)baseAgent != (Object)null) { if ((int)baseAgent.Type == 0) { IntPtr pointer = ((Il2CppObjectBase)baseAgent).Pointer; if (!_settings.DamageOwner && _ownerPtr == pointer) { return false; } if (!_settings.DamageFriendly && _ownerPtr != pointer) { return false; } if (_initialPlayers.Contains(pointer)) { s_playerCheck.Add(pointer); return false; } } if (!baseAgent.Alive) { return false; } } return _wallPierce?.IsTargetReachable(_owner.CourseNode, (baseAgent != null) ? baseAgent.CourseNode : null) ?? true; } private bool AlreadyHit(IDamageable? damageable) { if (damageable == null) { return false; } return HitEnts.Contains(((Il2CppObjectBase)damageable.GetBaseDamagable()).Pointer); } private void DoImpactFX(IDamageable? damageable) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0088: 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_0059: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)((RaycastHit)(ref s_rayHit)).collider).gameObject; ColliderMaterial component = gameObject.GetComponent(); bool flag = (LayerUtil.MaskDecalValid & gameObject.gameObject.layer) == 0; FX_GroupName val = (FX_GroupName)1; if ((Object)(object)component != (Object)null) { val = (FX_GroupName)component.MaterialId; } else if (damageable != null) { Agent baseAgent = damageable.GetBaseAgent(); if (((baseAgent != null) ? new AgentType?(baseAgent.Type) : null) == (AgentType?)0) { val = (FX_GroupName)12; } } FX_Manager.PlayEffect(false, val, (Transform)null, ((RaycastHit)(ref s_rayHit)).point, Quaternion.LookRotation(((RaycastHit)(ref s_rayHit)).normal), flag); } private bool BulletHit(IDamageable? damageable, bool terrain) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) HitData.ResetDamage(); HitData hitData = HitData; Vector3 val = (_settings.HitFromOwnerPos ? (((RaycastHit)(ref s_rayHit)).point - _owner.FirePos) : ((Ray)(ref s_ray)).direction); hitData.fireDir = ((Vector3)(ref val)).normalized; HitData.RayHit = s_rayHit; HitData.falloff = HitData.CalcFalloff(_distanceMoved) * _baseFalloff; if (!terrain || _settings.EnableTerrainHitFX) { DoImpactFX(damageable); } ProjectileAPI.FireProjectileHitCallback(_base, damageable); foreach (ProjectileStatChange statChange in _settings.StatChanges) { float num = Time.time.Map(_startLifetime + statChange.Delay, _startLifetime + statChange.Delay + statChange.ChangeTime, 1f, statChange.EndFrac, statChange.Exponent); switch (statChange.StatType) { case StatType.Damage: HitData.damage *= num; break; case StatType.Precision: HitData.precisionMulti *= num; break; case StatType.Stagger: HitData.staggerMulti *= num; break; } } if (_hitFuncOverride != null) { bool result = _hitFuncOverride(HitData, _base.ContextController); _base.OnHit(HitData.damageType); return result; } ToggleRunTriggers(enable: false); WeaponPatches.ApplyEWCHit(_settings.CWC, _base.ContextController, HitData, out var doBackstab); ToggleRunTriggers(enable: true); float num2 = HitData.damage * HitData.falloff; if (damageable != null) { if (_owner.IsType(OwnerType.Sentry)) { PlayerAgent? player = _owner.Player; if (player != null && ((Agent)player).IsLocallyOwned) { num2 /= EXPAPIWrapper.GetDamageMod(local: true, WeaponType.BulletWeapon); } } if (damageable != null) { float num3 = num2; PlayerAgent? owner = HitData.owner; Vector3 hitPos = HitData.hitPos; Vector3 fireDir = HitData.fireDir; RaycastHit rayHit = HitData.RayHit; damageable.BulletDamage(num3, (Agent)(object)owner, hitPos, fireDir, ((RaycastHit)(ref rayHit)).normal, doBackstab, HitData.staggerMulti, HitData.precisionMulti, 0u); } } _base.OnHit(HitData.damageType); return true; } private void ToggleRunTriggers(bool enable) { if (!_runHitTriggers) { _settings.CWC.RunHitTriggers = enable; } } } public sealed class EWCProjectileHoming { private readonly EWCProjectileComponentBase _base; private ProjectileHomingSettings _settings; private IOwnerComp? _owner; private eDimensionIndex _dimensionIndex; private WallPierce? _wallPierce; private bool _enabled; private bool _homingEnabled; private float _homingStartTime; private float _initialHomingEndTime; private EnemyAgent? _homingAgent; private byte _homingLimbID; private Collider? _homingCollider; private Transform? _homingTarget; private readonly List<(Collider, byte)> _weakspotList = new List<(Collider, byte)>(); private bool _hadTarget; private float _nextSearchTime; private static Vector3 s_position; private static Vector3 s_dir; private static readonly Queue s_nodeQueue = new Queue(); public EWCProjectileHoming(EWCProjectileComponentBase comp) { _base = comp; } public void Init(Projectile projBase, Vector3 position, Vector3 dir) { //IL_00a1: 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_00c7: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) if (_enabled) { return; } _enabled = true; _settings = projBase.HomingSettings; _wallPierce = null; _owner = null; _homingStartTime = Time.time + _settings.HomingDelay; _initialHomingEndTime = _homingStartTime + _settings.InitialHomingDuration; _homingEnabled = _settings.HomingEnabled; _nextSearchTime = 0f; ResetHomingAgent(); if (!_base.IsManaged) { return; } _owner = projBase.CWC.Owner; _dimensionIndex = _owner.DimensionIndex; _wallPierce = projBase.CWC.GetTrait(); if (!_homingEnabled) { return; } s_position = position; s_dir = dir; if (_settings.SearchInitialMode == SearchMode.AutoAim) { _homingEnabled = false; AutoAim trait = projBase.CWC.GetTrait(); if (trait != null && trait.UseAutoAim) { _homingEnabled = true; var (agent, collider, limbID) = trait.GetTargets(); ReceiveHomingAgent(agent, collider, limbID); ResetWeakspotList(); SendHomingTarget(); } } else { if (_settings.SearchInitialMode == SearchMode.AimDir) { s_dir = _owner.FireDir; } FindHomingAgent(); if ((Object)(object)_homingAgent == (Object)null && _settings.SearchStopMode.HasFlag(StopSearchMode.Invalid)) { _homingEnabled = false; } } } public void Update(Vector3 position, float deltaTime, ref Vector3 dir) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) s_position = position; s_dir = dir; if (_homingEnabled && !(Time.time < _homingStartTime) && UpdateHomingAgent()) { UpdateDir(position, deltaTime, ref dir); } } public void UpdateDir(Vector3 position, float deltaTime, ref Vector3 dir) { //IL_0036: 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) //IL_003c: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (_homingEnabled && !(Time.time < _homingStartTime) && !((Object)(object)_homingAgent == (Object)null)) { float num = _settings.InitialHomingStrength; Vector3 val = _homingTarget.position - position; if (Time.time >= _initialHomingEndTime) { num = _settings.HomingStrength * ((Vector3)(ref val)).magnitude.MapInverted(_settings.HomingMinDist, _settings.HomingMaxDist, 1f, 0f, _settings.HomingDistExponent); } if (_settings.UseSteadyStrength) { dir = Vector3.RotateTowards(dir, val, (float)((double)num * Math.PI / 180.0 * (double)deltaTime), 0f); } else { dir = Vector3.Slerp(dir, ((Vector3)(ref val)).normalized, Math.Min(num * deltaTime, 1f)); } } } public void Die() { _enabled = false; _weakspotList.Clear(); } private bool UpdateHomingAgent() { if (!_base.IsManaged) { if ((Object)(object)_homingAgent == (Object)null || !((Agent)_homingAgent).Alive || ((Dam_SyncedDamageBase)_homingAgent.Damage).Health <= 0f) { return false; } if (_homingLimbID != 0 && !_homingCollider.enabled) { return true; } _homingTarget = GetHomingTarget(_homingAgent); _homingCollider = null; _homingLimbID = 0; return true; } if ((Object)(object)_homingAgent == (Object)null || !((Agent)_homingAgent).Alive || ((Dam_SyncedDamageBase)_homingAgent.Damage).Health <= 0f) { if (_hadTarget && _settings.SearchStopMode.HasFlag(StopSearchMode.Dead)) { _homingEnabled = false; return false; } FindHomingAgent(); if ((Object)(object)_homingAgent == (Object)null && _settings.SearchStopMode.HasFlag(StopSearchMode.Invalid)) { _homingEnabled = false; return false; } return (Object)(object)_homingAgent != (Object)null; } if ((Object)(object)_homingAgent != (Object)null) { UpdateHomingTarget(); return true; } return false; } public void SendHomingTarget() { EWCProjectileManager.DoProjectileTarget(_base.PlayerIndex, _base.SyncID, _homingAgent, _homingLimbID); } public void SetHomingAgent(EnemyAgent? agent) { if ((Object)(object)agent == (Object)null) { ResetHomingAgent(); return; } _homingAgent = agent; ResetWeakspotList(); UpdateHomingTarget(); SendHomingTarget(); } public void ReceiveHomingAgent(EnemyAgent? agent, byte limbID) { if ((Object)(object)agent != (Object)null && limbID != 0) { ReceiveHomingAgent(agent, ((Component)((Il2CppArrayBase)(object)agent.Damage.DamageLimbs)[(int)limbID]).GetComponent(), limbID); } else { ReceiveHomingAgent(agent, null, 0); } } public void ReceiveHomingAgent(EnemyAgent? agent, Collider? collider, byte limbID) { if ((Object)(object)agent == (Object)null) { ResetHomingAgent(); return; } _homingAgent = agent; _homingLimbID = limbID; if (_homingLimbID != 0) { _homingCollider = collider; _homingTarget = ((Component)_homingCollider).transform; } else { _homingCollider = null; _homingTarget = GetHomingTarget(agent); } } public void ResetHomingAgent() { _homingAgent = null; _homingTarget = null; _homingCollider = null; _homingLimbID = 0; } public void UpdateOnPierce() { if (_settings.SearchStayOnTarget) { return; } if (_settings.SearchStopMode.HasFlag(StopSearchMode.Pierce)) { _homingEnabled = false; EWCProjectileManager.DoProjectileTarget(_base.PlayerIndex, _base.SyncID, null, 0); return; } FindHomingAgent(); if ((Object)(object)_homingAgent == (Object)null) { EWCProjectileManager.DoProjectileTarget(_base.PlayerIndex, _base.SyncID, null, 0); } } public void FindHomingAgent() { //IL_0059: 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_0063: 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_020c: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) if (!_hadTarget && _nextSearchTime > Time.time) { _homingAgent = null; return; } _nextSearchTime = Time.time + Math.Max(Configuration.HomingTickDelay, _settings.SearchCooldown); _hadTarget = false; ResetHomingAgent(); Ray ray = new Ray(s_position, s_dir); SearchUtil.DupeCheckSet = _base.Hitbox.HitEnts; EnemyAgent target = null; RaycastHit hit; if (_settings.SearchAngle > 0f) { List enemiesInRange = SearchUtil.GetEnemiesInRange(ray, _settings.SearchRange, _settings.SearchAngle, CourseNodeUtil.GetCourseNode(s_position, _dimensionIndex), SearchSetting.IgnoreDupes); switch (_settings.TargetPriority) { default: return; case TargetingPriority.Angle: { List<(EnemyAgent, float)> list3 = enemiesInRange.ConvertAll((EnemyAgent enemy) => (enemy, Vector3.Angle(((Ray)(ref ray)).direction, GetHomingTargetPos(enemy) - ((Ray)(ref ray)).origin))); list3.Sort(SortUtil.FloatTuple); SortUtil.CopySortedList(list3, enemiesInRange); break; } case TargetingPriority.Distance: { List<(EnemyAgent, float)> list2 = enemiesInRange.ConvertAll(delegate(EnemyAgent enemy) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) Vector3 val = GetHomingTargetPos(enemy) - ((Ray)(ref ray)).origin; return (enemy, ((Vector3)(ref val)).sqrMagnitude); }); list2.Sort(SortUtil.FloatTuple); SortUtil.CopySortedList(list2, enemiesInRange); break; } case TargetingPriority.Health: { List<(EnemyAgent, float, float)> list = enemiesInRange.ConvertAll((EnemyAgent enemy) => (enemy, ((Dam_SyncedDamageBase)enemy.Damage).HealthMax, 180f - Vector3.Angle(((Ray)(ref ray)).direction, GetHomingTargetPos(enemy) - ((Ray)(ref ray)).origin))); list.Sort(SortUtil.FloatTuple); list.Reverse(); SortUtil.CopySortedList(list, enemiesInRange); break; } } foreach (EnemyAgent item in enemiesInRange) { if (EnemyIsVisible(item) && (_settings.SearchIgnoreWalls || !Physics.Linecast(((Ray)(ref ray)).origin, GetHomingTargetPos(item), LayerUtil.MaskWorldExcProj)) && (!_settings.SearchIgnoreWalls || IsTargetReachable(_owner.CourseNode, ((Agent)item).CourseNode))) { target = item; break; } } } else if (!SearchUtil.RaycastFirst(ray, out hit, _settings.SearchRange, LayerUtil.MaskEnemy, (IDamageable damageable) => EnemyIsVisible(target = ((Il2CppObjectBase)damageable.GetBaseAgent()).Cast()) && (_settings.SearchIgnoreWalls || Physics.Linecast(((Ray)(ref ray)).origin, GetHomingTargetPos(target), LayerUtil.MaskWorldExcProj)) && (!_settings.SearchIgnoreWalls || IsTargetReachable(_owner.CourseNode, ((Agent)target).CourseNode)), SearchSetting.IgnoreDupes)) { return; } if (!((Object)(object)target == (Object)null)) { _hadTarget = true; SetHomingAgent(target); EWCProjectileManager.DoProjectileTarget(_base.PlayerIndex, _base.SyncID, _homingAgent, _homingLimbID); } } private bool EnemyIsVisible(EnemyAgent enemy) { if (!_settings.SearchIgnoreInvisibility && (enemy.RequireTagForDetection || _settings.SearchTagOnly)) { return enemy.IsTagged; } return true; } private void ResetWeakspotList() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 if (_settings.TargetMode != TargetingMode.Weakspot) { return; } _weakspotList.Clear(); foreach (Dam_EnemyDamageLimb item in (Il2CppArrayBase)(object)_homingAgent.Damage.DamageLimbs) { if ((int)item.m_type == 1 && ((Component)(object)item).TryGetComp(out var result) && result.enabled) { _weakspotList.Add((result, (byte)item.m_limbID)); } } } private void UpdateHomingTarget() { if (_homingLimbID != 0 && _homingCollider.enabled) { return; } if (_settings.TargetMode != TargetingMode.Weakspot || _weakspotList.Count == 0) { _homingLimbID = 0; _homingCollider = null; _homingTarget = GetHomingTarget(_homingAgent); return; } _weakspotList.Sort(WeakspotCompare); _weakspotList.Reverse(); int num = _weakspotList.Count - 1; while (num >= 0) { var (val, homingLimbID) = _weakspotList[num]; if ((Object)(object)val == (Object)null || !val.enabled) { _weakspotList.RemoveAt(num); num--; continue; } _homingLimbID = homingLimbID; _homingCollider = val; _homingTarget = ((Component)val).transform; return; } _homingTarget = ((Agent)_homingAgent).AimTarget; _homingCollider = null; _homingLimbID = 0; } private int WeakspotCompare((Collider collider, byte _) x, (Collider collider, byte _) y) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) float num = Vector3.Angle(s_dir, ((Component)x.collider).transform.position - s_position); float num2 = Vector3.Angle(s_dir, ((Component)y.collider).transform.position - s_position); if (num == num2) { return 0; } if (!(num < num2)) { return 1; } return -1; } private Transform GetHomingTarget(EnemyAgent enemy) { if (_settings.TargetMode != TargetingMode.Body) { return ((Agent)enemy).AimTarget; } return ((Agent)enemy).AimTargetBody; } private Vector3 GetHomingTargetPos(EnemyAgent enemy) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return GetHomingTarget(enemy).position; } private bool IsTargetReachable(AIG_CourseNode? source, AIG_CourseNode? target) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Invalid comparison between Unknown and I4 //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Invalid comparison between Unknown and I4 //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Invalid comparison between Unknown and I4 //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Invalid comparison between Unknown and I4 if (source == null || target == null) { return false; } if (source.NodeID == target.NodeID) { return true; } AIG_SearchID.IncrementSearchID(); ushort searchID = AIG_SearchID.SearchID; s_nodeQueue.Enqueue(source); while (s_nodeQueue.Count > 0) { AIG_CourseNode val = s_nodeQueue.Dequeue(); ((AIG_CourseGraphMember)val).m_searchID = searchID; Enumerator enumerator = val.m_portals.GetEnumerator(); while (enumerator.MoveNext()) { AIG_CoursePortal current = enumerator.Current; iLG_Door_Core val2 = current.m_door; WallPierce? wallPierce = _wallPierce; if ((wallPierce == null || !wallPierce.RequireOpenPath) && val2 != null && (int)val2.DoorType != 2 && (int)val2.DoorType != 3) { val2 = null; } if (val2 == null || (int)val2.LastStatus == 10 || (int)val2.LastStatus == 16 || (int)val2.LastStatus == 11) { AIG_CourseNode oppositeNode = current.GetOppositeNode(val); if (oppositeNode.NodeID == target.NodeID) { s_nodeQueue.Clear(); return true; } if (((AIG_CourseGraphMember)oppositeNode).m_searchID != searchID) { s_nodeQueue.Enqueue(oppositeNode); } } } } s_nodeQueue.Clear(); return false; } } } namespace EWC.CustomWeapon.Properties.Shared.UI { public sealed class UIData { public string FormatString { get; private set; } } } namespace EWC.CustomWeapon.Properties.Shared.Triggers { public sealed class ActivateHolder : TriggerHolder { private readonly List _accumulatedTriggers = new List(); private uint _applyCount; private List? _applyDelays; private Queue? _delayedApplies; public float CooldownOnApply { get; private set; } public uint CooldownOnApplyThreshold { get; private set; } = 1u; public bool ApplyAboveThreshold { get; private set; } public float ApplyOverrideAmount { get; private set; } public ActivateHolder(TriggerCoordinator parent, params ITrigger[] triggers) : base(parent, triggers) { } public override TriggerHolder Clone(TriggerCoordinator parent) { ActivateHolder obj = (ActivateHolder)base.Clone(parent); obj._applyDelays = _applyDelays; obj._delayedApplies = ((_delayedApplies != null) ? new Queue() : null); return obj; } public void ApplyTriggers() { if (ApplyAboveThreshold) { int num = 0; float num2 = 0f; while ((num2 += _accumulatedTriggers[num].triggerAmt) < base.Threshold) { num++; } _accumulatedTriggers.RemoveRange(0, num); } List list; if (ApplyOverrideAmount > 0f) { list = new List((int)ApplyOverrideAmount); float num3 = 0f; int num4 = _accumulatedTriggers.Count - 1; while (num4 >= 0 && num3 < ApplyOverrideAmount) { num3 += _accumulatedTriggers[num4].triggerAmt; list.Add(_accumulatedTriggers[num4]); num4--; } if (num3 != ApplyOverrideAmount) { List list2 = list; TriggerContext value = list2[list2.Count - 1]; value.triggerAmt += ApplyOverrideAmount - num3; List list3 = list; list3[list3.Count - 1] = value; } } else { list = new List(_accumulatedTriggers); } _triggerSum = 0f; _accumulatedTriggers.Clear(); if (++_applyCount >= CooldownOnApplyThreshold) { SetCooldown(CooldownOnApply); _applyCount = 0u; } DoApply(list); } private void DoApply(List triggerContexts) { List triggerContexts2 = triggerContexts; if (_applyDelays != null) { foreach (float applyDelay in _applyDelays) { DelayedCallback delayedCallback = new DelayedCallback(applyDelay, delegate { base.Caller?.TriggerApply(triggerContexts2); if (_delayedApplies.Count > 0) { _delayedApplies.Dequeue(); } }); _delayedApplies.Enqueue(delayedCallback); StartDelayedCallback(delayedCallback); } return; } base.Caller?.TriggerApply(triggerContexts2); } public override void Reset(bool resetAccumulated = true) { if (resetAccumulated) { _accumulatedTriggers.Clear(); _applyCount = 0u; } if (_delayedApplies != null) { DelayedCallback result; while (_delayedApplies.TryDequeue(out result)) { result.Cancel(); } } base.Reset(resetAccumulated); } protected override void DelayedReset() { _accumulatedTriggers.Clear(); base.DelayedReset(); } protected override void OnAddTrigger(WeaponTriggerContext context, float amount) { _accumulatedTriggers.Add(new TriggerContext { triggerAmt = amount, context = context }); } protected override void OnCancel() { if (base.CancelReduceAmount > 0f && _accumulatedTriggers.Count > 0) { int num = _accumulatedTriggers.Count - 1; float num2 = 0f; while (num > 0 && (num2 += _accumulatedTriggers[num].triggerAmt) < base.CancelReduceAmount) { num--; } _accumulatedTriggers.RemoveRange(num, _accumulatedTriggers.Count - num - 1); } else { _accumulatedTriggers.Clear(); } if (base.CancelDelay && _delayedApplies != null) { DelayedCallback result; while (_delayedApplies.TryDequeue(out result)) { result.Cancel(); } } base.OnCancel(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 11: { char c = property[5]; if (c != 'a') { if (c != 'd' || !(property == "applydelays")) { return; } goto IL_010e; } if (!(property == "applyamount")) { return; } break; } case 19: switch (property[5]) { default: return; case 'a': if (property == "applyabovethreshold") { ApplyAboveThreshold = reader.GetBoolean(); } return; case 'o': break; } if (!(property == "applyoverrideamount")) { return; } break; case 10: if (!(property == "applydelay")) { return; } goto IL_010e; case 6: if (!(property == "delays")) { return; } goto IL_010e; case 5: if (!(property == "delay")) { return; } goto IL_010e; case 15: if (property == "cooldownonapply") { CooldownOnApply = reader.GetSingle(); } return; case 24: if (property == "cooldownonapplythreshold") { CooldownOnApplyThreshold = Math.Max(reader.GetUInt32(), 1u); } return; default: return; IL_010e: if (reader.TokenType == JsonTokenType.Number) { _applyDelays = new List(1) { reader.GetSingle() }; } else { _applyDelays = EWCJson.Deserialize>(ref reader); } if (_applyDelays.Count == 0 || !_applyDelays.Any((float val) => val > 0f)) { _applyDelays = null; return; } _applyDelays.Sort(); _delayedApplies = new Queue(); return; } ApplyOverrideAmount = reader.GetSingle(); } } public enum TriggerName { Empty, PreFire, Fire, StartFiring, EndFiring, Aim, AimEnd, ReloadStart, Reload, ChargeStart, ChargeEnd, Unwield, Wield, PrePush, Push, PushHit, BulletLanded, ChargeLanded, Hit, PreHit, Charge, Damage, Backstab, Stagger, Kill, Miss, HitTaken, DamageTaken, Health, Clip, Crouch, CrouchEnd, Sprint, SprintEnd, Jump, JumpEnd, PerTarget, Key, Reference, Init } public interface ITrigger { static readonly TriggerName[] HitTriggers = new TriggerName[9] { TriggerName.Empty, TriggerName.PushHit, TriggerName.PreHit, TriggerName.Hit, TriggerName.Charge, TriggerName.Damage, TriggerName.Backstab, TriggerName.Stagger, TriggerName.PerTarget }; TriggerName Name { get; } bool StoreZeroAmount => false; bool Invoke(WeaponTriggerContext context, out float amount); void Reset(); void OnPropertiesSetup(CustomWeaponComponent cwc) { } ITrigger Clone(); void DeserializeProperty(string property, ref Utf8JsonReader reader); static ITrigger GetTrigger(TriggerName triggerName) { return GetTrigger(triggerName.ToString()); } static ITrigger? GetTrigger(string? name) { if (name == null) { return null; } string text = name; string text2 = name.ToLowerInvariant().Replace(" ", null); string text3; if (!text2.StartsWith("on")) { text3 = text2; } else { string text4 = text2; text3 = text4.Substring(2, text4.Length - 2); } name = text3; string text5 = name; switch (text5) { default: if (text5 != null) { if (text5.StartsWith("reference")) { string text4 = text.TrimStart(' '); int length = "reference".Length; return new ReferenceCallTrigger(text4.Substring(length, text4.Length - length)); } if (text5.StartsWith("key")) { return DetermineKeyTrigger(name); } if (text5.ContainsAny("setup", "init", "drop")) { return new InitTrigger(name); } string text6 = text5; if (text6.Contains("sync")) { return DetermineModSyncTrigger(text, text6); } if (text5.StartsWith("per")) { return DeterminePerTargetTrigger(name); } if (text5.Contains("hittaken")) { return new PlayerDamageTypeTrigger(TriggerName.HitTaken, name.ToPlayerDamageTypes()); } if (text5.Contains("damagetaken")) { return new DamageTakenTrigger(name.ToPlayerDamageTypes()); } string text7 = text5; if (text7.Contains("landed")) { return DetermineLandedTrigger(text7); } if (text5.Contains("prehit")) { return new DamageableTrigger(TriggerName.PreHit, name.ToDamageTypes()); } if (text5.Contains("hit")) { return new DamageableTrigger(TriggerName.Hit, name.ToDamageTypes()); } if (text5.Contains("miss")) { return new MissTrigger(name.ToDamageTypes()); } if (text5.Contains("charge")) { return new ChargeTrigger(name.ToDamageTypes()); } if (text5.Contains("backstab")) { return new BackstabTrigger(name.ToDamageTypes()); } if (text5.Contains("kill")) { return new KillTrigger(name.ToDamageTypes()); } if (text5.Contains("damage")) { return new DamageTrigger(name.ToDamageTypes()); } if (text5.ContainsAny("stagger", "stun")) { return new StaggerTrigger(name.ToDamageTypes()); } } return new ReferenceCallTrigger(text); case "invalid": case "null": return null; case "empty": return EmptyTrigger.Instance; case "prefire": case "preshot": case "preswing": return new BasicTrigger(TriggerName.PreFire); case "shot": case "fire": case "swing": return new BasicTrigger(TriggerName.Fire); case "startfiring": return new BasicTrigger(TriggerName.StartFiring); case "endfiring": case "stopfiring": return new BasicTrigger(TriggerName.EndFiring); case "pushhit": return new BasicTrigger(TriggerName.PushHit); case "prepush": return new BasicTrigger(TriggerName.PrePush); case "push": return new BasicTrigger(TriggerName.Push); case "aim": case "zoomin": return new BasicTrigger(TriggerName.Aim); case "zoomout": case "aimend": return new BasicTrigger(TriggerName.AimEnd); case "reloadstart": case "startreload": return new BasicTrigger(TriggerName.ReloadStart); case "reload": return new BasicTrigger(TriggerName.Reload); case "chargestart": return new BasicTrigger(TriggerName.ChargeStart); case "chargeend": return new ChargeEndTrigger(); case "unwield": return new BasicTrigger(TriggerName.Unwield); case "wield": return new BasicTrigger(TriggerName.Wield); case "health": return new HealthTrigger(); case "clip": case "mag": return new ClipTrigger(); case "crouch": return new BasicTrigger(TriggerName.Crouch); case "stand": case "uncrouch": case "crouchend": return new BasicTrigger(TriggerName.CrouchEnd); case "run": case "sprint": return new BasicTrigger(TriggerName.Sprint); case "sprintend": case "runend": return new BasicTrigger(TriggerName.SprintEnd); case "jump": return new BasicTrigger(TriggerName.Jump); case "jumpend": return new BasicTrigger(TriggerName.JumpEnd); } } private static ITrigger DetermineLandedTrigger(string name) { DamageType damageType = (name.Contains("shrapnel") ? DamageType.Shrapnel : DamageType.Bullet); if (name.Contains("terrain")) { damageType |= DamageType.Terrain; } if (!name.Contains("charge")) { return new BulletLandedTrigger(damageType); } return new ChargeLandedTrigger(damageType); } private static ITrigger? DeterminePerTargetTrigger(string name) { if (name == "pertarget") { return new PerTargetTrigger(); } int num = name.IndexOf("on", 3); if (num == -1) { return null; } ITrigger trigger = GetTrigger(name.Substring(3, num - 3)); if (trigger == null) { return null; } int num2 = num + 2; ITrigger trigger2 = GetTrigger(name.Substring(num2, name.Length - num2)); if (trigger2 == null) { return null; } return new PerTargetTrigger(trigger, trigger2); } private static ITrigger? DetermineModSyncTrigger(string origName, string name) { if (name == "modsync") { return new ModSyncTrigger(); } origName = origName.Replace(" ", null); int num = name.IndexOf("sync"); if (num == -1) { return null; } string text = origName.Substring(0, num); if (string.IsNullOrEmpty(text)) { return null; } int num2 = num + 4; ITrigger trigger = GetTrigger(name.Substring(num2, name.Length - num2)); if (trigger == null) { return null; } return new ModSyncTrigger(trigger, text); } private static ITrigger? DetermineKeyTrigger(string name) { //IL_010c: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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) string text = name; name = text.Substring(3, text.Length - 3); if (name.Length == 0) { return null; } bool onDown = true; int num; if ((num = name.IndexOf("down")) > -1) { if (num == 0) { text = name; name = text.Substring(4, text.Length - 4); } else { text = name; name = text.Substring(0, text.Length - 4); } } if ((num = name.IndexOf("up")) > -1) { onDown = false; if (num == 0) { text = name; name = text.Substring(2, text.Length - 2); } else { text = name; name = text.Substring(0, text.Length - 2); } } if (name.Length == 0) { return null; } KeyCode val; if (name.StartsWith("config")) { if (name.Length == 6) { return null; } val = (KeyCode)(name[6] switch { '1' => Configuration.Keybind1, '2' => Configuration.Keybind2, '3' => Configuration.Keybind3, '4' => Configuration.Keybind4, _ => 0, }); } else { val = name.ToEnum((KeyCode)0); } if ((int)val == 0) { return null; } return new KeyTrigger(val, onDown); } } public interface IDamageTypeTrigger : ITrigger { DamageType[] DamageTypes { get; } DamageType BlacklistType { get; set; } } public struct TriggerContext { public float triggerAmt; public WeaponTriggerContext context; } public interface ITriggerCallback : IWeaponProperty, IWeaponProperty { TriggerCoordinator? Trigger { get; set; } bool UseZeroAmountTrigger => false; void TriggerApply(List triggerList); void TriggerReset(); void RemoteReset() { if (Trigger != null) { Trigger.ForceReset(); } else { TriggerReset(); } } } public interface ITriggerCallbackSync : ITriggerCallback, IWeaponProperty, IWeaponProperty { ushort SyncID { get; set; } void TriggerResetSync(); } public interface ITriggerCallbackBasicSync : ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty { void TriggerApplySync(float mod); } public interface ITriggerCallbackDirSync : ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty { void TriggerApplySync(Vector3 position, Vector3 dir, float mod); } public interface ITriggerCallbackImpactSync : ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty { void TriggerApplySync(Vector3 position, Vector3 dir, Vector3 normal, float mod); } public interface ITriggerCallbackAgentSync : ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty { void TriggerApplySync(Agent target, float mod); } public interface ITriggerEvent { uint GetCallbackID(string callbackName); } public class TriggerEventHelper { private bool _isActive; private readonly Func? _callbackMap; public TriggerEventHelper(Func? callbackMap = null) { _callbackMap = callbackMap; } public uint GetCallbackID(string callbackName) { _isActive = true; callbackName = callbackName.Replace(" ", null).ToLowerInvariant(); return _callbackMap?.Invoke(callbackName) ?? 0; } public void Invoke(CustomWeaponComponent cwc, WeaponReferenceContext context) { if (_isActive) { cwc.Invoke(context); } } public void Invoke(ContextController cc, WeaponReferenceContext context) { if (_isActive) { cc.Invoke(context); } } } public sealed class ResetHolder : TriggerHolder { private DelayedCallback? _delayedApply; public float ApplyDelay { get; private set; } public ResetHolder(TriggerCoordinator parent, params ITrigger[] triggers) : base(parent, triggers) { } public override TriggerHolder Clone(TriggerCoordinator parent) { ResetHolder resetHolder = (ResetHolder)base.Clone(parent); resetHolder._delayedApply = ((_delayedApply != null) ? new DelayedCallback(ApplyDelay, resetHolder.ApplyReset) : null); return resetHolder; } public void ResetTriggers(bool resetAccumulated = true) { _triggerSum = 0f; if (ApplyDelay > 0f) { StartDelayedCallback(_delayedApply, checkEnd: true, refresh: false); } else { DoReset(resetAccumulated); } } public void DoReset(bool resetAccumulated = true) { base.Caller?.TriggerReset(); Parent.Activate.Reset(resetAccumulated); Reset(resetAccumulated); } public void ApplyReset() { DoReset(); } protected override void OnCancel() { if (base.CancelDelay && ApplyDelay > 0f) { _delayedApply.Cancel(); } base.OnCancel(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "applydelay" || property == "delay") { ApplyDelay = reader.GetSingle(); if (ApplyDelay > 0f) { _delayedApply = new DelayedCallback(ApplyDelay, ApplyReset); } } } } public sealed class TriggerCallbackSyncDummy : WeaponPropertyBase, ITriggerCallbackBasicSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty, ITriggerCallbackDirSync, ITriggerCallbackImpactSync, ITriggerCallbackAgentSync { public static readonly TriggerCallbackSyncDummy Instance = new TriggerCallbackSyncDummy(); public ushort SyncID { get; set; } public TriggerCoordinator? Trigger { get; set; } public override WeaponPropertyBase Clone() { return this; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { } public void Invoke(WeaponTriggerContext context) { } public override void Serialize(Utf8JsonWriter writer) { } public void TriggerApply(List triggerList) { } public void TriggerApplySync(Vector3 position, Vector3 dir, float mod) { } public void TriggerApplySync(Vector3 position, Vector3 dir, Vector3 normal, float mod) { } public void TriggerApplySync(Agent target, float mod) { } public void TriggerApplySync(float mod) { } public void TriggerReset() { } public void TriggerResetSync() { } } public sealed class TriggerCoordinator { public ITriggerCallback? Parent { get; set; } public ActivateHolder Activate { get; private set; } public ResetHolder? Reset { get; private set; } public bool ResetPreviousOnly { get; private set; } public TriggerCoordinator(params ITrigger[] triggers) { Activate = new ActivateHolder(this, triggers); } public TriggerCoordinator Clone() { TriggerCoordinator triggerCoordinator = CopyUtil.Clone(this); triggerCoordinator.Activate = (ActivateHolder)Activate.Clone(triggerCoordinator); triggerCoordinator.Reset = (ResetHolder)(Reset?.Clone(triggerCoordinator)); return triggerCoordinator; } public void OnPropertiesSetup() { Activate.OnPropertiesSetup(); Reset?.OnPropertiesSetup(); } public void Invoke(WeaponTriggerContext context) { bool flag = Activate.Invoke(context); bool flag2 = Reset?.Invoke(context) ?? false; if (ResetPreviousOnly && flag2) { Reset.ResetTriggers(!flag); } if (flag) { Activate.ApplyTriggers(); } if (!ResetPreviousOnly && flag2) { Reset.ResetTriggers(); } } public void RemoteActivateTrigger(List contexts) { if (Activate.RemoteActivate(contexts)) { Activate.ApplyTriggers(); } } public void RemoteResetTrigger(List contexts) { if (Reset != null && Reset.RemoteActivate(contexts)) { Reset.ResetTriggers(); } } public void ForceReset() { Parent?.TriggerReset(); Activate.Reset(); Reset?.Reset(); } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { string text = property; switch (text) { case "activate": case "triggers": case "trigger": Activate.DeserializeTriggerList(ref reader); return; case "resetpreviousonly": case "resetprevious": ResetPreviousOnly = reader.GetBoolean(); return; } if (text != null && text.StartsWith("reset")) { if (Reset == null) { ResetHolder resetHolder2 = (Reset = new ResetHolder(this)); } if (property == "reset") { Reset.DeserializeTriggerList(ref reader); return; } ResetHolder? reset = Reset; string text2 = property; int length = "reset".Length; reset.DeserializeProperty(text2.Substring(length, text2.Length - length), ref reader); } else { if (property.StartsWith("activate")) { string text2 = property; int length = "activate".Length; property = text2.Substring(length, text2.Length - length); } Activate.DeserializeProperty(property, ref reader); } } public static TriggerCoordinator? Deserialize(ref Utf8JsonReader reader, bool allowEmptyActivate = false) { TriggerCoordinator triggerCoordinator = EWCJson.Deserialize(ref reader); if (triggerCoordinator == null) { return null; } if (!allowEmptyActivate && triggerCoordinator.Activate.Triggers.Count == 0) { return null; } return triggerCoordinator; } } public abstract class TriggerHolder { private static readonly Random Random = new Random(); public readonly TriggerCoordinator Parent; private readonly DelayedCallback _delayedReset; protected float _triggerSum; protected float _triggerCount; protected float _nextTriggerTime; protected bool _allow = true; public List Triggers { get; private set; } public float Cap { get; private set; } public float Threshold { get; private set; } public float Cooldown { get; private set; } public float CooldownThreshold { get; private set; } public float Chance { get; private set; } = 1f; public float ResetDelay { get; private set; } public bool ConsumeThreshold { get; private set; } public float ThresholdOffset { get; private set; } public bool AllowOnce { get; private set; } public List? Apply { get; private set; } public List? Cancel { get; private set; } public float CancelReduceAmount { get; private set; } public bool CancelDelay { get; private set; } public ITriggerCallback? Caller => Parent.Parent; public TriggerHolder(TriggerCoordinator parent, params ITrigger[] triggers) { Parent = parent; Triggers = new List(triggers); _delayedReset = new DelayedCallback(() => ResetDelay, DelayedReset); } public void OnPropertiesSetup() { if (Caller == null) { return; } CustomWeaponComponent cWC = Caller.CWC; foreach (ITrigger trigger in Triggers) { trigger.OnPropertiesSetup(cWC); } foreach (ITrigger item in Apply.OrEmptyIfNull()) { item.OnPropertiesSetup(cWC); } foreach (ITrigger item2 in Cancel.OrEmptyIfNull()) { item2.OnPropertiesSetup(cWC); } _triggerSum = ((Threshold > 0f) ? (ThresholdOffset % Threshold) : 0f); } public virtual TriggerHolder Clone(TriggerCoordinator parent) { TriggerHolder triggerHolder = CopyUtil.Clone(this, parent); triggerHolder.Triggers = Triggers.ConvertAll((ITrigger trigger) => trigger.Clone()); triggerHolder.Apply = Apply?.ConvertAll((ITrigger trigger) => trigger.Clone()); triggerHolder.Cancel = Cancel?.ConvertAll((ITrigger trigger) => trigger.Clone()); return triggerHolder; } public bool Invoke(WeaponTriggerContext context) { bool flag = _triggerSum > 0f; if (_allow && Clock.Time >= _nextTriggerTime && (Cap == 0f || _triggerSum < Cap) && (Chance == 1f || Chance > Random.NextSingle())) { foreach (ITrigger trigger in Triggers) { if (!trigger.Invoke(context, out var amount)) { continue; } if (ResetDelay > 0f) { StartDelayedCallback(_delayedReset, checkEnd: true); } if (amount > 0f) { goto IL_00c9; } if (trigger.StoreZeroAmount) { ITriggerCallback? caller = Caller; if (caller != null && caller.UseZeroAmountTrigger) { goto IL_00c9; } } goto IL_00d3; IL_00c9: flag = true; AddTrigger(context, amount); goto IL_00d3; IL_00d3: if (Cap > 0f && _triggerSum >= Cap) { break; } } } if (flag & (_triggerSum >= Threshold)) { if (Apply == null) { _allow = !AllowOnce; if (ConsumeThreshold) { _triggerSum -= Threshold; } return true; } foreach (ITrigger item in Apply) { if (item.Invoke(context, out var amount2) && amount2 > 0f) { _allow = !AllowOnce; if (ConsumeThreshold) { _triggerSum -= Threshold; } return true; } } } if (Cancel != null) { foreach (ITrigger item2 in Cancel) { if (item2.Invoke(context, out var amount3) && amount3 > 0f) { OnCancel(); return false; } } } return false; } public bool RemoteActivate(List contexts) { if (!_allow) { return false; } foreach (TriggerContext context in contexts) { if (Cap > 0f && _triggerSum >= Cap) { break; } AddTrigger(context.context, context.triggerAmt); } if (_triggerSum >= Threshold) { _allow = !AllowOnce; if (ConsumeThreshold) { _triggerSum -= Threshold; } return true; } return false; } private void AddTrigger(WeaponTriggerContext context, float triggerAmt) { OnAddTrigger(context, triggerAmt); _triggerCount += triggerAmt; _triggerSum += triggerAmt; if (_triggerCount >= CooldownThreshold) { SetCooldown(Cooldown); _triggerCount = 0f; } } protected void SetCooldown(float time) { _nextTriggerTime = Math.Max(Clock.Time + time, _nextTriggerTime); } public virtual void Reset(bool resetAccumulated = true) { if (resetAccumulated) { _triggerSum = 0f; } _triggerCount = 0f; _delayedReset.Cancel(); _allow = true; Triggers.ForEach(delegate(ITrigger trigger) { trigger.Reset(); }); Apply?.ForEach(delegate(ITrigger trigger) { trigger.Reset(); }); Cancel?.ForEach(delegate(ITrigger trigger) { trigger.Reset(); }); } protected virtual void DelayedReset() { _triggerSum = 0f; _triggerCount = 0f; Triggers.ForEach(delegate(ITrigger trigger) { trigger.Reset(); }); Apply?.ForEach(delegate(ITrigger trigger) { trigger.Reset(); }); Cancel?.ForEach(delegate(ITrigger trigger) { trigger.Reset(); }); } protected virtual void OnAddTrigger(WeaponTriggerContext context, float amount) { } protected virtual void OnCancel() { if (CancelReduceAmount > 0f) { _triggerSum = Math.Max(0f, _triggerSum - CancelReduceAmount); } else { _triggerSum = 0f; } } protected void StartDelayedCallback(DelayedCallback callback, bool checkEnd = false, bool refresh = true) { if (Caller != null && (Object)(object)Caller.CWC != (Object)null) { Caller.CWC.StartDelayedCallback(callback, checkEnd, refresh); } else { callback.Start(checkEnd, refresh); } } public virtual void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == null) { return; } switch (property.Length) { default: return; case 9: switch (property[0]) { case 't': if (property == "threshold") { Threshold = Math.Max(reader.GetSingle(), 0f); } break; case 'a': if (property == "allowonce") { AllowOnce = reader.GetBoolean(); } break; } return; case 6: switch (property[1]) { case 'h': if (property == "chance") { Chance = reader.GetSingle(); } break; case 'a': if (property == "cancel") { Cancel = DeserializeTriggers(ref reader); } break; } return; case 16: switch (property[1]) { default: return; case 'o': if (property == "consumethreshold") { ConsumeThreshold = reader.GetBoolean(); } return; case 'a': break; } if (!(property == "cancelapplydelay")) { return; } break; case 3: if (property == "cap") { Cap = reader.GetSingle(); } return; case 8: if (property == "cooldown") { Cooldown = reader.GetSingle(); } return; case 17: if (property == "cooldownthreshold") { CooldownThreshold = Math.Max(reader.GetSingle(), 0f); } return; case 10: if (property == "resetdelay") { ResetDelay = reader.GetSingle(); } return; case 15: if (property == "thresholdoffset") { ThresholdOffset = reader.GetSingle(); } return; case 5: if (property == "apply") { Apply = DeserializeTriggers(ref reader); } return; case 18: if (property == "cancelreduceamount") { CancelReduceAmount = reader.GetSingle(); } return; case 11: if (!(property == "canceldelay")) { return; } break; case 4: case 7: case 12: case 13: case 14: return; } CancelDelay = reader.GetBoolean(); } private static List? DeserializeTriggers(ref Utf8JsonReader reader) { if (reader.TokenType == JsonTokenType.String || reader.TokenType == JsonTokenType.StartObject) { ITrigger trigger = EWCJson.Deserialize(ref reader); if (trigger == null) { return null; } return new List { trigger }; } if (reader.TokenType == JsonTokenType.StartArray) { List list = new List(); reader.Read(); while (reader.TokenType != JsonTokenType.EndArray) { ITrigger trigger2 = EWCJson.Deserialize(ref reader); reader.Read(); if (trigger2 != null) { list.Add(trigger2); } } return list; } throw new JsonException("Expected trigger or list of triggers when deserializing triggers for Coordinator"); } public void DeserializeTriggerList(ref Utf8JsonReader reader) { List list = DeserializeTriggers(ref reader); if (list != null) { Triggers = list; } } } public static class TriggerManager { private static readonly TriggerSync _triggerSync = new TriggerSync(); private static readonly TriggerDirSync _triggerDirSync = new TriggerDirSync(); private static readonly TriggerImpactSync _triggerImpactSync = new TriggerImpactSync(); private static readonly TriggerAgentSync _triggerAgentSync = new TriggerAgentSync(); private static readonly TriggerResetSync _resetSync = new TriggerResetSync(); private static readonly Dictionary<(OwnerType ownerType, InventorySlot slot), Queue> _queuedReceives = new Dictionary<(OwnerType, InventorySlot), Queue>(); public const float MaxMod = 256f; [InvokeOnAssetLoad] private static void Init() { _triggerSync.Setup(); _triggerDirSync.Setup(); _triggerImpactSync.Setup(); _triggerAgentSync.Setup(); _resetSync.Setup(); } [InvokeOnCleanup(false)] private static void Cleanup() { _queuedReceives.Clear(); } private static bool CheckInvalidCaller(ITriggerCallback caller) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)caller.CWC.Weapon.InventorySlot == 0) { PlayerAgent player = caller.CWC.Owner.Player; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(63, 2); defaultInterpolatedStringHandler.AppendLiteral("Attempting to send a trigger from "); ItemEquippable component = caller.CWC.Weapon.Component; defaultInterpolatedStringHandler.AppendFormatted((component != null) ? ((Object)component).name : null); defaultInterpolatedStringHandler.AppendLiteral(", but slot is None! (owner: "); defaultInterpolatedStringHandler.AppendFormatted(((Object)(object)player != (Object)null) ? player.Owner.NickName : "none"); defaultInterpolatedStringHandler.AppendLiteral(")"); EWCLogger.Warning(defaultInterpolatedStringHandler.ToStringAndClear()); return true; } return false; } internal static void RunQueuedReceives(CustomWeaponComponent cwc) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (_queuedReceives.TryGetValue((cwc.Owner.Type, cwc.Weapon.InventorySlot), out Queue value)) { Action result; while (value.TryDequeue(out result)) { result(); } } } public static void SendInstance(ITriggerCallbackBasicSync caller, float mod = 1f) { if (!CheckInvalidCaller(caller)) { _triggerSync.Send(PackInstance(caller, mod), null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveInstance(TriggerInstanceData data, bool storeOnFail = true) { if (TryGetTriggerSync(data, out ITriggerCallbackSync callback)) { ((ITriggerCallbackBasicSync)callback).TriggerApplySync(data.mod.Get(256f)); } else if (storeOnFail) { QueueReceive(data, delegate { Internal_ReceiveInstance(data, storeOnFail: false); }); } else { LogFailMessage(data); } } private static TriggerInstanceData PackInstance(ITriggerCallbackSync caller, float mod) { TriggerInstanceData result = default(TriggerInstanceData); result.cwc.Set(caller.CWC); result.mod.Set(mod, 256f); result.id = caller.SyncID; return result; } public static void SendInstance(ITriggerCallbackDirSync caller, Vector3 position, Vector3 dir, float mod = 1f) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!CheckInvalidCaller(caller)) { TriggerDirInstanceData packetData = default(TriggerDirInstanceData); packetData.position = position; packetData.dir.Value = dir; packetData.instance = PackInstance(caller, mod); _triggerDirSync.Send(packetData, null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveInstance(TriggerDirInstanceData data, bool storeOnFail = true) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (TryGetTriggerSync(data.instance, out ITriggerCallbackSync callback)) { ((ITriggerCallbackDirSync)callback).TriggerApplySync(data.position, data.dir.Value, data.instance.mod.Get(256f)); } else if (storeOnFail) { QueueReceive(data.instance, delegate { Internal_ReceiveInstance(data, storeOnFail: false); }); } else { LogFailMessage(data.instance); } } public static void SendInstance(ITriggerCallbackImpactSync caller, Vector3 position, Vector3 dir, Vector3 normal, float mod = 1f) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) if (!CheckInvalidCaller(caller)) { TriggerImpactInstanceData packetData = default(TriggerImpactInstanceData); packetData.position = position; packetData.dir.Value = dir; packetData.normal.Value = normal; packetData.instance = PackInstance(caller, mod); _triggerImpactSync.Send(packetData, null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveInstance(TriggerImpactInstanceData data, bool storeOnFail = true) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (TryGetTriggerSync(data.instance, out ITriggerCallbackSync callback)) { ((ITriggerCallbackImpactSync)callback).TriggerApplySync(data.position, data.dir.Value, data.normal.Value, data.instance.mod.Get(256f)); } else if (storeOnFail) { QueueReceive(data.instance, delegate { Internal_ReceiveInstance(data, storeOnFail: false); }); } else { LogFailMessage(data.instance); } } public static void SendInstance(ITriggerCallbackAgentSync caller, Agent target, float mod = 1f) { if (!CheckInvalidCaller(caller)) { TriggerAgentInstanceData packetData = default(TriggerAgentInstanceData); ((pAgent)(ref packetData.target)).Set(target); packetData.instance = PackInstance(caller, mod); _triggerAgentSync.Send(packetData, null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveInstance(TriggerAgentInstanceData data, bool storeOnFail = true) { Agent target = default(Agent); if (TryGetTriggerSync(data.instance, out ITriggerCallbackSync callback) && ((pAgent)(ref data.target)).TryGet(ref target)) { ((ITriggerCallbackAgentSync)callback).TriggerApplySync(target, data.instance.mod.Get(256f)); } else if (storeOnFail) { QueueReceive(data.instance, delegate { Internal_ReceiveInstance(data, storeOnFail: false); }); } else { LogFailMessage(data.instance); } } public static void SendReset(ITriggerCallbackSync caller) { if (!CheckInvalidCaller(caller)) { TriggerResetData packetData = default(TriggerResetData); packetData.cwc.Set(caller.CWC); packetData.id = caller.SyncID; _resetSync.Send(packetData, null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveReset(TriggerResetData data, bool storeOnFail = true) { if (TryGetTriggerSync(data, out ITriggerCallbackSync callback)) { callback.TriggerResetSync(); } else if (storeOnFail) { QueueReceive(data, delegate { Internal_ReceiveReset(data, storeOnFail: false); }); } else { LogFailMessage(data); } } private static bool TryGetTriggerSync(TriggerInstanceData data, [MaybeNullWhen(false)] out ITriggerCallbackSync callback) { return TryGetTriggerSync(data.cwc, data.id, out callback); } private static bool TryGetTriggerSync(TriggerResetData data, [MaybeNullWhen(false)] out ITriggerCallbackSync callback) { return TryGetTriggerSync(data.cwc, data.id, out callback); } private static bool TryGetTriggerSync(pCWC packet, ushort id, [MaybeNullWhen(false)] out ITriggerCallbackSync callback) { if (!packet.TryGet(out CustomWeaponComponent comp)) { callback = null; return false; } callback = comp.GetTriggerSync(id); return true; } private static void QueueReceive(TriggerInstanceData instance, Action onProcess) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) (OwnerType, InventorySlot) key = (instance.cwc.ownerType, instance.cwc.slot); if (!_queuedReceives.TryGetValue(key, out Queue value)) { _queuedReceives.Add(key, value = new Queue()); } value.Enqueue(onProcess); } private static void QueueReceive(TriggerResetData instance, Action onProcess) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) (OwnerType, InventorySlot) key = (instance.cwc.ownerType, instance.cwc.slot); if (!_queuedReceives.TryGetValue(key, out Queue value)) { _queuedReceives.Add(key, value = new Queue()); } value.Enqueue(onProcess); } private static void LogFailMessage(TriggerInstanceData instance) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) EWCLogger.Error($"Unable to get custom weapon for {(instance.cwc.TryGetPlayer(out PlayerAgent comp) ? comp.Owner.NickName : "No Player")} on slot {instance.cwc.slot} (Owner Type: {instance.cwc.ownerType})"); } private static void LogFailMessage(TriggerResetData instance) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) EWCLogger.Error($"Unable to get custom weapon for {(instance.cwc.TryGetPlayer(out PlayerAgent comp) ? comp.Owner.NickName : "No Player")} on slot {instance.cwc.slot} (Owner Type: {instance.cwc.ownerType})"); } } public struct TriggerInstanceData { public pCWC cwc; public UFloat16b mod; public ushort id; } public struct TriggerDirInstanceData { public Vector3 position; public Vector3_24b_Normalized dir; public TriggerInstanceData instance; } public struct TriggerImpactInstanceData { public Vector3 position; public Vector3_24b_Normalized dir; public Vector3_24b_Normalized normal; public TriggerInstanceData instance; } public struct TriggerAgentInstanceData { public pAgent target; public TriggerInstanceData instance; } public struct TriggerResetData { public pCWC cwc; public ushort id; } public sealed class BackstabTrigger : DamageableTrigger { public float Min { get; private set; } public float Max { get; private set; } = 1f; public float Exponent { get; private set; } = 1f; public BackstabTrigger(params DamageType[] types) : base(TriggerName.Backstab, types) { } protected override float InvokeInternal(WeaponHitDamageableContext context) { return base.Amount * (context.OrigBackstab - 1f).Map(base.MinBackstabRequired, base.MaxBackstabRequired, Min, Max, Exponent); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { switch (property) { case "min": Min = reader.GetSingle(); break; case "max": Max = reader.GetSingle(); break; case "minrequired": case "minreq": case "maxrequired": case "maxreq": base.DeserializeProperty(property.Substring(0, 3) + "backstab" + property.Substring(3, property.Length - 3), ref reader); break; default: base.DeserializeProperty(property, ref reader); break; } } } public sealed class BasicTrigger : ITrigger where TContext : WeaponTriggerContext { public TriggerName Name { get; } public float Amount { get; private set; } = 1f; public BasicTrigger(TriggerName name) { Name = name; } public bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (context is TContext) { amount = Amount; return true; } return false; } public void Reset() { } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == "triggeramount" || property == "amount") { Amount = reader.GetSingle(); } } } public sealed class BulletLandedTrigger : DamageTypeTrigger { public BulletLandedTrigger(params DamageType[] damageTypes) : base(TriggerName.BulletLanded, damageTypes) { } public override bool Invoke(WeaponTriggerContext context, out float amount) { if (base.Invoke(context, out amount) && (context is WeaponHitContext || context is WeaponHitDamageableContext)) { return true; } amount = 0f; return false; } } public sealed class ChargeEndTrigger : ITrigger { public TriggerName Name => TriggerName.ChargeEnd; public float Amount { get; private set; } = 1f; public float Min { get; private set; } public float Max { get; private set; } = 1f; public float Exponent { get; private set; } = 3f; public float MinRequired { get; private set; } public float MaxRequired { get; private set; } = 1f; public bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (!(context is WeaponChargeEndContext weaponChargeEndContext)) { return false; } float charge = weaponChargeEndContext.Charge; if (charge >= MinRequired && charge <= MaxRequired) { charge = charge.Map(MinRequired, MaxRequired, Min, Max, Exponent); amount = charge * Amount; return true; } return false; } public void Reset() { } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == null) { return; } int length = property.Length; if (length <= 6) { if (length == 3) { switch (property[1]) { case 'i': if (property == "min") { Min = reader.GetSingle(); } break; case 'a': if (property == "max") { Max = reader.GetSingle(); } break; } return; } if (length != 6) { return; } char c = property[1]; if (c != 'a') { if (c != 'i') { if (c != 'm' || !(property == "amount")) { return; } goto IL_00ee; } if (!(property == "minreq")) { return; } goto IL_0122; } if (!(property == "maxreq")) { return; } } else { if (length == 8) { if (property == "exponent") { Exponent = reader.GetSingle(); } return; } if (length != 11) { if (length != 13 || !(property == "triggeramount")) { return; } goto IL_00ee; } char c = property[1]; if (c != 'a') { if (c != 'i' || !(property == "minrequired")) { return; } goto IL_0122; } if (!(property == "maxrequired")) { return; } } MaxRequired = reader.GetSingle(); return; IL_00ee: Amount = reader.GetSingle(); return; IL_0122: MinRequired = reader.GetSingle(); } } public sealed class ChargeLandedTrigger : DamageTypeTrigger { public float Min { get; private set; } public float Max { get; private set; } = 1f; public float Exponent { get; private set; } = 3f; public float MinRequired { get; private set; } public float MaxRequired { get; private set; } = 1f; public ChargeLandedTrigger(params DamageType[] damageTypes) : base(TriggerName.ChargeLanded, damageTypes) { } public override bool Invoke(WeaponTriggerContext context, out float amount) { float cachedCharge = MeleePatches.CachedCharge; if (cachedCharge >= MinRequired && cachedCharge <= MaxRequired && base.Invoke(context, out amount) && (context is WeaponHitContext || context is WeaponHitDamageableContext)) { cachedCharge = cachedCharge.Map(MinRequired, MaxRequired, Min, Max, Exponent); amount *= cachedCharge; return true; } amount = 0f; return false; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } int length = property.Length; if (length <= 6) { if (length == 3) { switch (property[1]) { case 'i': if (property == "min") { Min = reader.GetSingle(); } break; case 'a': if (property == "max") { Max = reader.GetSingle(); } break; } return; } if (length != 6) { return; } char c = property[1]; if (c != 'a') { if (c != 'i' || !(property == "minreq")) { return; } goto IL_00ee; } if (!(property == "maxreq")) { return; } } else { if (length == 8) { if (property == "exponent") { Exponent = reader.GetSingle(); } return; } if (length != 11) { return; } char c = property[1]; if (c != 'a') { if (c != 'i' || !(property == "minrequired")) { return; } goto IL_00ee; } if (!(property == "maxrequired")) { return; } } MaxRequired = reader.GetSingle(); return; IL_00ee: MinRequired = reader.GetSingle(); } } public sealed class ChargeTrigger : DamageableTrigger { public float Min { get; private set; } public float Max { get; private set; } = 1f; public float Exponent { get; private set; } = 3f; public float MinRequired { get; private set; } public float MaxRequired { get; private set; } = 1f; public ChargeTrigger(params DamageType[] types) : base(TriggerName.Charge, types) { } protected override float InvokeInternal(WeaponHitDamageableContext context) { float cachedCharge = MeleePatches.CachedCharge; if (cachedCharge >= MinRequired && cachedCharge <= MaxRequired) { cachedCharge = cachedCharge.Map(MinRequired, MaxRequired, Min, Max, Exponent); return cachedCharge * base.Amount; } return 0f; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } int length = property.Length; if (length <= 6) { if (length == 3) { switch (property[1]) { case 'i': if (property == "min") { Min = reader.GetSingle(); } break; case 'a': if (property == "max") { Max = reader.GetSingle(); } break; } return; } if (length != 6) { return; } char c = property[1]; if (c != 'a') { if (c != 'i' || !(property == "minreq")) { return; } goto IL_00ee; } if (!(property == "maxreq")) { return; } } else { if (length == 8) { if (property == "exponent") { Exponent = reader.GetSingle(); } return; } if (length != 11) { return; } char c = property[1]; if (c != 'a') { if (c != 'i' || !(property == "minrequired")) { return; } goto IL_00ee; } if (!(property == "maxrequired")) { return; } } MaxRequired = reader.GetSingle(); return; IL_00ee: MinRequired = reader.GetSingle(); } } public sealed class ClipTrigger : ITrigger { public TriggerName Name { get; } = TriggerName.Clip; public float Amount { get; private set; } = 1f; public float AmountAtMin { get; private set; } = 1f; public float AmountAtMax { get; private set; } = 1f; public int ClipMin { get; private set; } public int ClipMax { get; private set; } = 1; public float ClipMinRel { get; private set; } = -1f; public float ClipMaxRel { get; private set; } = -1f; public float Exponent { get; private set; } = 1f; public bool FlipExponent { get; private set; } public bool StoreZeroAmount => true; public bool Invoke(WeaponTriggerContext context, out float amount) { if (context is WeaponAmmoContext weaponAmmoContext) { amount = ((ClipMaxRel >= 0f) ? CalculateAmount(weaponAmmoContext.ClipRel) : CalculateAmount(weaponAmmoContext.Clip)); return true; } if (context is WeaponInitContext weaponInitContext) { IGunComp gunComp = (IGunComp)weaponInitContext.Weapon; amount = ((ClipMaxRel >= 0f) ? CalculateAmount((float)gunComp.GetCurrentClip() / (float)gunComp.GetMaxClip()) : CalculateAmount(gunComp.GetCurrentClip())); return true; } amount = 0f; return false; } private float CalculateAmount(int ammo) { return CalculateAmount(ammo, ClipMin, ClipMax); } private float CalculateAmount(float ammoRel) { return CalculateAmount(ammoRel, ClipMinRel, ClipMaxRel); } private float CalculateAmount(float val, float min, float max) { if (FlipExponent) { return Amount * val.MapInverted(min, max, AmountAtMin, AmountAtMax, Exponent); } return Amount * val.Map(min, max, AmountAtMin, AmountAtMax, Exponent); } public void Reset() { } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == null) { return; } switch (property.Length) { default: return; case 18: { char c = property[16]; if (c != 'a') { if (c != 'i' || !(property == "triggeramountatmin")) { return; } goto IL_018a; } if (!(property == "triggeramountatmax")) { return; } goto IL_0197; } case 11: { char c = property[9]; if (c != 'a') { if (c != 'i' || !(property == "amountatmin")) { return; } goto IL_018a; } if (!(property == "amountatmax")) { return; } goto IL_0197; } case 7: switch (property[5]) { case 'i': if (property == "clipmin") { ClipMin = reader.GetInt32(); } break; case 'a': if (property == "clipmax") { ClipMax = reader.GetInt32(); } break; } return; case 10: switch (property[5]) { case 'i': if (property == "clipminrel") { ClipMinRel = reader.GetSingle(); } break; case 'a': if (property == "clipmaxrel") { ClipMaxRel = reader.GetSingle(); } break; } return; case 13: if (!(property == "triggeramount")) { return; } goto IL_017d; case 6: if (!(property == "amount")) { return; } goto IL_017d; case 8: if (property == "exponent") { Exponent = reader.GetSingle(); } return; case 12: if (!(property == "flipexponent")) { return; } break; case 4: if (!(property == "flip")) { return; } break; case 5: case 9: case 14: case 15: case 16: case 17: return; IL_018a: AmountAtMin = reader.GetSingle(); return; IL_017d: Amount = reader.GetSingle(); return; IL_0197: AmountAtMax = reader.GetSingle(); return; } FlipExponent = reader.GetBoolean(); } } public class DamageableTrigger : DamageTypeTrigger where TContext : WeaponHitDamageableContextBase { private Dictionary? _uniqueCounts; public float MinBackstabRequired { get; set; } public float MaxBackstabRequired { get; set; } = 1f; public float UniqueThreshold { get; private set; } public float UniqueCap { get; private set; } public bool UniqueConsumeOnTrigger { get; private set; } = true; private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; protected override bool CloneObject => _uniqueCounts != null; public DamageableTrigger(TriggerName name, DamageType[] types) : base(name, types) { base.BlacklistType |= DamageType.Dead; } public override bool Invoke(WeaponTriggerContext context, out float amount) { if (!base.Invoke(context, out amount)) { return false; } TContext val = (TContext)context; float num = val.OrigBackstab - 1f; if (num < MinBackstabRequired || num > MaxBackstabRequired) { amount = 0f; return false; } amount = InvokeInternal(val); if (amount == 0f) { return false; } if (_uniqueCounts != null) { TempWrapper.Set(val.Damageable); if (!_uniqueCounts.ContainsKey(TempWrapper)) { _uniqueCounts.Keys.Where((BaseDamageableWrapper wrapper) => !wrapper.Alive).ToList().ForEach(delegate(BaseDamageableWrapper wrapper) { _uniqueCounts.Remove(wrapper); }); _uniqueCounts[new BaseDamageableWrapper(TempWrapper)] = 0f; } _uniqueCounts[TempWrapper] += amount; if (_uniqueCounts[TempWrapper] < UniqueThreshold || (UniqueCap > 0f && _uniqueCounts[TempWrapper] > UniqueCap)) { amount = 0f; return true; } if (UniqueConsumeOnTrigger) { _uniqueCounts[TempWrapper] -= UniqueThreshold; } } return true; } protected virtual float InvokeInternal(TContext context) { return base.Amount; } public override void Reset() { base.Reset(); _uniqueCounts?.Clear(); } public override ITrigger Clone() { if (!CloneObject) { return this; } DamageableTrigger obj = (DamageableTrigger)base.Clone(); obj._uniqueCounts = ((_uniqueCounts != null) ? new Dictionary() : null); return obj; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property) { case "minbackstabrequired": case "minbackstab": MinBackstabRequired = reader.GetSingle(); break; case "maxbackstabrequired": case "maxbackstab": MaxBackstabRequired = reader.GetSingle(); break; case "uniquethreshold": UniqueThreshold = reader.GetSingle(); break; case "uniquecap": UniqueCap = reader.GetSingle(); break; case "uniqueconsumeontrigger": case "uniquedecreaseontrigger": UniqueConsumeOnTrigger = reader.GetBoolean(); break; } if (_uniqueCounts == null && (UniqueThreshold > 0f || UniqueCap > 0f)) { _uniqueCounts = new Dictionary(); } } } public sealed class DamageTakenTrigger : PlayerDamageTypeTrigger { public float Cap { get; private set; } public DamageTakenTrigger(PlayerDamageType[] damageTypes) : base(TriggerName.DamageTaken, damageTypes) { } public override bool Invoke(WeaponTriggerContext context, out float amount) { if (base.Invoke(context, out amount)) { float damage = ((WeaponDamageTakenContext)context).Damage; amount = ((Cap > 0f) ? Math.Min(Cap, amount * damage) : (base.Amount * damage)); return true; } return false; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "cap") { Cap = reader.GetSingle(); } } } public sealed class DamageTrigger : DamageableTrigger { public float Cap { get; private set; } public bool ClampToHealth { get; private set; } = true; public bool IgnoreInnateMod { get; private set; } public DamageTrigger(params DamageType[] types) : base(TriggerName.Damage, types) { } protected override float InvokeInternal(WeaponHitDamageableContext context) { float num = context.Damage; if (IgnoreInnateMod) { num /= context.ShotInfo.ExternalDamageMod * context.ShotInfo.InnateDamageMod; } if (ClampToHealth && num > context.DamageClamped) { num = context.DamageClamped; } if (!(Cap > 0f)) { return num * base.Amount; } return Math.Min(Cap, num * base.Amount); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 3: if (property == "cap") { Cap = reader.GetSingle(); } return; case 13: if (!(property == "clamptohealth")) { return; } goto IL_00ae; case 5: if (!(property == "clamp")) { return; } goto IL_00ae; case 16: if (!(property == "ignoreinnatemods")) { return; } break; case 15: if (!(property == "ignoreinnatemod")) { return; } break; case 12: if (!(property == "ignorexpmods")) { return; } break; case 11: if (!(property == "ignorexpmod")) { return; } break; default: return; IL_00ae: ClampToHealth = reader.GetBoolean(); return; } IgnoreInnateMod = reader.GetBoolean(); } } public class DamageTypeTrigger : IDamageTypeTrigger, ITrigger where TContext : WeaponDamageTypeContext { public DamageType[] DamageTypes { get; } public DamageType BlacklistType { get; set; } public TriggerName Name { get; private set; } public float Amount { get; private set; } = 1f; public uint MaxPerShot { get; private set; } protected virtual bool CloneObject => false; public DamageTypeTrigger(TriggerName name, params DamageType[] types) { Name = name; DamageTypes = ((types.Length == 0) ? DamageTypeConst.Any : types); } public virtual bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (context is TContext val && !val.DamageType.HasAnyFlag(BlacklistType) && val.DamageType.HasFlagIn(DamageTypes) && (MaxPerShot == 0 || MaxPerShot > val.ShotInfo.TypeHits(DamageTypes, BlacklistType))) { amount = Amount; return true; } return false; } public virtual void Reset() { } public virtual ITrigger Clone() { if (!CloneObject) { return this; } DamageTypeTrigger obj = ((GetType().GetConstructor(new Type[1] { typeof(DamageType[]) }) != null) ? CopyUtil.Clone(this, DamageTypes) : CopyUtil.Clone(this, Name, DamageTypes)); obj.BlacklistType = BlacklistType; return obj; } public virtual void DeserializeProperty(string property, ref Utf8JsonReader reader) { switch (property) { case "triggeramount": case "amount": Amount = reader.GetSingle(); break; case "maxpershot": MaxPerShot = reader.GetUInt32(); break; } } } public sealed class EmptyTrigger : ITrigger { public static readonly EmptyTrigger Instance = new EmptyTrigger(); public TriggerName Name { get; } public bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; return false; } public void Reset() { } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { } } public sealed class HealthTrigger : ITrigger { public TriggerName Name { get; } = TriggerName.Health; public float Amount { get; private set; } = 1f; public float AmountAtMin { get; private set; } = 1f; public float AmountAtMax { get; private set; } = 1f; public float HealthMinRel { get; private set; } public float HealthMaxRel { get; private set; } = 1f; public float Exponent { get; private set; } = 1f; public bool FlipExponent { get; private set; } public bool StoreZeroAmount => true; public bool Invoke(WeaponTriggerContext context, out float amount) { if (context is WeaponHealthContext weaponHealthContext) { amount = CalculateAmount(weaponHealthContext.Health, weaponHealthContext.HealthMax); return true; } if (context is WeaponInitContext weaponInitContext) { PlayerAgent player = weaponInitContext.Owner.Player; if ((Object)(object)player == (Object)null) { amount = 0f; return false; } amount = CalculateAmount(((Dam_SyncedDamageBase)player.Damage).Health, ((Dam_SyncedDamageBase)player.Damage).HealthMax); return true; } amount = 0f; return false; } private float CalculateAmount(float health, float healthMax) { if (FlipExponent) { return Amount * (health / healthMax).MapInverted(HealthMinRel, HealthMaxRel, AmountAtMin, AmountAtMax, Exponent); } return Amount * (health / healthMax).Map(HealthMinRel, HealthMaxRel, AmountAtMin, AmountAtMax, Exponent); } public void Reset() { } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == null) { return; } switch (property.Length) { default: return; case 18: { char c = property[16]; if (c != 'a') { if (c != 'i' || !(property == "triggeramountatmin")) { return; } goto IL_0192; } if (!(property == "triggeramountatmax")) { return; } goto IL_019f; } case 11: { char c = property[9]; if (c != 'a') { if (c != 'i' || !(property == "amountatmin")) { return; } goto IL_0192; } if (!(property == "amountatmax")) { return; } goto IL_019f; } case 12: { char c = property[7]; if (c != 'a') { if (c != 'i') { if (c != 'o' || !(property == "flipexponent")) { return; } break; } if (!(property == "healthminrel")) { return; } goto IL_01ac; } if (!(property == "healthmaxrel")) { return; } goto IL_01b9; } case 9: { char c = property[7]; if (c != 'a') { if (c != 'i' || !(property == "healthmin")) { return; } goto IL_01ac; } if (!(property == "healthmax")) { return; } goto IL_01b9; } case 13: if (!(property == "triggeramount")) { return; } goto IL_0185; case 6: if (!(property == "amount")) { return; } goto IL_0185; case 8: if (property == "exponent") { Exponent = reader.GetSingle(); } return; case 4: if (!(property == "flip")) { return; } break; case 5: case 7: case 10: case 14: case 15: case 16: case 17: return; IL_0192: AmountAtMin = reader.GetSingle(); return; IL_0185: Amount = reader.GetSingle(); return; IL_019f: AmountAtMax = reader.GetSingle(); return; IL_01ac: HealthMinRel = reader.GetSingle(); return; IL_01b9: HealthMaxRel = reader.GetSingle(); return; } FlipExponent = reader.GetBoolean(); } } public class HitTrackerTrigger : DamageableTrigger where TContext : WeaponHitTrackerContextBase { public float MaxDelay { get; private set; } = 0.5f; public bool RequireLastHit { get; private set; } = true; public HitTrackerTrigger(TriggerName name, params DamageType[] types) : base(name, types) { } public override bool Invoke(WeaponTriggerContext context, out float amount) { if (!base.Invoke(context, out amount)) { return false; } TContext val = (TContext)context; if (val.Delay < MaxDelay && (!RequireLastHit || val.DidLastHit)) { return true; } amount = 0f; return false; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property) { case "maxdelay": case "delay": MaxDelay = reader.GetSingle(); break; case "requiredidkill": case "requirekill": case "requirelasthit": case "lasthit": RequireLastHit = reader.GetBoolean(); break; } } } public sealed class InitTrigger : ITrigger { private enum PlayerType { Any, Host, Client } private readonly PlayerType _type; public TriggerName Name => TriggerName.Init; public float Amount { get; private set; } = 1f; public InitTrigger(string jsonName) { jsonName = jsonName.ToLower(); if (jsonName.Contains("client")) { _type = PlayerType.Client; } else if (jsonName.Contains("host")) { _type = PlayerType.Host; } else { _type = PlayerType.Any; } } public bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (_type != 0 && SNet.IsMaster != (_type == PlayerType.Host)) { return false; } if (context is WeaponInitContext) { amount = Amount; return true; } return false; } public void Reset() { } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == "triggeramount" || property == "amount") { Amount = reader.GetSingle(); } } } public sealed class KeyTrigger : ITrigger { public TriggerName Name => TriggerName.Key; public float Amount { get; private set; } = 1f; public KeyCode Key { get; } public bool OnDown { get; } public KeyTrigger(KeyCode key, bool onDown) { //IL_0012: 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) Key = key; OnDown = onDown; } public bool Invoke(WeaponTriggerContext context, out float amount) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) amount = 0f; if (context is WeaponKeyContext weaponKeyContext && Key == weaponKeyContext.Key && OnDown == weaponKeyContext.IsDown) { amount = Amount; return true; } return false; } public void Reset() { } public void OnPropertiesSetup(CustomWeaponComponent cwc) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) cwc.RegisterKeyWatcher(Key); } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == "triggeramount" || property == "amount") { Amount = reader.GetSingle(); } } } public sealed class KillTrigger : HitTrackerTrigger { public KillTrigger(params DamageType[] types) : base(TriggerName.Kill, types) { base.BlacklistType &= ~DamageType.Dead; } } public sealed class MissTrigger : IDamageTypeTrigger, ITrigger { public TriggerName Name { get; } = TriggerName.Miss; public DamageType BaseType { get; } public DamageType[] DamageTypes { get; } public DamageType BlacklistType { get; set; } = DamageType.Dead; public float Amount { get; private set; } = 1f; public int RequiredHits { get; private set; } = 1; public MissTrigger(params DamageType[] types) { BaseType = types.GetBaseType(); DamageTypes = ((types.Length == 0) ? DamageTypeConst.Any : types); } public bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (context is WeaponShotEndContext weaponShotEndContext && !weaponShotEndContext.DamageType.HasAnyFlag(BlacklistType) && weaponShotEndContext.DamageType.HasFlag(BaseType) && weaponShotEndContext.DiffTypeHits(DamageTypes, BlacklistType) < (float)RequiredHits) { amount = Amount; return true; } return false; } public void Reset() { } public ITrigger Clone() { return this; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { switch (property) { case "triggeramount": case "amount": Amount = reader.GetSingle(); break; case "requiredhits": RequiredHits = reader.GetInt32(); break; } } } public sealed class ModSyncTrigger : ITrigger { private TriggerMod? _syncedMod; private static readonly TriggerName[] ValidActivates = ITrigger.HitTriggers.Remove(default(TriggerName)).Extend(TriggerName.Kill); public TriggerName Name => Activate.Name; public ITrigger Activate { get; private set; } public uint ID { get; private set; } public float Amount { get; private set; } = 1f; public float Cap { get; private set; } public float Threshold { get; private set; } public bool ApplyAboveThreshold { get; private set; } public bool OverrideAmount { get; private set; } private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; public ModSyncTrigger() { Activate = null; } public ModSyncTrigger(ITrigger trigger, uint id = 0u) { Activate = trigger; ID = id; } public ModSyncTrigger(ITrigger trigger, string id) : this(trigger) { ID = WeaponPropertyBase.StringIDToInt(id); } public bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (_syncedMod == null) { return false; } if (!Activate.Invoke(context, out var amount2)) { return false; } if (amount2 == 0f) { return true; } float stacks; if (context is WeaponHitDamageableContextBase weaponHitDamageableContextBase) { if (!_syncedMod.TryGetStacks(out stacks, TempWrapper.Set(weaponHitDamageableContextBase.Damageable))) { return false; } } else if (!_syncedMod.TryGetStacks(out stacks)) { return false; } stacks *= Amount; if (stacks < Threshold) { return false; } if (OverrideAmount) { amount = Amount; } else if (ApplyAboveThreshold) { amount = stacks - Threshold; } else { amount = stacks; } if (Cap > 0f && amount > Cap) { amount = Cap; } return true; } public void Reset() { } public void OnPropertiesSetup(CustomWeaponComponent cwc) { if (!cwc.TryGetProperty(ID, out WeaponPropertyBase property)) { return; } if (property is TriggerMod triggerMod) { if (!triggerMod.IsPerTarget || ValidActivates.Contains(Name)) { _syncedMod = triggerMod; return; } EWCLogger.Error($"Cannot sync with {triggerMod.GetType().Name} since trigger {Name} is not a hit trigger!"); } else { EWCLogger.Error("Cannot use " + property.GetType().Name + " as a synced mod!"); } } public ITrigger Clone() { ModSyncTrigger modSyncTrigger = CopyUtil.Clone(this); modSyncTrigger.Activate = Activate.Clone(); return modSyncTrigger; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == null) { return; } switch (property.Length) { case 11: { char c = property[0]; if (c != 'a') { if (c != 'r' || !(property == "referenceid")) { break; } goto IL_0172; } if (!(property == "applyamount")) { break; } goto IL_01c1; } case 19: switch (property[5]) { default: return; case 'a': if (property == "applyabovethreshold") { ApplyAboveThreshold = reader.GetBoolean(); } return; case 'o': break; } if (!(property == "applyoverrideamount")) { break; } goto IL_01c1; case 7: if (!(property == "trigger")) { break; } goto IL_0153; case 8: if (!(property == "activate")) { break; } goto IL_0153; case 2: if (!(property == "id")) { break; } goto IL_0172; case 3: if (property == "cap") { Cap = reader.GetSingle(); } break; case 9: if (property == "threshold") { Threshold = reader.GetSingle(); } break; case 14: if (!(property == "overrideamount")) { break; } goto IL_01c1; case 13: if (!(property == "triggeramount")) { break; } goto IL_01ce; case 6: if (!(property == "amount")) { break; } goto IL_01ce; case 4: case 5: case 10: case 12: case 15: case 16: case 17: case 18: break; IL_01ce: Amount = reader.GetSingle(); break; IL_01c1: OverrideAmount = reader.GetBoolean(); break; IL_0153: Activate = EWCJson.Deserialize(ref reader); if (Activate == null) { throw new JsonException("ModSynced needs a valid Activate trigger!"); } break; IL_0172: if (reader.TokenType == JsonTokenType.String) { ID = WeaponPropertyBase.StringIDToInt(reader.GetString()); } else { ID = reader.GetUInt32(); } break; } } } public sealed class PerTargetTrigger : ITrigger { private static readonly TriggerName[] ValidActivates = ITrigger.HitTriggers.Remove(default(TriggerName)); private static readonly TriggerName[] ValidApplies = ValidActivates.Extend(TriggerName.Kill); private readonly Dictionary _targetAmounts = new Dictionary(); public TriggerName Name { get; } = TriggerName.PerTarget; public ITrigger Activate { get; private set; } public ITrigger Apply { get; private set; } public ITrigger? Cancel { get; private set; } public float Amount { get; private set; } = 1f; public float Cap { get; private set; } public float Threshold { get; private set; } public bool ActivateScaleWithFalloff { get; private set; } public bool ApplyAboveThreshold { get; private set; } public bool OverrideAmount { get; private set; } private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; public PerTargetTrigger() { Activate = null; Apply = null; } public PerTargetTrigger(ITrigger activate, ITrigger apply) { Activate = activate; Apply = apply; } public bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (!(context is WeaponHitDamageableContextBase weaponHitDamageableContextBase)) { return false; } if (Activate.Invoke(context, out var amount2) && amount2 > 0f) { IDamageable damageable = ((WeaponHitDamageableContextBase)context).Damageable; if (!_targetAmounts.TryGetValue(TempWrapper.Set(damageable), out var value)) { _targetAmounts.Keys.Where((BaseDamageableWrapper wrapper) => wrapper.Object == null).ToList().ForEach(delegate(BaseDamageableWrapper wrapper) { _targetAmounts.Remove(wrapper); }); _targetAmounts.Add(new BaseDamageableWrapper(TempWrapper), value = 0f); } float num = amount2 * Amount; if (ActivateScaleWithFalloff) { num *= weaponHitDamageableContextBase.Falloff; } value += amount2 * Amount; if (Cap > 0f) { value = Math.Min(value, Cap); } _targetAmounts[TempWrapper] = value; } if (Apply.Invoke(context, out amount2) && amount2 > 0f) { IDamageable damageable2 = ((WeaponHitDamageableContextBase)context).Damageable; if (_targetAmounts.TryGetValue(TempWrapper.Set(damageable2), out var value2) && value2 >= Threshold) { if (OverrideAmount) { amount = Amount; } else if (ApplyAboveThreshold) { amount = value2 - Threshold; } else { amount = value2; } if (amount == 0f) { return true; } _targetAmounts.Remove(TempWrapper); return true; } } ITrigger? cancel = Cancel; if (cancel != null && cancel.Invoke(context, out amount2) && amount2 > 0f) { IDamageable damageable3 = ((WeaponHitDamageableContextBase)context).Damageable; _targetAmounts.Remove(TempWrapper.Set(damageable3)); } return _targetAmounts.Count > 0; } public void Reset() { _targetAmounts.Clear(); Activate.Reset(); Apply.Reset(); } public ITrigger Clone() { PerTargetTrigger perTargetTrigger = CopyUtil.Clone(this); perTargetTrigger.Activate = Activate.Clone(); perTargetTrigger.Apply = Apply.Clone(); return perTargetTrigger; } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == null) { return; } switch (property.Length) { case 5: { char c = property[0]; if (c != 'a') { if (c != 'r') { if (c != 's' || !(property == "store")) { break; } goto IL_01a5; } if (!(property == "reset")) { break; } goto IL_0249; } if (property == "apply") { Apply = EWCJson.Deserialize(ref reader); if (Apply == null || !ValidApplies.Contains(Apply.Name)) { throw new JsonException("PerTarget Trigger requires a trigger of type [" + string.Join(", ", ValidApplies) + "]!"); } } break; } case 6: { char c = property[0]; if (c != 'a') { if (c != 'c' || !(property == "cancel")) { break; } goto IL_0249; } if (!(property == "amount")) { break; } goto IL_02dc; } case 19: switch (property[5]) { default: return; case 'a': if (property == "applyabovethreshold") { ApplyAboveThreshold = reader.GetBoolean(); } return; case 'o': break; } if (!(property == "applyoverrideamount")) { break; } goto IL_02cf; case 8: if (!(property == "activate")) { break; } goto IL_01a5; case 3: if (property == "cap") { Cap = reader.GetSingle(); } break; case 9: if (property == "threshold") { Threshold = reader.GetSingle(); } break; case 24: if (!(property == "activatescalewithfalloff")) { break; } goto IL_02c2; case 16: if (!(property == "scalewithfalloff")) { break; } goto IL_02c2; case 14: if (!(property == "overrideamount")) { break; } goto IL_02cf; case 11: if (!(property == "applyamount")) { break; } goto IL_02cf; case 13: { if (!(property == "triggeramount")) { break; } goto IL_02dc; } IL_02c2: ActivateScaleWithFalloff = reader.GetBoolean(); break; IL_0249: Cancel = EWCJson.Deserialize(ref reader); if (Cancel != null && !ValidActivates.Contains(Cancel.Name)) { throw new JsonException("PerTarget Trigger requires a trigger of type [" + string.Join(", ", ValidApplies) + "]!"); } break; IL_01a5: Activate = EWCJson.Deserialize(ref reader); if (Activate == null || !ValidActivates.Contains(Activate.Name)) { throw new JsonException("PerTarget Trigger requires a trigger of type [" + string.Join(", ", ValidActivates) + "]!"); } break; IL_02dc: Amount = reader.GetSingle(); break; IL_02cf: OverrideAmount = reader.GetBoolean(); break; } } } public class PlayerDamageTypeTrigger : ITrigger { public PlayerDamageType[] DamageTypes { get; } public TriggerName Name { get; } public float Amount { get; private set; } = 1f; public PlayerDamageTypeTrigger(TriggerName name, params PlayerDamageType[] types) { Name = name; DamageTypes = ((types.Length == 0) ? PlayerDamageTypeConst.Any : types); } public virtual bool Invoke(WeaponTriggerContext context, out float amount) { amount = 0f; if (context is WeaponDamageTakenContext weaponDamageTakenContext && weaponDamageTakenContext.DamageType.HasFlagIn(DamageTypes)) { amount = Amount; return true; } return false; } public void Reset() { } public ITrigger Clone() { return this; } public virtual void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == "triggeramount" || property == "amount") { Amount = reader.GetSingle(); } } } public sealed class ReferenceCallTrigger : ITrigger { private uint _callbackID; public TriggerName Name { get; } = TriggerName.Reference; public float Amount { get; private set; } = 1f; public uint ID { get; private set; } public string Callback { get; private set; } = string.Empty; public ReferenceCallTrigger(string id) { ID = WeaponPropertyBase.StringIDToInt(id); } public ReferenceCallTrigger(uint id) { ID = id; } public ReferenceCallTrigger() { } public bool Invoke(WeaponTriggerContext context, out float amount) { if (context is WeaponReferenceContext weaponReferenceContext && weaponReferenceContext.ID == ID && weaponReferenceContext.CallbackID == _callbackID) { amount = Amount * weaponReferenceContext.Mod; return true; } amount = 0f; return false; } public void Reset() { } public ITrigger Clone() { return this; } public void OnPropertiesSetup(CustomWeaponComponent cwc) { if (cwc.TryGetProperty(ID, out WeaponPropertyBase property)) { if (property is ITriggerEvent triggerEvent) { _callbackID = triggerEvent.GetCallbackID(Callback); } else { EWCLogger.Error("Cannot use " + property.GetType().Name + " as a trigger!"); } } } public void DeserializeProperty(string property, ref Utf8JsonReader reader) { switch (property) { case "triggeramount": case "amount": Amount = reader.GetSingle(); break; case "referenceid": case "id": if (reader.TokenType == JsonTokenType.String) { ID = WeaponPropertyBase.StringIDToInt(reader.GetString()); } else { ID = reader.GetUInt32(); } break; case "callback": Callback = reader.GetString(); break; } } } public sealed class StaggerTrigger : HitTrackerTrigger { public bool IncludeLimbBreak { get; private set; } = true; public StaggerTrigger(params DamageType[] types) : base(TriggerName.Stagger, types) { } public override bool Invoke(WeaponTriggerContext context, out float amount) { if (!base.Invoke(context, out amount)) { return false; } if (!((WeaponPostStaggerContext)context).LimbBreak || IncludeLimbBreak) { return true; } amount = 0f; return false; } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "includelimbbreak" || property == "limbbreak") { IncludeLimbBreak = reader.GetBoolean(); } } } internal sealed class TriggerSync : SyncedEvent { public override string GUID => "TRGIN"; protected override void Receive(TriggerInstanceData packet) { TriggerManager.Internal_ReceiveInstance(packet); } } internal sealed class TriggerDirSync : SyncedEvent { public override string GUID => "TRGDIR"; protected override void Receive(TriggerDirInstanceData packet) { TriggerManager.Internal_ReceiveInstance(packet); } } internal sealed class TriggerImpactSync : SyncedEvent { public override string GUID => "TRGIMP"; protected override void Receive(TriggerImpactInstanceData packet) { TriggerManager.Internal_ReceiveInstance(packet); } } internal sealed class TriggerAgentSync : SyncedEvent { public override string GUID => "TRGAGT"; protected override void Receive(TriggerAgentInstanceData packet) { TriggerManager.Internal_ReceiveInstance(packet); } } internal sealed class TriggerResetSync : SyncedEvent { public override string GUID => "TRGRS"; protected override void Receive(TriggerResetData packet) { TriggerManager.Internal_ReceiveReset(packet); } } } namespace EWC.CustomWeapon.Properties.Effects { public sealed class Accelerate : Effect, ITriggerCallbackBasicSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private float _endFireRateMod = 1f; private float _accelTime = 1f; private float _decelTime = 0.001f; private float _progress; private float _lastUpdateTime; private float _resetProgress; private float _resetUpdateTime; public ushort SyncID { get; set; } public float EndFireRate { get; private set; } public float EndFireRateMod { get { return _endFireRateMod; } private set { _endFireRateMod = Math.Max(0.001f, value); } } public StackType FireRateStackLayer { get; private set; } = StackType.Multiply; private float FireRateMod { get { if (!(EndFireRate > 0f)) { return EndFireRateMod; } return EndFireRate / base.CGC.BaseFireRate; } } public float EndShotMod { get; private set; } = 1f; public DamageType[] ModDamageType { get; private set; } = DamageTypeConst.Any; public StatType ModStatType { get; private set; } public StackType ModStackLayer { get; private set; } = StackType.Multiply; public bool StoreModOnGroup { get; private set; } = true; public float AccelTime { get { return _accelTime; } private set { _accelTime = Math.Max(0.001f, value); } } public float DecelTime { get { return _decelTime; } private set { _decelTime = Math.Max(0.001f, value); } } public float DecelDelay { get; private set; } public float AccelExponent { get; private set; } = 1f; public bool UseContinuousGrowth { get; private set; } protected override WeaponType RequiredWeaponType => WeaponType.Gun; public override bool ShouldRegister(Type contextType) { bool flag = EndShotMod != 1f || ModStackLayer == StackType.Override; if (contextType == typeof(WeaponShotInitContext)) { if (flag) { return !StoreModOnGroup; } return false; } if (contextType == typeof(WeaponShotGroupInitContext)) { if (flag) { return StoreModOnGroup; } return false; } return base.ShouldRegister(contextType); } private void UpdateProgress() { _resetProgress = _progress; _resetUpdateTime = _lastUpdateTime; if (_lastUpdateTime == 0f) { _lastUpdateTime = Clock.Time; } float num = Clock.Time - _lastUpdateTime; float num2 = Math.Min(1f / base.CGC.CurrentFireRate, num); _progress = Math.Min(_progress + num2 / AccelTime, 1f); num -= num2 + Clock.Delta; if (num > 0f && num > DecelDelay) { _progress = Math.Max(_progress - (num - DecelDelay) / DecelTime, 0f); } _lastUpdateTime = Clock.Time; } public void Invoke(WeaponPreStartFireContext context) { UpdateProgress(); } public void Invoke(WeaponPreFireContextSync context) { UpdateProgress(); } public void Invoke(WeaponPostFireContext context) { _resetProgress = _progress; _resetUpdateTime = _lastUpdateTime; } public void Invoke(WeaponFireRateContext context) { _progress = Math.Min(_progress + (Clock.Time - _lastUpdateTime) / AccelTime, 1f); _lastUpdateTime = Clock.Time; if (FireRateMod != 1f && _progress > 0f) { context.AddMod(GetMod(FireRateMod), FireRateStackLayer); } } public void Invoke(WeaponShotInitContext context) { if (_progress > 0f) { context.Mod.Add(this, ModStatType, GetMod(EndShotMod), 0f, StackType.Override, ModStackLayer, null, ModDamageType); } } public void Invoke(WeaponShotGroupInitContext context) { if (_progress > 0f) { context.GroupMod.Add(this, ModStatType, GetMod(EndShotMod), 0f, StackType.Override, ModStackLayer, null, ModDamageType); } } public void Invoke(WeaponFireCanceledContext context) { _progress = _resetProgress; _lastUpdateTime = _resetUpdateTime; } public override void TriggerReset() { TriggerResetSync(); TriggerManager.SendReset(this); } public void TriggerResetSync() { _progress = 0f; _lastUpdateTime = Clock.Time; } public override void TriggerApply(List contexts) { TriggerReset(); } public void TriggerApplySync(float mod) { TriggerResetSync(); } private float GetMod(float mod) { if (UseContinuousGrowth) { return (float)Math.Pow(mod, _progress); } return Math.Pow(_progress, AccelExponent).Lerp(1f, mod); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("EndShotDelay", 0f); writer.WriteNumber("EndFireRate", EndFireRate); writer.WriteNumber("EndFireRateMod", EndFireRateMod); writer.WriteString("FireRateStackLayer", FireRateStackLayer.ToString()); writer.WriteNumber("EndShotMod", EndShotMod); writer.WriteString("ModStatType", ModStatType.ToString()); writer.WriteString("ModDamageType", ModDamageType[0].ToString()); writer.WriteString("ModStackLayer", ModStackLayer.ToString()); writer.WriteBoolean("StoreModOnGroup", StoreModOnGroup); writer.WriteNumber("AccelTime", AccelTime); if (UseContinuousGrowth) { writer.WriteString("AccelExponent", "e"); } else { writer.WriteNumber("AccelExponent", AccelExponent); } writer.WriteNumber("DecelTime", DecelTime); writer.WriteNumber("DecelDelay", DecelDelay); writer.WriteNull("ResetTrigger"); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { if (property == null) { return; } switch (property.Length) { case 12: { char c = property[4]; if ((uint)c <= 101u) { if (c != 'a') { if (c != 'e' || !(property == "storeongroup")) { break; } goto IL_047a; } if (!(property == "enddamagemod")) { break; } } else { if (c == 'h') { if (!(property == "endshotdelay")) { break; } goto IL_03eb; } if (c != 'l') { if (c != 't' || !(property == "resettrigger")) { break; } goto IL_04ea; } if (!(property == "accelshotmod")) { break; } } goto IL_0435; } case 14: { char c = property[5]; if (c != 'd') { if (c != 'r') { if (c != 's' || !(property == "accelshotdelay")) { break; } goto IL_03eb; } if (!(property == "endfireratemod")) { break; } goto IL_0415; } if (!(property == "acceldamagemod")) { break; } goto IL_0435; } case 11: switch (property[0]) { default: return; case 'e': break; case 'f': goto IL_0242; case 'd': goto IL_0253; case 'm': goto IL_0264; } if (!(property == "endfirerate")) { break; } goto IL_0408; case 13: { char c = property[6]; if ((uint)c <= 99u) { if (c != 'a') { if (c != 'c' || !(property == "modstacklayer")) { break; } goto IL_0454; } if (!(property == "moddamagetype")) { break; } goto IL_0442; } if (c != 'i') { if (c != 't') { if (c != 'x' || !(property == "accelexponent")) { break; } goto IL_0494; } if (!(property == "fireratelayer")) { break; } goto IL_0422; } if (!(property == "accelfirerate")) { break; } goto IL_0408; } case 16: { char c = property[0]; if (c != 'a') { if (c != 'd') { if (c != 'r' || !(property == "resettriggertype")) { break; } goto IL_04ea; } if (!(property == "damagestacklayer")) { break; } goto IL_0454; } if (!(property == "accelfireratemod")) { break; } goto IL_0415; } case 9: switch (property[1]) { default: return; case 'a': break; case 'c': if (property == "acceltime") { AccelTime = reader.GetSingle(); } return; case 'e': if (property == "deceltime") { DecelTime = reader.GetSingle(); } return; case 'b': case 'd': return; } if (!(property == "damagemod")) { break; } goto IL_0435; case 10: { char c = property[1]; if (c != 'a') { switch (c) { default: return; case 'n': break; case 'e': if (property == "deceldelay") { DecelDelay = reader.GetSingle(); } return; } if (!(property == "endshotmod")) { break; } goto IL_0435; } if (!(property == "damagetype")) { break; } goto IL_0442; } case 7: { char c = property[0]; if (c != 'm') { if (c != 's' || !(property == "shotmod")) { break; } goto IL_0435; } if (!(property == "modstat")) { break; } goto IL_0467; } case 8: { char c = property[0]; if (c != 'e') { if (c != 'm') { if (c != 's' || !(property == "stattype")) { break; } goto IL_0467; } if (!(property == "modlayer")) { break; } goto IL_0454; } if (!(property == "exponent")) { break; } goto IL_0494; } case 18: if (!(property == "fireratestacklayer")) { break; } goto IL_0422; case 4: if (!(property == "stat")) { break; } goto IL_0467; case 15: if (!(property == "storemodongroup")) { break; } goto IL_047a; case 5: case 6: case 17: break; IL_0264: if (!(property == "modstattype")) { break; } goto IL_0467; IL_0242: if (!(property == "fireratemod")) { break; } goto IL_0415; IL_0442: ModDamageType = reader.GetString().ToDamageTypes(); break; IL_0454: ModStackLayer = reader.GetString().ToEnum(StackType.Invalid); break; IL_0253: if (!(property == "damagelayer")) { break; } goto IL_0454; IL_0467: ModStatType = reader.GetString().ToEnum(StatType.Damage); break; IL_0435: EndShotMod = reader.GetSingle(); break; IL_04ea: base.Trigger = TriggerCoordinator.Deserialize(ref reader); break; IL_047a: StoreModOnGroup = reader.GetBoolean(); break; IL_0494: if (reader.TokenType == JsonTokenType.String) { if (reader.GetString().ToLowerInvariant() == "e") { UseContinuousGrowth = true; } } else { AccelExponent = reader.GetSingle(); UseContinuousGrowth = false; } break; IL_0415: EndFireRateMod = reader.GetSingle(); break; IL_03eb: EndFireRate = 1f / Math.Max(0.001953125f, reader.GetSingle()); break; IL_0422: FireRateStackLayer = reader.GetString().ToEnum(StackType.Invalid); break; IL_0408: EndFireRate = reader.GetSingle(); break; } } } public sealed class ActionLock : Effect, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private float _endTime; public PlayerAction Actions { get; private set; } public float Duration { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Local; public override bool ShouldRegister(Type contextType) { if (!Actions.HasFlag(PlayerAction.Swap) && contextType == typeof(WeaponPreSwapContext)) { return false; } if (!Actions.HasFlag(PlayerAction.Sprint) && contextType == typeof(WeaponPreSprintContext)) { return false; } if (!Actions.HasFlag(PlayerAction.Fire) && contextType == typeof(WeaponFireCancelContext)) { return false; } if (!Actions.HasFlag(PlayerAction.Reload) && contextType == typeof(WeaponPreReloadContext)) { return false; } return base.ShouldRegister(contextType); } public override void TriggerApply(List contexts) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 if (Actions.HasFlag(PlayerAction.Sprint)) { PlayerLocomotion locomotion = base.CWC.Owner.Player.Locomotion; if ((int)locomotion.m_currentStateEnum == 2) { locomotion.ChangeState((PLOC_State)0, false); } } _endTime = Clock.Time + Duration; } public override void TriggerReset() { _endTime = 0f; } public void Invoke(WeaponPreSwapContext context) { context.Allow = context.Allow && _endTime < Clock.Time; } public void Invoke(WeaponPreSprintContext context) { context.Allow = context.Allow && _endTime < Clock.Time; } public void Invoke(WeaponFireCancelContext context) { context.Allow = context.Allow && _endTime < Clock.Time; } public void Invoke(WeaponPreReloadContext context) { context.Allow = context.Allow && _endTime < Clock.Time; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteString("Actions", Actions.ToString()); writer.WriteNumber("Duration", Duration); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property) { case "actions": case "action": Actions = ToPlayerAction(reader.GetString()); break; case "duration": Duration = reader.GetSingle(); break; } } private static PlayerAction ToPlayerAction(string value) { value = value.Replace(" ", null).ToLower(); if (value == "all") { return PlayerAction.All; } PlayerAction playerAction = PlayerAction.None; if (value.Contains("swap")) { playerAction |= PlayerAction.Swap; } if (value.Contains("sprint") || value.Contains("run")) { playerAction |= PlayerAction.Sprint; } if (value.Contains("fire") || value.Contains("shoot")) { playerAction |= PlayerAction.Fire; } if (value.Contains("reload")) { playerAction |= PlayerAction.Reload; } return playerAction; } } [Flags] public enum PlayerAction { None = 0, Swap = 1, Sprint = 2, Fire = 4, Reload = 8, All = -1 } public sealed class AmmoMod : Effect, IWeaponProperty, IWeaponProperty, IWeaponProperty { private class EmptyHolder : IAmmoComp, IWeaponComp { private readonly bool _isSentry; private readonly ItemEquippable? _item; public AmmoType AmmoType { get { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!_isSentry) { return _item.AmmoType; } return (AmmoType)2; } } public InventorySlot InventorySlot => AmmoType.ToInventorySlot(); public CellSoundPlayer Sound { get { throw new NotImplementedException(); } } public ItemEquippable Component { get { throw new NotImplementedException(); } } public WeaponType Type { get { throw new NotImplementedException(); } } public bool AllowBackstab { get { throw new NotImplementedException(); } } public ArchetypeDataBlock ArchetypeData { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public bool IsShotgun { get { throw new NotImplementedException(); } } public bool IsAiming { get { throw new NotImplementedException(); } } public WeaponHitData VanillaHitData { get { throw new NotImplementedException(); } } public FX_Pool TracerPool { get { throw new NotImplementedException(); } } public float MaxRayDist { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public EmptyHolder(ItemEquippable? item) { _isSentry = (Object)(object)item == (Object)null; _item = item; } public int GetCurrentClip() { if (_isSentry) { return 0; } return _item.GetCurrentClip(); } public int GetMaxClip() { if (_isSentry) { return 0; } return _item.GetMaxClip(); } public void SetCurrentClip(int clip) { if (!_isSentry) { _item.SetCurrentClip(clip); } } } private float _clipBuffer; private float _reserveBuffer; private bool _bonusRound; public float ClipChange { get; private set; } public float ReserveChange { get; private set; } public bool OverflowAtBounds { get; private set; } = true; public bool PullFromReserve { get; private set; } public bool UseRawAmmo { get; private set; } public bool BypassClipCap { get; private set; } public bool BypassReserveCap { get; private set; } public InventorySlot ReceiverSlot { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; public override bool ValidProperty() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 if (base.ValidProperty()) { if (base.CWC.Weapon.IsType(WeaponType.Melee)) { return (int)ReceiverSlot > 0; } return true; } return false; } public void Invoke(WeaponPreFireContext context) { _bonusRound = SlotMatchesWeapon(); } public void Invoke(WeaponPostFireContext context) { _bonusRound = false; } public override void TriggerReset() { _clipBuffer = 0f; _reserveBuffer = 0f; } public override void TriggerApply(List triggerList) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (HandleLevelSentry(triggerList)) { return; } PlayerBackpack backpack = PlayerBackpackManager.GetBackpack(base.CWC.Owner.Player.Owner); BackpackItem bpItem = default(BackpackItem); IAmmoComp holder; if (!SlotMatchesWeapon() && backpack.TryGetBackpackItem(ReceiverSlot, ref bpItem)) { if (!TryCreateHolder(bpItem, out holder)) { return; } } else if (base.CWC.Weapon.IsType(WeaponType.Gun)) { holder = base.CGC.Gun; } else { if (!base.CWC.Weapon.IsType(WeaponType.SentryHolder) || CustomWeaponManager.TryGetSentry(base.CWC.Owner.Player, out (SentryGunInstance, CustomGunComponent) _)) { return; } holder = (IAmmoComp)base.CWC.Weapon; } PlayerAmmoStorage ammoStorage = backpack.AmmoStorage; InventorySlotAmmo inventorySlotAmmo = ammoStorage.GetInventorySlotAmmo(holder.AmmoType); float num = triggerList.Sum((TriggerContext context) => context.triggerAmt); _clipBuffer += ClipChange * num; _reserveBuffer += ReserveChange * num; float costOfBullet = inventorySlotAmmo.CostOfBullet; float num2 = (UseRawAmmo ? costOfBullet : 1f); if (!(Math.Abs(_clipBuffer) < num2) || !(Math.Abs(_reserveBuffer) < num2)) { int num3 = (_bonusRound ? 1 : 0); if (UseRawAmmo) { _clipBuffer /= costOfBullet; _reserveBuffer /= costOfBullet; } int bulletsInPack = inventorySlotAmmo.BulletsInPack; int num4 = 0; if (OverflowAtBounds && ReserveChange < 0f && (float)bulletsInPack < 0f - _reserveBuffer) { int num5 = (int)_reserveBuffer + bulletsInPack; _reserveBuffer = -bulletsInPack; num4 = num5; } bool overflow; int num6 = holder.GetMaxClip(out overflow); if (BypassClipCap) { num6 = int.MaxValue - num3; } else if (overflow) { num3 = 0; } int num7 = (int)(PullFromReserve ? Math.Min(_clipBuffer, bulletsInPack) : (_clipBuffer + (float)num4)); int num8 = Math.Clamp(holder.GetCurrentClip() + num7, num3, num6 + num3); int num9 = (OverflowAtBounds ? (num7 - (num8 - holder.GetCurrentClip())) : 0); num7 = num8 - holder.GetCurrentClip(); int num10 = (int)(PullFromReserve ? (_reserveBuffer - (float)num7) : (_reserveBuffer + (float)num9)); _clipBuffer -= (int)_clipBuffer; _reserveBuffer -= (int)_reserveBuffer; holder.SetCurrentClip(num8); if (UseRawAmmo) { _clipBuffer *= costOfBullet; _reserveBuffer *= costOfBullet; } float num11 = (float)num10 * costOfBullet; if (BypassReserveCap || num11 < 0f) { inventorySlotAmmo.AmmoInPack = Math.Max(inventorySlotAmmo.AmmoInPack + num11, 0f); } else if (!inventorySlotAmmo.IsFull) { inventorySlotAmmo.AmmoInPack = Math.Clamp(inventorySlotAmmo.AmmoInPack + num11, 0f, inventorySlotAmmo.AmmoMaxCap); } inventorySlotAmmo.OnBulletsUpdateCallback?.Invoke(inventorySlotAmmo.BulletsInPack); ammoStorage.NeedsSync = true; ammoStorage.UpdateSlotAmmoUI(inventorySlotAmmo, num8); } } private bool HandleLevelSentry(List triggerList) { if (!base.CWC.Weapon.IsType(WeaponType.Sentry) || (Object)(object)base.CWC.Owner.Player != (Object)null) { return false; } SentryGunComp sentryGunComp = (SentryGunComp)base.CWC.Weapon; float num = triggerList.Sum((TriggerContext context) => context.triggerAmt); _clipBuffer += ClipChange * num; float costOfBullet = sentryGunComp.ArchetypeData.CostOfBullet; float num2 = (UseRawAmmo ? costOfBullet : 1f); if (Math.Abs(_clipBuffer) < num2) { return true; } int num3 = (_bonusRound ? 1 : 0); if (UseRawAmmo) { _clipBuffer /= costOfBullet; } bool overflow; int num4 = sentryGunComp.GetMaxClip(out overflow); if (BypassClipCap) { num4 = int.MaxValue - num3; } else if (overflow) { num3 = 0; } int currentClip = Math.Clamp(sentryGunComp.GetCurrentClip() + (int)_clipBuffer, num3, num4 + num3); _clipBuffer -= (int)_clipBuffer; sentryGunComp.SetCurrentClip(currentClip); if (UseRawAmmo) { _clipBuffer *= costOfBullet; } return true; } public override void Serialize(Utf8JsonWriter writer) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("ClipChange", ClipChange); writer.WriteNumber("ReserveChange", ReserveChange); writer.WriteBoolean("OverflowAtBounds", OverflowAtBounds); writer.WriteBoolean("PullFromReserve", PullFromReserve); writer.WriteBoolean("UseRawAmmo", UseRawAmmo); writer.WriteBoolean("BypassClipCap", BypassClipCap); writer.WriteBoolean("BypassReserveCap", BypassReserveCap); writer.WriteString("ReceiverSlot", SlotToName(ReceiverSlot)); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { //IL_0213: Unknown result type (might be due to invalid IL or missing references) base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 10: { char c = property[0]; if (c != 'c') { if (c != 'u' || !(property == "userawammo")) { return; } goto IL_01e5; } if (!(property == "clipchange")) { return; } goto IL_01b1; } case 4: { char c = property[0]; if (c != 'c') { if (c != 's' || !(property == "slot")) { return; } break; } if (!(property == "clip")) { return; } goto IL_01b1; } case 13: switch (property[0]) { default: return; case 'r': break; case 'b': if (property == "bypassclipcap") { BypassClipCap = reader.GetBoolean(); } return; } if (!(property == "reservechange")) { return; } goto IL_01be; case 7: { char c = property[0]; if (c != 'r') { if (c != 'u' || !(property == "useammo")) { return; } goto IL_01e5; } if (!(property == "reserve")) { return; } goto IL_01be; } case 16: { char c = property[0]; if (c != 'b') { if (c != 'o' || !(property == "overflowatbounds")) { return; } goto IL_01cb; } if (!(property == "bypassreservecap")) { return; } goto IL_01ff; } case 17: if (!(property == "overflowtoreserve")) { return; } goto IL_01cb; case 8: if (!(property == "overflow")) { return; } goto IL_01cb; case 15: if (property == "pullfromreserve") { PullFromReserve = reader.GetBoolean(); } return; case 9: if (!(property == "bypasscap")) { return; } goto IL_01ff; case 12: if (!(property == "receiverslot")) { return; } break; case 5: case 6: case 11: case 14: return; IL_01be: ReserveChange = reader.GetSingle(); return; IL_01cb: OverflowAtBounds = reader.GetBoolean(); return; IL_01e5: UseRawAmmo = reader.GetBoolean(); return; IL_01ff: BypassReserveCap = reader.GetBoolean(); return; IL_01b1: ClipChange = reader.GetSingle(); return; } ReceiverSlot = SlotNameToSlot(reader.GetString()); } private static InventorySlot SlotNameToSlot(string name) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) switch (name.ToLowerInvariant().Replace(" ", null)) { case "main": case "primary": return (InventorySlot)1; case "special": case "secondary": return (InventorySlot)2; case "tool": case "class": return (InventorySlot)3; default: return (InventorySlot)0; } } private bool SlotMatchesWeapon() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_001b: 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) InventorySlot receiverSlot = ReceiverSlot; if ((int)receiverSlot != 0) { if (receiverSlot - 1 <= 2) { return base.CWC.Weapon.InventorySlot == ReceiverSlot; } return false; } return true; } private static string SlotToName(InventorySlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown return (slot - 1) switch { 0 => "Main", 1 => "Special", 2 => "Tool", _ => "None", }; } private static bool TryCreateHolder(BackpackItem bpItem, [MaybeNullWhen(false)] out IAmmoComp holder) { Item instance = bpItem.Instance; if (((Object)(object)instance).TryCastOut(out BulletWeapon result)) { holder = new EmptyHolder((ItemEquippable?)(object)result); return true; } if (((Object)(object)instance).TryCastOut(out BulletWeaponSynced result2)) { holder = new EmptyHolder((ItemEquippable?)(object)result2); return true; } if (((Object)(object)instance).TryCastOut(out SentryGunFirstPerson result3)) { if (CustomWeaponManager.TryGetSentry(((Item)result3).Owner, out (SentryGunInstance, CustomGunComponent) sentryInfo)) { holder = sentryInfo.Item2?.Gun ?? new SentryGunComp(sentryInfo.Item1); } else { holder = new EmptyHolder(null); } return true; } holder = null; return false; } } public sealed class AmmoRegen : Effect, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { [CompilerGenerated] private sealed class d__66 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public AmmoRegen <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__66(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown int num = <>1__state; AmmoRegen ammoRegen = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; ammoRegen._lastTickTime = Clock.Time; break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; case 3: <>1__state = -1; break; case 4: <>1__state = -1; break; case 5: <>1__state = -1; break; } if ((Object)(object)ammoRegen.CWC != (Object)null) { if (!ammoRegen.ResetCache()) { <>2__current = null; <>1__state = 1; return true; } float time = Clock.Time; if (ammoRegen._nextTickTime > time) { <>2__current = (object)new WaitForSeconds(ammoRegen._nextTickTime - time); <>1__state = 2; return true; } float num2 = Math.Min(time - ammoRegen._nextTickTime, time - ammoRegen._lastTickTime); ammoRegen._lastTickTime = time; if (ammoRegen.HandleLevelSentry(num2)) { <>2__current = null; <>1__state = 3; return true; } IAmmoComp ammoComp = (IAmmoComp)ammoRegen.CWC.Weapon; int currentClip = ammoComp.GetCurrentClip(); int num3 = (ammoRegen.BypassClipCap ? int.MaxValue : ammoComp.GetMaxClip()); float ammoInPack = ammoRegen._slotAmmo.AmmoInPack; float ammoMaxCap = ammoRegen._slotAmmo.AmmoMaxCap; float costOfBullet = ammoRegen._slotAmmo.CostOfBullet; bool flag = ammoRegen.ClipRegen != 0f; bool flag2 = ammoRegen.ReserveRegen != 0f; if (ammoRegen.ResetWhileFull) { if (ammoRegen.ClipRegen > 0f) { flag = currentClip < num3 || (ammoRegen.OverflowToReserve && ammoInPack < ammoMaxCap); flag &= !ammoRegen.PullFromReserve || ammoInPack >= costOfBullet; } else if (ammoRegen.ClipRegen < 0f) { flag = currentClip != 0 || (ammoRegen.OverflowToReserve && ammoInPack > 0f); } if (ammoRegen.ReserveRegen > 0f) { flag2 = ammoRegen.BypassReserveCap || ammoInPack < ammoMaxCap; } else if (ammoRegen.ReserveRegen < 0f) { flag2 = ammoInPack > costOfBullet; flag2 &= !ammoRegen.PullFromReserve || currentClip < num3; } } ammoRegen._clipBuffer = (flag ? (ammoRegen._clipBuffer + ammoRegen.ClipRegen * num2) : 0f); ammoRegen._reserveBuffer = (flag2 ? (ammoRegen._reserveBuffer + ammoRegen.ReserveRegen * num2) : 0f); int num4 = (int)(ammoRegen.UseRawAmmo ? (ammoRegen._clipBuffer / costOfBullet) : ammoRegen._clipBuffer); int num5 = (int)(ammoRegen.UseRawAmmo ? (ammoRegen._reserveBuffer / costOfBullet) : ammoRegen._reserveBuffer); num4 = num4 / ammoRegen.ChangeAmount * ammoRegen.ChangeAmount; num5 = num5 / ammoRegen.ChangeAmount * ammoRegen.ChangeAmount; if (num4 == 0 && num5 == 0) { <>2__current = null; <>1__state = 4; return true; } int num6 = (ammoRegen.PullFromReserve ? Math.Min(num4, ammoRegen._slotAmmo.BulletsInPack) : num4); int num7 = Math.Clamp(currentClip + num6, 0, num3); int num8 = (ammoRegen.OverflowToReserve ? (num6 - (num7 - currentClip)) : 0); num6 = num7 - currentClip; int num9 = (ammoRegen.PullFromReserve ? (num5 - num6) : (num5 + num8)); ammoComp.SetCurrentClip(num7); if (ammoRegen.UseRawAmmo) { ammoRegen._clipBuffer -= (float)num4 * costOfBullet; ammoRegen._reserveBuffer -= (float)num5 * costOfBullet; } else { ammoRegen._clipBuffer -= num4; ammoRegen._reserveBuffer -= num5; } float num10 = (float)num9 * costOfBullet; if (ammoRegen.BypassReserveCap || num10 < 0f) { ammoRegen._slotAmmo.AmmoInPack = Math.Max(ammoInPack + num10, 0f); } else if (!ammoRegen._slotAmmo.IsFull) { ammoRegen._slotAmmo.AmmoInPack = Math.Clamp(ammoInPack + num10, 0f, ammoMaxCap); } ammoRegen._slotAmmo.OnBulletsUpdateCallback?.Invoke(ammoRegen._slotAmmo.BulletsInPack); ammoRegen._ammoStorage.NeedsSync = true; ammoRegen._ammoStorage.UpdateSlotAmmoUI(ammoRegen._slotAmmo, num7); <>2__current = null; <>1__state = 5; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private float _clipBuffer; private float _reserveBuffer; private PlayerAmmoStorage? _ammoStorage; private InventorySlotAmmo? _slotAmmo; private float _lastTickTime; private float _nextTickTime; private Coroutine? _updateRoutine; public float ClipRegen { get; private set; } public float ReserveRegen { get; private set; } public int ChangeAmount { get; private set; } = 1; public bool OverflowToReserve { get; private set; } = true; public bool PullFromReserve { get; private set; } public bool UseRawAmmo { get; private set; } public bool BypassClipCap { get; private set; } public bool BypassReserveCap { get; private set; } public bool AllowReload { get; private set; } = true; public bool ActiveInHolster { get; private set; } = true; public bool ResetWhileFull { get; private set; } = true; public float DelayAfterTrigger { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; protected override WeaponType ValidWeaponType => WeaponType.SentryHolder | WeaponType.Gun; public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponSetupContext)) { return ActiveInHolster; } if (contextType == typeof(WeaponWieldContext) || contextType == typeof(WeaponUnWieldContext)) { return !ActiveInHolster; } if (contextType == typeof(WeaponPreReloadContext)) { if (!AllowReload && base.CWC.Owner.IsType(OwnerType.Player)) { return base.CWC.Weapon.IsType(WeaponType.Gun); } return false; } return base.ShouldRegister(contextType); } public void Invoke(WeaponSetupContext _) { if (_updateRoutine == null) { _updateRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(Update()), (Action)null); } } public void Invoke(WeaponClearContext _) { CoroutineUtil.Stop(ref _updateRoutine); } public void Invoke(WeaponWieldContext _) { if (_updateRoutine == null) { _updateRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(Update()), (Action)null); } } public void Invoke(WeaponUnWieldContext _) { CoroutineUtil.Stop(ref _updateRoutine); } public void Invoke(WeaponPreReloadContext context) { context.Allow = false; } private bool ResetCache() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (base.CWC.Weapon.IsType(WeaponType.SentryHolder) && CustomWeaponManager.TryGetSentry(base.CWC.Owner.Player, out (SentryGunInstance, CustomGunComponent) _)) { return false; } if (base.CWC.Weapon.IsType(WeaponType.Sentry) && (Object)(object)base.CWC.Owner.Player == (Object)null) { return true; } if (_ammoStorage == null || _slotAmmo == null) { PlayerBackpack val = default(PlayerBackpack); if (!PlayerBackpackManager.TryGetBackpack(base.CWC.Owner.Player.Owner, ref val)) { return false; } _ammoStorage = val.AmmoStorage; if (_ammoStorage == null) { return false; } _slotAmmo = _ammoStorage.GetInventorySlotAmmo(base.CWC.Weapon.AmmoType); if (_slotAmmo == null) { return false; } } return true; } [IteratorStateMachine(typeof(d__66))] private IEnumerator Update() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__66(0) { <>4__this = this }; } private bool HandleLevelSentry(float delta) { if (!base.CWC.Weapon.IsType(WeaponType.Sentry) || (Object)(object)base.CWC.Owner.Player != (Object)null) { return false; } SentryGunComp sentryGunComp = (SentryGunComp)base.CWC.Weapon; int currentClip = sentryGunComp.GetCurrentClip(); int num = (BypassClipCap ? int.MaxValue : sentryGunComp.GetMaxClip()); bool flag = true; if (ResetWhileFull) { if (ClipRegen > 0f) { flag = currentClip < num; } else if (ClipRegen < 0f) { flag = currentClip != 0; } } _clipBuffer = (flag ? (_clipBuffer + ClipRegen * delta) : 0f); float costOfBullet = sentryGunComp.ArchetypeData.CostOfBullet; int num2 = (int)(UseRawAmmo ? (_clipBuffer / costOfBullet) : _clipBuffer); num2 = num2 / ChangeAmount * ChangeAmount; if (num2 == 0) { return true; } int currentClip2 = Math.Clamp(currentClip + num2, 0, num); sentryGunComp.SetCurrentClip(currentClip2); if (UseRawAmmo) { _clipBuffer -= (float)num2 * costOfBullet; } else { _clipBuffer -= num2; } return true; } public override void TriggerApply(List _) { _nextTickTime = Clock.Time + DelayAfterTrigger; } public override void TriggerReset() { _nextTickTime = 0f; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("ClipRegen", ClipRegen); writer.WriteNumber("ReserveRegen", ReserveRegen); writer.WriteNumber("ChangeAmount", ChangeAmount); writer.WriteBoolean("OverflowToReserve", OverflowToReserve); writer.WriteBoolean("PullFromReserve", PullFromReserve); writer.WriteBoolean("UseRawAmmo", UseRawAmmo); writer.WriteBoolean("BypassClipCap", BypassClipCap); writer.WriteBoolean("BypassReserveCap", BypassReserveCap); writer.WriteBoolean("AllowReload", AllowReload); writer.WriteBoolean("ActiveInHolster", ActiveInHolster); writer.WriteBoolean("ResetWhileFull", ResetWhileFull); writer.WriteNumber("DelayAfterTrigger", DelayAfterTrigger); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 9: { char c = property[0]; if (c != 'b') { if (c != 'c' || !(property == "clipregen")) { break; } goto IL_0245; } if (!(property == "bypasscap")) { break; } goto IL_02a6; } case 10: { char c = property[0]; if (c != 'c') { if (c != 'u' || !(property == "userawammo")) { break; } goto IL_028c; } if (!(property == "clipchange")) { break; } goto IL_0245; } case 12: switch (property[0]) { default: return; case 'r': break; case 'c': if (property == "changeamount") { ChangeAmount = Math.Max(1, reader.GetInt32()); } return; } if (!(property == "reserveregen")) { break; } goto IL_0252; case 13: switch (property[0]) { default: return; case 'r': break; case 'b': if (property == "bypassclipcap") { BypassClipCap = reader.GetBoolean(); } return; } if (!(property == "reservechange")) { break; } goto IL_0252; case 7: { char c = property[0]; if (c != 'r') { if (c != 'u' || !(property == "useammo")) { break; } goto IL_028c; } if (!(property == "reserve")) { break; } goto IL_0252; } case 17: switch (property[0]) { default: return; case 'o': break; case 'd': if (property == "delayaftertrigger") { DelayAfterTrigger = reader.GetSingle(); } return; } if (!(property == "overflowtoreserve")) { break; } goto IL_0272; case 15: switch (property[0]) { case 'p': if (property == "pullfromreserve") { PullFromReserve = reader.GetBoolean(); } break; case 'a': if (property == "activeinholster") { ActiveInHolster = reader.GetBoolean(); } break; } break; case 4: if (!(property == "clip")) { break; } goto IL_0245; case 8: if (!(property == "overflow")) { break; } goto IL_0272; case 16: if (!(property == "bypassreservecap")) { break; } goto IL_02a6; case 11: if (property == "allowreload") { AllowReload = reader.GetBoolean(); } break; case 14: if (property == "resetwhilefull") { ResetWhileFull = reader.GetBoolean(); } break; case 5: case 6: break; IL_0245: ClipRegen = reader.GetSingle(); break; IL_0252: ReserveRegen = reader.GetSingle(); break; IL_0272: OverflowToReserve = reader.GetBoolean(); break; IL_02a6: BypassReserveCap = reader.GetBoolean(); break; IL_028c: UseRawAmmo = reader.GetBoolean(); break; } } } public sealed class ArmorMod : TriggerModDebuff { public PlayerDamageType[] DamageType { get; private set; } = PlayerDamageTypeConst.Any; public bool Immune { get; private set; } public bool ApplyToTarget { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; public ArmorMod() { base.Trigger = null; SetValidTriggers(); } public override bool ValidProperty() { if (!ApplyToTarget && !base.CWC.Owner.IsType(OwnerType.Local)) { return false; } return base.ValidProperty(); } public override void TriggerApply(List contexts) { if (!ApplyToTarget) { PlayerAgent player = base.CWC.Owner.Player; if ((Object)(object)player != (Object)null) { float num = Count(contexts); AddTriggerInstance(new BaseDamageableWrapper(((Il2CppObjectBase)player.Damage).Cast()), num); TriggerManager.SendInstance(this, (Agent)(object)player, num); } return; } if (contexts.Count > 1) { Dictionary dictionary = new Dictionary(); foreach (TriggerContext context in contexts) { if (TryGetPlayerDamageable(context, out IDamageable damageable)) { TempWrapper.Set(damageable); if (!dictionary.TryGetValue(TempWrapper, out var value)) { dictionary.Add(new BaseDamageableWrapper(TempWrapper), context.triggerAmt); } else { dictionary[TempWrapper] = Combine(value, context.triggerAmt); } } } { foreach (var (baseDamageableWrapper2, num3) in dictionary) { AddTriggerInstance(baseDamageableWrapper2, num3); TriggerManager.SendInstance(this, baseDamageableWrapper2.Object.GetBaseAgent(), num3); } return; } } if (TryGetPlayerDamageable(contexts[0], out IDamageable damageable2)) { float triggerAmt = contexts[0].triggerAmt; AddTriggerInstance(new BaseDamageableWrapper(damageable2), triggerAmt); TriggerManager.SendInstance(this, damageable2.GetBaseAgent(), triggerAmt); } } private bool TryGetPlayerDamageable(TriggerContext tContext, [MaybeNullWhen(false)] out IDamageable damageable) { if (tContext.context is WeaponHitDamageableContextBase weaponHitDamageableContextBase && weaponHitDamageableContextBase.DamageType.HasFlag(EWC.CustomWeapon.Enums.DamageType.Player)) { damageable = weaponHitDamageableContextBase.Damageable; return true; } if ((Object)(object)base.CWC.Owner.Player != (Object)null) { damageable = ((Il2CppObjectBase)base.CWC.Owner.Player.Damage).Cast(); return true; } damageable = null; return false; } protected override DebuffModifierBase AddModifier(IDamageable damageable) { if (Immune) { return DebuffManager.AddArmorImmuneBuff(damageable, DamageType); } return DebuffManager.AddArmorModBuff(damageable, 1f, base.StackLayer, DamageType); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteBoolean("Immune", Immune); writer.WriteString("DamageType", DamageType[0].ToString()); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteBoolean("ApplyToTarget", ApplyToTarget); writer.WriteNumber("GlobalID", base.GlobalID); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property) { case "moddamagetype": case "damagetype": DamageType = reader.GetString().ToPlayerDamageTypes(); break; case "immune": case "immunity": Immune = reader.GetBoolean(); break; case "applytotarget": ApplyToTarget = reader.GetBoolean(); break; } } } public sealed class ArmorShred : TriggerModDebuff { public ArmorShred() { SetValidTriggers(DamageType.Player | DamageType.Object, ITrigger.HitTriggers); } protected override DebuffModifierBase AddModifier(IDamageable damageable) { return DebuffManager.AddArmorShredDebuff(damageable, 1f, base.StackLayer, base.DebuffID); } } public sealed class BioPing : Effect { private readonly Dictionary, float> _cooldownTimes = new Dictionary, float>(); public float CooldownPerTarget { get; private set; } private static ObjectWrapper TempWrapper => ObjectWrapper.SharedInstance; public BioPing() { if (base.Trigger == null) { TriggerCoordinator triggerCoordinator2 = (base.Trigger = new TriggerCoordinator(ITrigger.GetTrigger(TriggerName.Hit))); } SetValidTriggers(DamageType.Player | DamageType.Object, ITrigger.HitTriggers); } public override void TriggerApply(List contexts) { float value = Clock.Time + CooldownPerTarget; foreach (TriggerContext context in contexts) { IDamageable damageable = ((WeaponHitDamageableContext)context.context).Damageable; if (damageable == null) { continue; } if (!_cooldownTimes.TryGetValue(TempWrapper.Set(((Il2CppObjectBase)damageable.GetBaseAgent()).Cast()), out var value2)) { _cooldownTimes.Keys.Where((ObjectWrapper wrapper) => (Object)(object)wrapper.Object == (Object)null || !((Agent)wrapper.Object).Alive).ToList().ForEach(delegate(ObjectWrapper wrapper) { _cooldownTimes.Remove(wrapper); }); _cooldownTimes.Add(new ObjectWrapper(TempWrapper), value); ToolSyncManager.WantToTagEnemy(TempWrapper.Object); } else if (Clock.Time > value2) { _cooldownTimes[TempWrapper] = value; ToolSyncManager.WantToTagEnemy(TempWrapper.Object); } } } public override void TriggerReset() { _cooldownTimes.Clear(); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("CooldownPerTarget", CooldownPerTarget); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "cooldownpertarget") { CooldownPerTarget = reader.GetSingle(); } } } public class ChargeSpeedMod : TriggerMod, IWeaponProperty, IWeaponProperty { private readonly TriggerStack _triggerStack; public bool ForceUpdate { get; private set; } protected override WeaponType RequiredWeaponType => WeaponType.BulletWeapon; protected override OwnerType RequiredOwnerType => OwnerType.Local; public ChargeSpeedMod() { _triggerStack = new TriggerStack(this); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? _ = null) { return _triggerStack.TryGetStacks(out stacks); } public override void TriggerReset() { _triggerStack.Clear(); base.CGC.UpdateChargeTime(ForceUpdate); } public override void TriggerApply(List contexts) { float num = Count(contexts); _triggerStack.Add(num); base.CGC.UpdateChargeTime(ForceUpdate); } public void Invoke(WeaponChargeSpeedContext context) { if (_triggerStack.TryGetMod(out var mod)) { context.AddMod(mod, base.StackLayer); } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteBoolean("ForceUpdate", ForceUpdate); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "forceupdate") { ForceUpdate = reader.GetBoolean(); } } } public sealed class DamageOverTime : Effect, ITriggerCallbackAgentSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty { private float _tickRate = 2f; private readonly DOTController _controller = new DOTController(); private readonly Dictionary> _lastDOTs = new Dictionary>(); private readonly Dictionary _hitmarkerCooldowns = new Dictionary(); public ushort SyncID { get; set; } public PlayerAgent? Owner => base.CWC.Owner.Player; public float TotalDamage { get; private set; } public float EndDamageFrac { get; private set; } = 1f; public float Exponent { get; private set; } = 1f; public float PrecisionDamageMulti { get; private set; } public float FriendlyDamageMulti { get; private set; } = 1f; public float StaggerDamageMulti { get; private set; } public float Duration { get; private set; } public uint StackLimit { get; private set; } public bool IgnoreFalloff { get; private set; } public bool DamageLimb { get; private set; } = true; public bool IgnoreArmor { get; private set; } public bool IgnoreBackstab { get; private set; } public bool IgnoreShotMods { get; private set; } public bool UseParentShotMod { get; private set; } = true; public bool CalcShotModsPerTick { get; private set; } public float TickRate { get { return _tickRate; } private set { _tickRate = Math.Max(0.01f, value); } } public bool ApplyAttackCooldown { get; private set; } public float HitmarkerCooldown { get; private set; } public Color GlowColor { get; private set; } = Color.black; public float GlowIntensity { get; private set; } = 1f; public float GlowRange { get; private set; } public bool BatchStacks { get; private set; } = true; private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; public DamageOverTime() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (base.Trigger == null) { TriggerCoordinator triggerCoordinator2 = (base.Trigger = new TriggerCoordinator(ITrigger.GetTrigger(TriggerName.Hit))); } SetValidTriggers(DamageType.DOT, ITrigger.HitTriggers); } public bool ShouldDoHitmarker(IDamageable damageable) { if (HitmarkerCooldown <= 0f) { return true; } float time = Clock.Time; if (_hitmarkerCooldowns.TryGetValue(TempWrapper.Set(damageable), out var value)) { if (time < value) { return false; } _hitmarkerCooldowns[TempWrapper] = time + HitmarkerCooldown; } else { BaseDamageableWrapper[] array = _hitmarkerCooldowns.Keys.ToArray(); foreach (BaseDamageableWrapper baseDamageableWrapper in array) { if (!baseDamageableWrapper.Alive) { _hitmarkerCooldowns.Remove(baseDamageableWrapper); } } _hitmarkerCooldowns[new BaseDamageableWrapper(TempWrapper)] = time + HitmarkerCooldown; } return true; } public override void TriggerApply(List triggerList) { foreach (TriggerContext trigger in triggerList) { WeaponHitDamageableContextBase weaponHitDamageableContextBase = (WeaponHitDamageableContextBase)trigger.context; AddDOT(weaponHitDamageableContextBase, trigger.triggerAmt); if (GlowRange != 0f && GlowIntensity != 0f) { Agent baseAgent = weaponHitDamageableContextBase.Damageable.GetBaseAgent(); if ((Object)(object)baseAgent != (Object)null) { TriggerApplySync(baseAgent, trigger.triggerAmt); TriggerManager.SendInstance(this, baseAgent, trigger.triggerAmt); } } } } public override void TriggerReset() { _controller.Clear(); TriggerResetSync(); } public void TriggerApplySync(Agent target, float mod) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_000c: Invalid comparison between Unknown and I4 AgentType type = target.Type; IDamageable damBase; Transform target2; if ((int)type != 0) { if ((int)type != 1) { return; } EnemyAgent obj = ((Il2CppObjectBase)target).Cast(); damBase = ((Il2CppObjectBase)obj.Damage).Cast(); target2 = ((Agent)obj).EasyAimTarget; } else { PlayerAgent obj2 = ((Il2CppObjectBase)target).Cast(); damBase = ((Il2CppObjectBase)obj2.Damage).Cast(); target2 = ((Agent)obj2).TentacleTarget; } DOTGlowPooling.TryDoEffect(this, damBase, target2, mod); } public void TriggerResetSync() { DOTGlowPooling.TryEndEffect(this); } private void AddDOT(WeaponHitDamageableContextBase context, float triggerAmt) { TempWrapper.Set(context.Damageable); float falloff = (IgnoreFalloff ? 1f : context.Falloff); float num = TotalDamage * triggerAmt; float backstab = 1f; float origBackstab = 1f; if (!IgnoreBackstab) { backstab = context.Backstab; origBackstab = context.OrigBackstab; } float precision = PrecisionDamageMulti; float staggerDamageMulti = StaggerDamageMulti; ShotInfo shotInfo = new ShotInfo(context.ShotInfo.Orig, modOnly: true, UseParentShotMod); num *= shotInfo.ExternalDamageMod * shotInfo.InnateDamageMod; staggerDamageMulti *= shotInfo.InnateStaggerMod; WeaponStatContext weaponStatContext = new WeaponStatContext(num, precision, staggerDamageMulti, DamageType.DOT.WithSubTypes(context.Damageable), context.Damageable, context.ShotInfo.Orig, base.CWC.DebuffIDs); base.CWC.Invoke(weaponStatContext); if (!CalcShotModsPerTick && !IgnoreShotMods) { num = weaponStatContext.Damage; precision = weaponStatContext.Precision; staggerDamageMulti = weaponStatContext.Stagger; } DOTInstance dOTInstance = new DOTInstance(num, falloff, precision, staggerDamageMulti, weaponStatContext.BypassTumorCap, backstab, origBackstab, shotInfo, this); if (StackLimit == 0) { _controller.AddDOT(dOTInstance, context.Damageable); return; } ClearDeadQueues(); if (_lastDOTs.TryGetValue(TempWrapper, out Queue value)) { if (value.Count >= StackLimit) { DOTInstance dOTInstance2 = value.Peek(); if (num <= dOTInstance2.GetRemainingDamage()) { return; } dOTInstance.StartWithTargetTime(dOTInstance2.NextTickTime); value.Dequeue().Destroy(); } } else { _lastDOTs.Add(new BaseDamageableWrapper(context.Damageable), value = new Queue()); } _controller.AddDOT(dOTInstance, context.Damageable); value.Enqueue(dOTInstance); } private void ClearDeadQueues() { BaseDamageableWrapper[] array = _lastDOTs.Keys.ToArray(); foreach (BaseDamageableWrapper baseDamageableWrapper in array) { if (!baseDamageableWrapper.Alive) { _lastDOTs.Remove(baseDamageableWrapper); continue; } Queue queue = _lastDOTs[baseDamageableWrapper]; DOTInstance result; while (queue.TryPeek(out result) && result.Expired) { queue.Dequeue(); } if (queue.Count == 0) { _lastDOTs.Remove(baseDamageableWrapper); } } } public override void Serialize(Utf8JsonWriter writer) { //IL_0155: Unknown result type (might be due to invalid IL or missing references) writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("TotalDamage", TotalDamage); writer.WriteNumber("EndDamageFrac", EndDamageFrac); writer.WriteNumber("Exponent", Exponent); writer.WriteNumber("PrecisionDamageMulti", PrecisionDamageMulti); writer.WriteNumber("StaggerDamageMulti", StaggerDamageMulti); writer.WriteNumber("FriendlyDamageMulti", FriendlyDamageMulti); writer.WriteNumber("Duration", Duration); writer.WriteNumber("TickRate", TickRate); writer.WriteNumber("StackLimit", StackLimit); writer.WriteBoolean("IgnoreFalloff", IgnoreFalloff); writer.WriteBoolean("DamageLimb", DamageLimb); writer.WriteBoolean("IgnoreArmor", IgnoreArmor); writer.WriteBoolean("IgnoreBackstab", IgnoreBackstab); writer.WriteBoolean("IgnoreShotMods", IgnoreShotMods); writer.WriteBoolean("UseParentShotMod", UseParentShotMod); writer.WriteBoolean("CalcShotModsPerTick", CalcShotModsPerTick); writer.WriteBoolean("ApplyAttackCooldown", ApplyAttackCooldown); writer.WriteNumber("HitmarkerCooldown", HitmarkerCooldown); EWCJson.Serialize(writer, "GlowColor", GlowColor); writer.WriteNumber("GlowIntensity", GlowIntensity); writer.WriteNumber("GlowRange", GlowRange); SerializeTrigger(writer); writer.WriteBoolean("BatchStacks", BatchStacks); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { //IL_05ca: Unknown result type (might be due to invalid IL or missing references) base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 11: { char c = property[0]; if ((uint)c <= 105u) { switch (c) { case 'i': if (property == "ignorearmor") { IgnoreArmor = reader.GetBoolean(); } break; case 'b': if (property == "batchstacks") { BatchStacks = reader.GetBoolean(); } break; } break; } if (c != 's') { if (c != 't' || !(property == "totaldamage")) { break; } goto IL_04de; } if (!(property == "staggermult")) { break; } goto IL_0512; } case 13: switch (property[2]) { default: return; case 'd': if (!(property == "enddamagefrac")) { return; } goto IL_04eb; case 'm': if (!(property == "damageendfrac")) { return; } goto IL_04eb; case 'e': break; case 'i': goto IL_029d; case 'n': goto IL_02ae; case 'r': goto IL_02cf; case 'o': { if (property == "glowintensity") { GlowIntensity = reader.GetSingle(); } return; } IL_04eb: EndDamageFrac = reader.GetSingle(); return; } if (!(property == "precisionmult")) { break; } goto IL_0505; case 8: switch (property[0]) { default: return; case 'e': if (property == "exponent") { Exponent = reader.GetSingle(); } return; case 'd': if (property == "duration") { Duration = reader.GetSingle(); } return; case 't': break; } if (!(property == "tickrate")) { break; } goto IL_0539; case 20: { char c = property[0]; if (c != 'a') { if (c != 'p' || !(property == "precisiondamagemulti")) { break; } goto IL_0505; } if (!(property == "applyattackcooldowns")) { break; } goto IL_05ae; } case 14: { char c = property[6]; if (c != 'b') { if (c != 'i') { if (c != 's' || !(property == "ignoreshotmods")) { break; } goto IL_0587; } if (!(property == "precisionmulti")) { break; } goto IL_0505; } if (!(property == "ignorebackstab")) { break; } goto IL_057a; } case 9: switch (property[4]) { default: return; case 'i': break; case 'c': if (property == "glowcolor") { GlowColor = EWCJson.Deserialize(ref reader); } return; case 'r': if (property == "glowrange") { GlowRange = reader.GetSingle(); } return; } if (!(property == "precision")) { break; } goto IL_0505; case 18: { char c = property[0]; if (c != 'c') { if (c != 's' || !(property == "staggerdamagemulti")) { break; } goto IL_0512; } if (!(property == "calcshotmodpertick")) { break; } goto IL_05a1; } case 12: { char c = property[0]; if (c != 'f') { if (c != 's' || !(property == "staggermulti")) { break; } goto IL_0512; } if (!(property == "friendlymult")) { break; } goto IL_051f; } case 7: { char c = property[0]; if (c != 'h') { if (c != 's' || !(property == "stagger")) { break; } goto IL_0512; } if (!(property == "hitrate")) { break; } goto IL_0539; } case 19: { char c = property[0]; if (c != 'a') { if (c != 'c') { if (c != 'f' || !(property == "friendlydamagemulti")) { break; } goto IL_051f; } if (!(property == "calcshotmodspertick")) { break; } goto IL_05a1; } if (!(property == "applyattackcooldown")) { break; } goto IL_05ae; } case 10: switch (property[0]) { default: return; case 's': break; case 'd': if (property == "damagelimb") { DamageLimb = reader.GetBoolean(); } return; } if (!(property == "stacklimit")) { break; } goto IL_0546; case 16: switch (property[6]) { default: return; case 'b': break; case 'd': goto IL_0489; case 'e': goto IL_049a; case 'c': return; } if (!(property == "ignorebackdamage")) { break; } goto IL_057a; case 15: { char c = property[6]; if (c != 'b') { if (c != 'd' || !(property == "ignoredamagemod")) { break; } goto IL_0587; } if (!(property == "ignorebackbonus")) { break; } goto IL_057a; } case 6: if (!(property == "damage")) { break; } goto IL_04de; case 5: if (!(property == "limit")) { break; } goto IL_0546; case 17: { if (property == "hitmarkercooldown") { HitmarkerCooldown = reader.GetSingle(); } break; } IL_0539: TickRate = reader.GetSingle(); break; IL_05a1: CalcShotModsPerTick = reader.GetBoolean(); break; IL_02cf: if (!(property == "parentshotmod")) { break; } goto IL_0594; IL_049a: if (!(property == "useparentshotmod")) { break; } goto IL_0594; IL_0489: if (!(property == "ignoredamagemods")) { break; } goto IL_0587; IL_0594: UseParentShotMod = reader.GetBoolean(); break; IL_0546: StackLimit = reader.GetUInt32(); break; IL_04de: TotalDamage = reader.GetSingle(); break; IL_0587: IgnoreShotMods = reader.GetBoolean(); break; IL_057a: IgnoreBackstab = reader.GetBoolean(); break; IL_02ae: if (!(property == "ignorefalloff")) { if (!(property == "ignoreshotmod")) { break; } goto IL_0587; } IgnoreFalloff = reader.GetBoolean(); break; IL_0512: StaggerDamageMulti = reader.GetSingle(); break; IL_029d: if (!(property == "friendlymulti")) { break; } goto IL_051f; IL_051f: FriendlyDamageMulti = reader.GetSingle(); break; IL_05ae: ApplyAttackCooldown = reader.GetBoolean(); break; IL_0505: PrecisionDamageMulti = reader.GetSingle(); break; } } } public abstract class Effect : WeaponPropertyBase, ITriggerCallback, IWeaponProperty, IWeaponProperty { private TriggerCoordinator? _coordinator; private TriggerName[]? _validTriggers; private DamageType _blacklistType; public TriggerCoordinator? Trigger { get { return _coordinator; } set { _coordinator = value; if (value != null) { value.Parent = this; } } } protected virtual bool IsTriggerValid => Trigger?.Activate.Triggers.Any() ?? false; public override bool ShouldRegister(Type contextType) { if (Trigger == null && contextType == typeof(WeaponTriggerContext)) { return false; } return base.ShouldRegister(contextType); } public void Invoke(WeaponTriggerContext context) { Trigger.Invoke(context); } protected void SetValidTriggers(DamageType blacklist = DamageType.Any, params TriggerName[] names) { _validTriggers = ((names.Length != 0) ? names : null); _blacklistType = blacklist; VerifyTriggers(); } protected void SetValidTriggers(params TriggerName[] names) { SetValidTriggers(DamageType.Any, names); } public abstract void TriggerApply(List triggerList); public abstract void TriggerReset(); public override WeaponPropertyBase Clone() { Effect obj = (Effect)base.Clone(); obj.Trigger = Trigger?.Clone(); return obj; } protected void SerializeTrigger(Utf8JsonWriter writer) { if (Trigger != null) { EWCJson.Serialize(writer, "Trigger", Trigger); } else { writer.WriteString("Trigger", "Invalid"); } } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "triggertype" || property == "trigger") { Trigger = TriggerCoordinator.Deserialize(ref reader, allowEmptyActivate: true); VerifyTriggers(); } } private void VerifyTriggers() { if (Trigger == null) { return; } for (int num = Trigger.Activate.Triggers.Count - 1; num >= 0; num--) { TriggerName name = Trigger.Activate.Triggers[num].Name; if (_validTriggers != null && !_validTriggers.Contains(name)) { EWCLogger.Warning($"{GetType().Name} has an invalid trigger {name}. Only the following are allowed: {string.Join(", ", _validTriggers)}"); Trigger.Activate.Triggers.RemoveAt(num); } else { ITrigger trigger = Trigger.Activate.Triggers[num]; IDamageTypeTrigger typeTrigger = trigger as IDamageTypeTrigger; if (typeTrigger != null) { if (!typeTrigger.DamageTypes.Any((DamageType type) => type.HasAnyFlag(_blacklistType))) { typeTrigger.BlacklistType |= _blacklistType; } if (typeTrigger.DamageTypes.All((DamageType type) => type.HasAnyFlag(typeTrigger.BlacklistType))) { EWCLogger.Warning($"{GetType().Name} has a trigger {name} with invalid damage types {string.Join(", ", typeTrigger.DamageTypes)}. It cannot contain any types within {_blacklistType}"); Trigger.Activate.Triggers.RemoveAt(num); } } } } if (!IsTriggerValid) { Trigger = null; } } } public sealed class Explosive : Effect, ISyncProperty, IWeaponProperty { private const float WallHitBuffer = 0.03f; public ushort SyncPropertyID { get; set; } public float MaxDamage { get; private set; } public float MinDamage { get; private set; } public float InnerRadius { get; private set; } public float Radius { get; private set; } public float Exponent { get; private set; } = 1f; public float PrecisionDamageMulti { get; private set; } public float StaggerDamageMulti { get; private set; } = 1f; public float FriendlyDamageMulti { get; private set; } = 1f; public bool IgnoreFalloff { get; private set; } public bool DamageLimb { get; private set; } = true; public bool IgnoreArmor { get; private set; } public bool IgnoreBackstab { get; private set; } public bool IgnoreShotMods { get; private set; } public bool UseParentShotMod { get; private set; } = true; public bool DamageFriendly { get; private set; } = true; public bool DamageOwner { get; private set; } = true; public bool DamageLocks { get; private set; } = true; public bool HitFromExplosionPos { get; private set; } public bool HitClosestFirst { get; private set; } public bool ApplyAttackCooldown { get; private set; } = true; public TriggerPosMode ApplyPositionMode { get; private set; } public uint SoundID { get; private set; } = EVENTS.STICKYMINEEXPLODE; public bool EnableMineFX { get; private set; } public Color GlowColor { get; private set; } = new Color(1f, 0.2f, 0f, 1f); public float GlowIntensity { get; private set; } = 5f; public float GlowDuration { get; private set; } = 0.1f; public float GlowFadeDuration { get; private set; } = 0.1f; public float ScreenShakeIntensity { get; private set; } public float ScreenShakeFrequency { get; private set; } = 30f; public float ScreenShakeDuration { get; private set; } public float ScreenShakeInnerRadius { get; private set; } public float ScreenShakeRadius { get; private set; } public float CacheBackstab { get; private set; } public Explosive() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (base.Trigger == null) { TriggerCoordinator triggerCoordinator2 = (base.Trigger = new TriggerCoordinator(ITrigger.GetTrigger(TriggerName.BulletLanded))); } SetValidTriggers(DamageType.Explosive); } public override void TriggerReset() { } public override void TriggerApply(List triggerList) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //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) foreach (TriggerContext trigger in triggerList) { CacheBackstab = 0f; if (ApplyPositionMode != TriggerPosMode.User && trigger.context is IPositionContext positionContext) { Vector3 val = positionContext.Position; if (positionContext is WeaponHitDamageableContextBase weaponHitDamageableContextBase) { CacheBackstab = weaponHitDamageableContextBase.Backstab; Agent baseAgent = weaponHitDamageableContextBase.Damageable.GetBaseAgent(); if (ApplyPositionMode == TriggerPosMode.Relative && (Object)(object)baseAgent != (Object)null) { val = weaponHitDamageableContextBase.LocalPosition + baseAgent.Position; } } else { val += positionContext.Normal * 0.03f; } ExplosionManager.DoExplosion(val, positionContext.Direction, positionContext.Normal, IgnoreFalloff ? 1f : positionContext.Falloff, this, trigger.triggerAmt, positionContext.ShotInfo.Orig); } else { IOwnerComp owner = base.CWC.Owner; ExplosionManager.DoExplosion(owner.FirePos, owner.FireDir, owner.FireDir, 1f, this, trigger.triggerAmt); } } } public override void Serialize(Utf8JsonWriter writer) { //IL_01bf: Unknown result type (might be due to invalid IL or missing references) writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("MaxDamage", MaxDamage); writer.WriteNumber("MinDamage", MinDamage); writer.WriteNumber("InnerRadius", InnerRadius); writer.WriteNumber("Radius", Radius); writer.WriteNumber("Exponent", Exponent); writer.WriteNumber("PrecisionDamageMulti", PrecisionDamageMulti); writer.WriteNumber("StaggerDamageMulti", StaggerDamageMulti); writer.WriteNumber("FriendlyDamageMulti", FriendlyDamageMulti); writer.WriteBoolean("IgnoreFalloff", IgnoreFalloff); writer.WriteBoolean("DamageLimb", DamageLimb); writer.WriteBoolean("IgnoreArmor", IgnoreArmor); writer.WriteBoolean("IgnoreBackstab", IgnoreBackstab); writer.WriteBoolean("IgnoreShotMods", IgnoreShotMods); writer.WriteBoolean("UseParentShotMod", UseParentShotMod); writer.WriteBoolean("DamageFriendly", DamageFriendly); writer.WriteBoolean("DamageOwner", DamageOwner); writer.WriteBoolean("DamageLocks", DamageLocks); writer.WriteBoolean("HitFromExplosionPos", HitFromExplosionPos); writer.WriteBoolean("HitClosestFirst", HitClosestFirst); writer.WriteBoolean("ApplyAttackCooldown", ApplyAttackCooldown); writer.WriteString("ApplyPositionMode", ApplyPositionMode.ToString()); SerializeTrigger(writer); writer.WriteNumber("SoundID", SoundID); writer.WriteBoolean("EnableMineFX", EnableMineFX); EWCJson.Serialize(writer, "GlowColor", GlowColor); writer.WriteNumber("GlowIntensity", GlowIntensity); writer.WriteNumber("GlowDuration", GlowDuration); writer.WriteNumber("GlowFadeDuration", GlowFadeDuration); writer.WriteNumber("ScreenShakeIntensity", ScreenShakeIntensity); writer.WriteNumber("ScreenShakeFrequency", ScreenShakeFrequency); writer.WriteNumber("ScreenShakeDuration", ScreenShakeDuration); writer.WriteNumber("ScreenShakeInnerRadius", ScreenShakeInnerRadius); writer.WriteNumber("ScreenShakeRadius", ScreenShakeRadius); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { //IL_088c: Unknown result type (might be due to invalid IL or missing references) base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 9: { char c = property[1]; if ((uint)c <= 105u) { if (c != 'a') { if (c != 'i') { return; } if (!(property == "mindamage")) { if (!(property == "minradius")) { return; } goto IL_0750; } MinDamage = reader.GetSingle(); return; } if (!(property == "maxdamage")) { if (!(property == "maxradius")) { return; } goto IL_075d; } MaxDamage = reader.GetSingle(); return; } if (c != 'l') { if (c != 'n') { if (c != 'r' || !(property == "precision")) { return; } goto IL_0777; } if (!(property == "intensity")) { return; } goto IL_0897; } if (!(property == "glowcolor")) { return; } goto IL_088a; } case 11: { char c = property[1]; if ((uint)c <= 104u) { if (c != 'a') { switch (c) { default: return; case 'g': if (property == "ignorearmor") { IgnoreArmor = reader.GetBoolean(); } return; case 'h': break; } if (!(property == "shakeradius")) { return; } break; } if (!(property == "damageowner")) { if (property == "damagelocks") { DamageLocks = reader.GetBoolean(); } return; } goto IL_07f9; } if (c != 'n') { switch (c) { default: return; case 't': break; case 'p': if (property == "applyonuser") { ApplyPositionMode = TriggerPosMode.User; } return; } if (!(property == "staggermult")) { return; } goto IL_0784; } if (!(property == "innerradius")) { return; } goto IL_0750; } case 6: { char c = property[0]; if (c != 'm') { if (c != 'r' || !(property == "radius")) { return; } goto IL_075d; } if (!(property == "minefx")) { return; } goto IL_087d; } case 8: switch (property[0]) { default: return; case 'e': if (property == "exponent") { Exponent = reader.GetSingle(); } return; case 'd': break; } if (!(property == "duration")) { return; } goto IL_08a4; case 20: { char c = property[11]; if ((uint)c <= 102u) { if (c != 'c') { if (c != 'f' || !(property == "screenshakefrequency")) { return; } goto IL_08cb; } if (!(property == "applyattackcooldowns")) { return; } goto IL_082d; } if (c != 'i') { if (c != 'm' || !(property == "precisiondamagemulti")) { return; } goto IL_0777; } if (!(property == "screenshakeintensity")) { return; } goto IL_08be; } case 14: { char c = property[6]; if ((uint)c <= 105u) { if (c != 'b') { if (c != 'f') { if (c != 'i' || !(property == "precisionmulti")) { return; } goto IL_0777; } if (!(property == "damagefriendly")) { return; } goto IL_07ec; } if (!(property == "ignorebackstab")) { return; } goto IL_07c5; } if (c != 'n') { if (c != 'r') { if (c != 's' || !(property == "ignoreshotmods")) { return; } goto IL_07d2; } if (!(property == "shakefrequency")) { return; } goto IL_08cb; } if (!(property == "shakeintensity")) { return; } goto IL_08be; } case 13: switch (property[2]) { default: return; case 'e': break; case 'i': goto IL_04d4; case 'n': goto IL_04e5; case 'r': goto IL_0506; case 'o': goto IL_0517; case 'a': goto IL_0528; } if (!(property == "precisionmult")) { return; } goto IL_0777; case 12: { char c = property[8]; if ((uint)c <= 109u) { if (c != 'f') { if (c != 'i') { if (c != 'm' || !(property == "friendlymult")) { return; } goto IL_0791; } if (!(property == "closestfirst")) { return; } goto IL_0820; } if (!(property == "friendlyfire")) { return; } goto IL_07ec; } if (c != 'n') { if (c != 't') { if (c != 'u' || !(property == "staggermulti")) { return; } goto IL_0784; } if (property == "glowduration") { goto IL_08a4; } if (!(property == "fadeduration")) { return; } goto IL_08b1; } if (!(property == "enableminefx")) { return; } goto IL_087d; } case 7: { char c = property[1]; if (c != 'o') { if (c != 't' || !(property == "stagger")) { return; } goto IL_0784; } if (!(property == "soundid")) { return; } goto IL_0855; } case 19: { char c = property[0]; if ((uint)c <= 102u) { if (c != 'a') { if (c != 'f' || !(property == "friendlydamagemulti")) { return; } goto IL_0791; } if (!(property == "applyattackcooldown")) { return; } goto IL_082d; } if (c != 'h') { if (c != 's' || !(property == "screenshakeduration")) { return; } goto IL_08d8; } if (!(property == "hitfromexplosionpos")) { return; } goto IL_0813; } case 10: switch (property[6]) { default: return; case 'l': if (property == "damagelimb") { DamageLimb = reader.GetBoolean(); } return; case 'u': break; } if (!(property == "damageuser")) { return; } goto IL_07f9; case 16: switch (property[8]) { default: return; case 'c': break; case 'm': goto IL_0659; case 't': goto IL_066a; case 'd': goto IL_067b; case 'e': goto IL_068c; } if (!(property == "ignorebackdamage")) { return; } goto IL_07c5; case 15: { char c = property[6]; if (c != 'b') { if (c != 'd') { if (c != 's' || !(property == "hitclosestfirst")) { return; } goto IL_0820; } if (!(property == "ignoredamagemod")) { return; } goto IL_07d2; } if (!(property == "ignorebackbonus")) { return; } goto IL_07c5; } case 17: switch (property[0]) { default: return; case 'a': if (property == "applypositionmode") { ApplyPositionMode = reader.GetString().ToEnum(TriggerPosMode.Relative); } return; case 's': break; } if (!(property == "screenshakeradius")) { return; } break; case 5: { char c = property[0]; if (c != 'c') { if (c != 's' || !(property == "sound")) { return; } goto IL_0855; } if (!(property == "color")) { return; } goto IL_088a; } case 18: if (!(property == "staggerdamagemulti")) { return; } goto IL_0784; case 24: if (!(property == "hitfromexplosionposition")) { return; } goto IL_0813; case 22: if (!(property == "screenshakeinnerradius")) { return; } goto IL_08e5; case 21: case 23: return; IL_0897: GlowIntensity = reader.GetSingle(); return; IL_0777: PrecisionDamageMulti = reader.GetSingle(); return; IL_0750: InnerRadius = reader.GetSingle(); return; IL_07d2: IgnoreShotMods = reader.GetBoolean(); return; IL_0528: if (!(property == "shakeduration")) { return; } goto IL_08d8; IL_08b1: GlowFadeDuration = reader.GetSingle(); return; IL_068c: if (!(property == "shakeinnerradius")) { return; } goto IL_08e5; IL_08e5: ScreenShakeInnerRadius = reader.GetSingle(); return; IL_067b: if (!(property == "glowfadeduration")) { return; } goto IL_08b1; IL_066a: if (!(property == "useparentshotmod")) { return; } goto IL_07df; IL_0659: if (!(property == "ignoredamagemods")) { return; } goto IL_07d2; IL_08d8: ScreenShakeDuration = reader.GetSingle(); return; IL_0517: if (!(property == "glowintensity")) { return; } goto IL_0897; IL_0506: if (!(property == "parentshotmod")) { return; } goto IL_07df; IL_04e5: if (!(property == "ignorefalloff")) { if (!(property == "ignoreshotmod")) { return; } goto IL_07d2; } IgnoreFalloff = reader.GetBoolean(); return; IL_08cb: ScreenShakeFrequency = reader.GetSingle(); return; IL_088a: GlowColor = EWCJson.Deserialize(ref reader); return; IL_07df: UseParentShotMod = reader.GetBoolean(); return; IL_04d4: if (!(property == "friendlymulti")) { return; } goto IL_0791; IL_087d: EnableMineFX = reader.GetBoolean(); return; IL_0791: FriendlyDamageMulti = reader.GetSingle(); return; IL_0813: HitFromExplosionPos = reader.GetBoolean(); return; IL_07f9: DamageOwner = reader.GetBoolean(); return; IL_0855: if (reader.TokenType == JsonTokenType.String) { SoundID = AkSoundEngine.GetIDFromString(reader.GetString()); } else { SoundID = reader.GetUInt32(); } return; IL_075d: Radius = reader.GetSingle(); return; IL_08be: ScreenShakeIntensity = reader.GetSingle(); return; IL_0784: StaggerDamageMulti = reader.GetSingle(); return; IL_082d: ApplyAttackCooldown = reader.GetBoolean(); return; IL_08a4: GlowDuration = reader.GetSingle(); return; IL_0820: HitClosestFirst = reader.GetBoolean(); return; IL_07c5: IgnoreBackstab = reader.GetBoolean(); return; IL_07ec: DamageFriendly = reader.GetBoolean(); return; } ScreenShakeRadius = reader.GetSingle(); } } public class FireRateMod : TriggerMod, ITriggerCallbackBasicSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty, IWeaponProperty { private readonly TriggerStack _triggerStack; public ushort SyncID { get; set; } public bool ForceUpdate { get; private set; } public FireRateMod() { _triggerStack = new TriggerStack(this); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? _ = null) { return _triggerStack.TryGetStacks(out stacks); } public override void TriggerReset() { TriggerResetSync(); if (base.CWC.Weapon.IsType(WeaponType.Gun)) { TriggerManager.SendReset(this); } } public override void TriggerApply(List contexts) { float num = Count(contexts); TriggerApplySync(num); if (base.CWC.Weapon.IsType(WeaponType.Gun)) { TriggerManager.SendInstance(this, num); } } public void TriggerResetSync() { _triggerStack.Clear(); if (ForceUpdate && base.CWC.Weapon.IsType(WeaponType.Gun)) { base.CGC.UpdateStoredFireRate(); base.CGC.ModifyFireRate(); } } public void TriggerApplySync(float num) { _triggerStack.Add(num); if (ForceUpdate && base.CWC.Weapon.IsType(WeaponType.Gun)) { base.CGC.UpdateStoredFireRate(); base.CGC.ModifyFireRate(); } } public void Invoke(WeaponFireRateContext context) { if (_triggerStack.TryGetMod(out var mod)) { context.AddMod(mod, base.StackLayer); } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteBoolean("ForceUpdate", ForceUpdate); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "forceupdate") { ForceUpdate = reader.GetBoolean(); } } bool ITriggerCallback.get_UseZeroAmountTrigger() { return UseZeroAmountTrigger; } } public sealed class FireShot : Effect, ITriggerCallbackBasicSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty, ITriggerCallbackDirSync { private const float WallHitBuffer = 0.03f; private ArchetypeDataBlock? _cachedArchetype; public ushort SyncID { get; set; } public float[] Offsets { get; private set; } = Array.Empty(); public uint ArchetypeID { get; private set; } public uint Repeat { get; private set; } public float Spread { get; private set; } public bool IgnoreSpreadMod { get; private set; } public bool UseParentShotMod { get; private set; } = true; public bool ForceSingleBullet { get; private set; } public FireSetting FireFrom { get; private set; } public bool UserUseAimDir { get; private set; } public bool DamageFriendly { get; private set; } = true; public bool DamageOwner { get; private set; } public bool HitTriggerTarget { get; private set; } public bool RunHitTriggers { get; private set; } = true; private ArchetypeDataBlock SafeArchetype { get { if (ArchetypeID == 0) { return base.CWC.Weapon.ArchetypeData; } return _cachedArchetype; } } public override bool ValidProperty() { if (ArchetypeID != 0) { ArchetypeDataBlock block = GameDataBlockBase.GetBlock(ArchetypeID); if (block == null) { EWCLogger.Error($"FireShot: Unable to find Archetype block with ID {ArchetypeID}!"); return false; } _cachedArchetype = block; } else { if (!base.CWC.Weapon.IsType(WeaponType.Gun)) { return false; } _cachedArchetype = null; } return base.ValidProperty(); } public override void TriggerReset() { } public void TriggerResetSync() { } public override void TriggerApply(List contexts) { //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0233: 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_00ac: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) int num = 0; List<(Vector3, Vector3, float, ShotInfo, IDamageable)> list = null; if (FireFrom != 0) { list = new List<(Vector3, Vector3, float, ShotInfo, IDamageable)>(5); foreach (TriggerContext context in contexts) { if (context.triggerAmt < 1f || !(context.context is IPositionContext positionContext)) { continue; } IDamageable item = null; Vector3 val = positionContext.Position; if (positionContext is WeaponHitDamageableContextBase weaponHitDamageableContextBase) { item = weaponHitDamageableContextBase.Damageable.GetBaseDamagable(); Agent baseAgent = weaponHitDamageableContextBase.Damageable.GetBaseAgent(); if ((Object)(object)baseAgent != (Object)null) { val = weaponHitDamageableContextBase.LocalPosition + baseAgent.Position; } } else { val += positionContext.Normal * 0.03f; } list.Add((val, (Vector3)(FireFrom switch { FireSetting.HitNormal => positionContext.Normal, FireSetting.HitReflect => Vector3.Reflect(positionContext.Direction, positionContext.Normal), _ => positionContext.Direction, }), context.triggerAmt, positionContext.ShotInfo.Orig, item)); } if (list.Count == 0) { return; } } else { num = (int)contexts.Sum((TriggerContext context) => context.triggerAmt); if (num == 0) { return; } } IWeaponComp weapon = base.CWC.Weapon; int num2 = 1; float coneSize = 0f; float segmentSize = 0f; ArchetypeDataBlock safeArchetype = SafeArchetype; if (weapon.IsShotgun && !ForceSingleBullet) { num2 = safeArchetype.ShotgunBulletCount; coneSize = safeArchetype.ShotgunConeSize; segmentSize = (float)Math.PI / 180f * (360f / (float)(num2 - 1)); } float num3 = Spread; if (num3 < 0f) { num3 = ((!weapon.IsShotgun) ? (weapon.IsAiming ? safeArchetype.AimSpread : safeArchetype.HipFireSpread) : ((float)safeArchetype.ShotgunBulletSpread)); } Ray ray = default(Ray); ((Ray)(ref ray))..ctor(base.CWC.Owner.FirePos, (UserUseAimDir || weapon.IsType(WeaponType.Melee)) ? base.CWC.Owner.FireDir : ShotManager.VanillaFireDir); if (FireFrom != 0) { foreach (var item7 in list) { Vector3 item2 = item7.Item1; Vector3 item3 = item7.Item2; float item4 = item7.Item3; ShotInfo item5 = item7.Item4; IDamageable item6 = item7.Item5; ((Ray)(ref ray)).origin = item2; ((Ray)(ref ray)).direction = item3; IntPtr ignoreEnt = IntPtr.Zero; if (!HitTriggerTarget && item6 != null) { ignoreEnt = ((Il2CppObjectBase)item6).Pointer; } FirePerTrigger(ray, num3, num2, segmentSize, coneSize, visual: false, item5, ignoreEnt); if (!base.CWC.HasTrait()) { TriggerManager.SendInstance(this, item2, item3, item4); } } return; } for (int i = 0; i < num; i++) { FirePerTrigger(ray, num3, num2, segmentSize, coneSize, visual: false, null, (IntPtr)0); } if (!base.CWC.HasTrait()) { TriggerManager.SendInstance(this, num); } } public void TriggerApplySync(Vector3 position, Vector3 direction, float triggerSum) { //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_0095: Unknown result type (might be due to invalid IL or missing references) int num = (int)Math.Round(triggerSum); Ray ray = default(Ray); ((Ray)(ref ray))..ctor(position, direction); IWeaponComp weapon = base.CWC.Weapon; int num2 = 1; int num3 = 0; float segmentSize = 0f; ArchetypeDataBlock safeArchetype = SafeArchetype; if (weapon.IsShotgun && !ForceSingleBullet) { num2 = safeArchetype.ShotgunBulletCount; num3 = safeArchetype.ShotgunConeSize; segmentSize = (float)Math.PI / 180f * (360f / (float)(num2 - 1)); } float num4 = Spread; if (num4 < 0f) { num4 = (weapon.IsShotgun ? ((float)safeArchetype.ShotgunBulletSpread) : 0f); } for (int i = 0; i < num; i++) { FirePerTrigger(ray, num4, num2, segmentSize, num3, visual: true, null, (IntPtr)0); } } public void TriggerApplySync(float iterations) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) TriggerApplySync(base.CWC.Owner.FirePos, base.CWC.Owner.FireDir, iterations); } private void FirePerTrigger(Ray ray, float spread, int shotgunBullets, float segmentSize, float coneSize, bool visual, ShotInfo? shotInfo = null, IntPtr ignoreEnt = default(IntPtr)) { //IL_006b: 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_00b2: 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) float num = 1f; if (!IgnoreSpreadMod) { num = base.CWC.SpreadController.Value; spread *= num; coneSize *= num; } for (uint num2 = 1u; num2 <= Repeat + 1; num2++) { for (int i = 0; i < Offsets.Length; i += 2) { float num3 = Offsets[i] * (float)num2 * num; float num4 = Offsets[i + 1] * (float)num2 * num; if (visual) { FireVisual(ray, num3, num4, spread); } else { Fire(ray, num3, num4, spread, shotInfo, ignoreEnt); } for (int j = 1; j < shotgunBullets; j++) { float num5 = segmentSize * (float)j; if (visual) { FireVisual(ray, num3 + coneSize * (float)Math.Cos(num5), num4 + coneSize * (float)Math.Sin(num5), spread); } else { Fire(ray, num3 + coneSize * (float)Math.Cos(num5), num4 + coneSize * (float)Math.Sin(num5), spread, shotInfo, ignoreEnt); } } } } } private void Fire(Ray ray, float x, float y, float spread, ShotInfo? orig, IntPtr ignoreEnt) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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) //IL_00dc: 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_00f5: Unknown result type (might be due to invalid IL or missing references) ArchetypeDataBlock safeArchetype = SafeArchetype; HitData hitData = new HitData(DamageType.Bullet); hitData.owner = base.CWC.Owner.Player; hitData.shotInfo.Reset(safeArchetype.Damage, safeArchetype.PrecisionDamageMulti, safeArchetype.StaggerDamageMulti, base.CWC, orig, UseParentShotMod); hitData.ResetDamage(); hitData.damageFalloff = safeArchetype.DamageFalloff; hitData.pierceLimit = safeArchetype.PierceLimit(); hitData.maxRayDist = base.CWC.Weapon.MaxRayDist; hitData.angOffsetX = x; hitData.angOffsetY = y; hitData.randomSpread = spread; hitData.RayHit = default(RaycastHit); int num = 0; if (DamageOwner) { num |= LayerUtil.MaskLocal; } if (DamageFriendly) { num |= LayerUtil.MaskFriendly; } ToggleRunTriggers(enable: false); base.CWC.ShotComponent.FireSpread(ray, (FireFrom != 0) ? ((Ray)(ref ray)).origin : base.CWC.Owner.MuzzleAlign.position, hitData, num, ignoreEnt); ToggleRunTriggers(enable: true); } private void ToggleRunTriggers(bool enable) { if (!RunHitTriggers) { base.CWC.RunHitTriggers = enable; } } private void FireVisual(Ray ray, float x, float y, float spread) { //IL_0058: 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_0071: Unknown result type (might be due to invalid IL or missing references) ArchetypeDataBlock safeArchetype = SafeArchetype; HitData hitData = new HitData(DamageType.Bullet) { owner = base.CWC.Owner.Player, damage = safeArchetype.Damage, pierceLimit = 1, angOffsetX = x, angOffsetY = y, randomSpread = spread }; base.CWC.ShotComponent.FireSpread(ray, (FireFrom != 0) ? ((Ray)(ref ray)).origin : base.CWC.Owner.MuzzleAlign.position, hitData, -1, (IntPtr)0); } public override WeaponPropertyBase Clone() { FireShot obj = (FireShot)base.Clone(); obj.Offsets = (float[])Offsets.Clone(); return obj; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); EWCJson.Serialize(writer, "Offsets", Offsets); writer.WriteNumber("ArchetypeID", ArchetypeID); writer.WriteNumber("Repeat", Repeat); writer.WriteNumber("Spread", Spread); writer.WriteBoolean("IgnoreSpreadMod", IgnoreSpreadMod); writer.WriteBoolean("UseParentShotMod", UseParentShotMod); writer.WriteBoolean("ForceSingleBullet", ForceSingleBullet); writer.WriteString("FireFrom", FireFrom.ToString()); writer.WriteBoolean("UserUseAimDir", UserUseAimDir); writer.WriteBoolean("DamageFriendly", DamageFriendly); writer.WriteBoolean("DamageOwner", DamageOwner); writer.WriteBoolean("HitTriggerTarget", HitTriggerTarget); writer.WriteBoolean("RunHitTriggers", RunHitTriggers); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 7: { char c = property[0]; if (c != 'o') { if (c != 'r' || !(property == "repeats")) { return; } goto IL_02ed; } if (!(property == "offsets")) { return; } goto IL_02d3; } case 6: switch (property[0]) { case 'o': break; case 'a': goto IL_016e; case 'r': goto IL_017f; case 's': if (property == "spread") { Spread = reader.GetSingle(); } return; default: return; } if (!(property == "offset")) { return; } goto IL_02d3; case 11: { char c = property[0]; if (c != 'a') { if (c != 'd') { if (c != 'h' || !(property == "hittriggers")) { return; } break; } if (!(property == "damageowner")) { return; } goto IL_035b; } if (!(property == "archetypeid")) { return; } goto IL_02e0; } case 9: { char c = property[0]; if (c != 'a') { if (c != 'u' || !(property == "useaimdir")) { return; } goto IL_0341; } if (!(property == "archetype")) { return; } goto IL_02e0; } case 16: switch (property[0]) { default: return; case 'u': break; case 'h': if (property == "hittriggertarget") { HitTriggerTarget = reader.GetBoolean(); } return; } if (!(property == "useparentshotmod")) { return; } goto IL_0314; case 13: { char c = property[0]; if (c != 'p') { if (c != 'u' || !(property == "useruseaimdir")) { return; } goto IL_0341; } if (!(property == "parentshotmod")) { return; } goto IL_0314; } case 12: { char c = property[0]; if (c != 'f') { if (c != 's' || !(property == "singlebullet")) { return; } goto IL_0321; } if (!(property == "friendlyfire")) { return; } goto IL_034e; } case 14: { char c = property[0]; if (c != 'd') { if (c != 'r' || !(property == "runhittriggers")) { return; } break; } if (!(property == "damagefriendly")) { return; } goto IL_034e; } case 4: if (!(property == "arch")) { return; } goto IL_02e0; case 15: if (property == "ignorespreadmod") { IgnoreSpreadMod = reader.GetBoolean(); } return; case 17: if (!(property == "forcesinglebullet")) { return; } goto IL_0321; case 8: if (property == "firefrom") { FireFrom = reader.GetString().ToEnum(FireSetting.User); } return; case 10: if (!(property == "damageuser")) { return; } goto IL_035b; case 5: return; IL_0314: UseParentShotMod = reader.GetBoolean(); return; IL_02e0: ArchetypeID = EWCJson.Deserialize(ref reader); return; IL_0341: UserUseAimDir = reader.GetBoolean(); return; IL_017f: if (!(property == "repeat")) { return; } goto IL_02ed; IL_016e: if (!(property == "archid")) { return; } goto IL_02e0; IL_0321: ForceSingleBullet = reader.GetBoolean(); return; IL_034e: DamageFriendly = reader.GetBoolean(); return; IL_02d3: Offsets = JsonUtil.ReadPairs(ref reader); return; IL_02ed: Repeat = reader.GetUInt32(); return; IL_035b: DamageOwner = reader.GetBoolean(); return; } RunHitTriggers = reader.GetBoolean(); } } public enum FireSetting { User, HitPos, HitNormal, HitReflect } public sealed class Foam : Effect, ISyncProperty, IWeaponProperty { private const float WallHitBuffer = 0.03f; private int _layerDynamic; public ushort SyncPropertyID { get; set; } public float Amount { get; private set; } public float PrecisionAmountMulti { get; private set; } public bool IgnoreArmor { get; private set; } public bool IgnoreBackstab { get; private set; } public bool IgnoreShotMods { get; private set; } public float BubbleAmount { get; private set; } public float BubbleStrength { get; private set; } = 1f; public float BubbleExpandSpeed { get; private set; } = 0.3f; public bool BubbleOnDoors { get; private set; } = true; public bool BubbleIgnoreModifiers { get; private set; } = true; public float BubbleLifetime { get; private set; } public float FoamTime { get; private set; } public FoamOverrideType FoamTimeType { get; private set; } public bool IgnoreFalloff { get; private set; } public bool IgnoreBooster { get; private set; } = true; private int LayerDynamic { get { if (_layerDynamic == 0) { return _layerDynamic = LayerManager.LAYER_DYNAMIC; } return _layerDynamic; } } public Foam() { if (base.Trigger == null) { TriggerCoordinator triggerCoordinator2 = (base.Trigger = new TriggerCoordinator(ITrigger.GetTrigger(TriggerName.BulletLanded))); } SetValidTriggers(DamageType.Player | DamageType.Object, ITrigger.HitTriggers.Extend(TriggerName.BulletLanded, TriggerName.ChargeLanded)); } public override void TriggerReset() { } public override void TriggerApply(List triggerList) { //IL_008d: 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_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) PlayerAgent player = base.CWC.Owner.Player; float num = (IgnoreBooster ? 1f : AgentModifierManager.ApplyModifier((Agent)(object)player, (AgentModifier)100, 1f)); foreach (TriggerContext trigger in triggerList) { WeaponHitContextBase weaponHitContextBase = (WeaponHitContextBase)trigger.context; if (weaponHitContextBase.DamageType.HasAnyFlag(DamageType.Player | DamageType.Object)) { continue; } float num2 = trigger.triggerAmt * (IgnoreFalloff ? 1f : weaponHitContextBase.Falloff); float num3 = 1f; Vector3 position = weaponHitContextBase.Position; GameObject val = null; if (weaponHitContextBase.DamageType.HasFlag(DamageType.Enemy)) { WeaponHitDamageableContextBase weaponHitDamageableContextBase = (WeaponHitDamageableContextBase)weaponHitContextBase; float num4 = PrecisionAmountMulti; if (!IgnoreShotMods) { WeaponStatContext weaponStatContext = new WeaponStatContext(num3, num4, 1f, DamageType.Foam.WithSubTypes(weaponHitDamageableContextBase.Damageable), weaponHitDamageableContextBase.Damageable, weaponHitContextBase.ShotInfo.Orig, base.CWC.DebuffIDs); base.CWC.Invoke(weaponStatContext); num3 = weaponStatContext.Damage; num4 = weaponStatContext.Precision; } Dam_EnemyDamageLimb val2 = ((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable).Cast(); val = ((Component)val2).gameObject; EnemyAgent val3 = ((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable.GetBaseAgent()).Cast(); position = weaponHitDamageableContextBase.LocalPosition + val3.Position; if (weaponHitDamageableContextBase.DamageType.HasFlag(DamageType.Weakspot)) { num3 = Math.Max(num3, num3 * num4 * val2.m_weakspotDamageMulti); } if (!IgnoreBackstab) { num3 *= weaponHitDamageableContextBase.Backstab; } if (!IgnoreArmor) { float armorMulti = val2.m_armorDamageMulti; DebuffManager.GetAndApplyArmorShredDebuff(ref armorMulti, weaponHitDamageableContextBase.Damageable, base.CWC.DebuffIDs); num3 *= armorMulti; } FoamActionManager.FoamDirect(val2.m_base.Owner, Amount * num * num2 * num3, this); } else { position += weaponHitContextBase.Normal * 0.03f; } if (BubbleAmount <= 0f) { break; } if (!BubbleIgnoreModifiers) { num2 *= num3; } if ((Object)(object)val != (Object)null) { FoamActionManager.FoamEnemy(val, player, position, num2, this); } else { if (weaponHitContextBase.DamageType.HasFlag(DamageType.Enemy)) { continue; } val = weaponHitContextBase.GameObject; if ((Object)(object)val != (Object)null && val.layer == LayerDynamic) { if (!BubbleOnDoors) { break; } iLG_WeakDoor_Destruction componentInParent = val.GetComponentInParent(); if (componentInParent != null && !componentInParent.SkinnedDoorEnabled) { componentInParent.EnableSkinnedDoor(); val = ((Component)componentInParent.FindCollider(position)).gameObject; } FoamActionManager.FoamDoor(val, player, position, num2, this); } else { FoamActionManager.FoamStatic(player, position, num2, this); } } } } public float GetMaxFoamTime(float origTime) { if (FoamTime <= 0f) { return origTime; } return FoamTimeType switch { FoamOverrideType.Min => Math.Min(origTime, FoamTime), FoamOverrideType.Mult => origTime * FoamTime, FoamOverrideType.Override => FoamTime, _ => origTime, }; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Amount", Amount); writer.WriteNumber("PrecisionAmountMulti", PrecisionAmountMulti); writer.WriteBoolean("IgnoreArmor", IgnoreArmor); writer.WriteBoolean("IgnoreBackstab", IgnoreBackstab); writer.WriteBoolean("IgnoreShotMods", IgnoreShotMods); writer.WriteNumber("BubbleAmount", BubbleAmount); writer.WriteNumber("BubbleStrength", BubbleStrength); writer.WriteNumber("BubbleExpandSpeed", BubbleExpandSpeed); writer.WriteBoolean("BubbleOnDoors", BubbleOnDoors); writer.WriteBoolean("BubbleIgnoreModifiers", BubbleIgnoreModifiers); writer.WriteNumber("BubbleLifetime", BubbleLifetime); writer.WriteNumber("FoamTime", FoamTime); writer.WriteString("FoamTimeType", FoamTimeType.ToString()); writer.WriteBoolean("IgnoreFalloff", IgnoreFalloff); writer.WriteBoolean("IgnoreBooster", IgnoreBooster); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 6: switch (property[0]) { default: return; case 'a': if (property == "amount") { Amount = reader.GetSingle(); } return; case 'b': break; } if (!(property == "bubble")) { return; } goto IL_0395; case 14: { char c = property[7]; if ((uint)c <= 104u) { switch (c) { default: return; case 'a': if (property == "ignorebackstab") { IgnoreBackstab = reader.GetBoolean(); } return; case 'h': break; } if (!(property == "ignoreshotmods")) { return; } goto IL_0388; } if (c != 'i') { if (c != 'o') { if (c != 't' || !(property == "bubblestrength")) { return; } goto IL_03a2; } if (!(property == "precisionmulti")) { return; } goto IL_0361; } if (!(property == "bubblelifetime")) { return; } goto IL_03d6; } case 13: { char c = property[6]; if ((uint)c <= 102u) { switch (c) { case 'f': if (property == "ignorefalloff") { IgnoreFalloff = reader.GetBoolean(); } break; case 'b': if (property == "ignorebooster") { IgnoreBooster = reader.GetBoolean(); } break; } return; } if (c != 'i') { if (c != 'o') { if (c != 's' || !(property == "ignoreshotmod")) { return; } goto IL_0388; } if (!(property == "bubbleondoors")) { return; } goto IL_03bc; } if (!(property == "precisionmult")) { return; } goto IL_0361; } case 11: switch (property[0]) { default: return; case 'i': if (property == "ignorearmor") { IgnoreArmor = reader.GetBoolean(); } return; case 'e': break; } if (!(property == "expandspeed")) { return; } goto IL_03af; case 16: { char c = property[0]; if (c != 'b') { if (c != 'i' || !(property == "ignoredamagemods")) { return; } goto IL_0388; } if (!(property == "bubbleignoremods")) { return; } goto IL_03c9; } case 12: { char c = property[0]; if (c != 'b') { if (c != 'f' || !(property == "foamtimetype")) { return; } break; } if (!(property == "bubbleamount")) { return; } goto IL_0395; } case 8: { char c = property[0]; if ((uint)c <= 108u) { if (c != 'f') { if (c != 'l' || !(property == "lifetime")) { return; } goto IL_03d6; } if (!(property == "foamtime")) { return; } goto IL_03e3; } if (c != 's') { if (c != 't' || !(property == "timetype")) { return; } break; } if (!(property == "strength")) { return; } goto IL_03a2; } case 20: if (!(property == "precisionamountmulti")) { return; } goto IL_0361; case 9: if (!(property == "precision")) { return; } goto IL_0361; case 15: if (!(property == "ignoredamagemod")) { return; } goto IL_0388; case 17: if (!(property == "bubbleexpandspeed")) { return; } goto IL_03af; case 7: if (!(property == "ondoors")) { return; } goto IL_03bc; case 21: if (!(property == "bubbleignoremodifiers")) { return; } goto IL_03c9; case 4: if (!(property == "time")) { return; } goto IL_03e3; case 5: case 10: case 18: case 19: return; IL_03bc: BubbleOnDoors = reader.GetBoolean(); return; IL_03c9: BubbleIgnoreModifiers = reader.GetBoolean(); return; IL_0388: IgnoreShotMods = reader.GetBoolean(); return; IL_03e3: FoamTime = reader.GetSingle(); return; IL_0361: PrecisionAmountMulti = reader.GetSingle(); return; IL_03af: BubbleExpandSpeed = reader.GetSingle(); return; IL_0395: BubbleAmount = reader.GetSingle(); return; IL_03a2: BubbleStrength = reader.GetSingle(); return; IL_03d6: BubbleLifetime = reader.GetSingle(); return; } FoamTimeType = reader.GetString().ToEnum(FoamOverrideType.Min); } } public enum FoamOverrideType { Min = 0, Mult = 1, Multiply = 1, Override = 2 } public sealed class ForceFire : Effect { public WeaponState RequiredState { get; private set; } protected override WeaponType RequiredWeaponType => WeaponType.BulletWeapon; protected override OwnerType RequiredOwnerType => OwnerType.Local; public override void TriggerApply(List contexts) { BulletWeaponArchetype gunArchetype = ((LocalGunComp)base.CWC.Weapon).GunArchetype; FirstPersonItemHolder fPItemHolder = base.CWC.Owner.Player.FPItemHolder; ItemEquippable wieldedItem = fPItemHolder.WieldedItem; bool flag = ((wieldedItem != null) ? new IntPtr?(((Il2CppObjectBase)wieldedItem).Pointer) : null) == ((Il2CppObjectBase)base.CWC.Weapon.Component).Pointer; if ((!flag && RequiredState.HasFlag(WeaponState.Held)) || (flag && fPItemHolder.ItemIsBusy) || gunArchetype.m_clip <= 0f) { return; } float time = Clock.Time; bool flag2 = time < gunArchetype.m_nextShotTimer || time < gunArchetype.m_nextBurstTimer; if (RequiredState.HasFlag(WeaponState.Ready) && (gunArchetype.m_firing || flag2)) { return; } if (flag2) { FireRateAPI.FireCooldownInterruptCallback(gunArchetype.m_weapon); } if (gunArchetype.m_firing) { gunArchetype.OnFireShot(); gunArchetype.PostFireCheck(); return; } if (gunArchetype.m_inChargeup) { gunArchetype.m_inChargeup = false; GuiManager.CrosshairLayer.SetChargeUpVisibleAndProgress(false, 0f); } gunArchetype.m_readyToFire = true; gunArchetype.OnStartFiring(); gunArchetype.OnFireShot(); gunArchetype.PostFireCheck(); gunArchetype.m_clip = ((ItemEquippable)gunArchetype.m_weapon).GetCurrentClip(); } public override void TriggerReset() { } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteString("RequiredState", RequiredState.ToString()); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "requiredstate" || property == "required") { RequiredState = ToWeaponState(reader.GetString()); } } private static WeaponState ToWeaponState(string value) { value = value.Replace(" ", null).ToLower(); WeaponState weaponState = WeaponState.None; if (value == "all") { return WeaponState.All; } if (value.Contains("ready")) { weaponState |= WeaponState.Ready; } if (value.Contains("held")) { weaponState |= WeaponState.Held; } return weaponState; } } [Flags] public enum WeaponState { None = 0, Ready = 1, Held = 2, All = -1 } public sealed class HealthMod : Effect { public float HealthChangeRel { get; private set; } public float CapRel { get; private set; } = -1f; public bool CancelRegen { get; private set; } public bool StopBleed { get; private set; } public bool ApplyToTarget { get; private set; } public bool EnableDamageFX { get; private set; } = true; public override void TriggerReset() { } public override void TriggerApply(List contexts) { if (ApplyToTarget) { foreach (TriggerContext context in contexts) { PlayerAgent val = (PlayerAgent)((!(context.context is WeaponHitDamageableContextBase weaponHitDamageableContextBase) || !weaponHitDamageableContextBase.DamageType.HasFlag(DamageType.Player)) ? ((object)base.CWC.Owner.Player) : ((object)((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable.GetBaseAgent()).Cast())); if ((Object)(object)val != (Object)null) { DoHeal(val, context.triggerAmt); } } return; } if ((Object)(object)base.CWC.Owner.Player != (Object)null) { DoHeal(base.CWC.Owner.Player, contexts.Sum((TriggerContext tContext) => tContext.triggerAmt)); } } private void DoHeal(PlayerAgent target, float mod) { float num = ((CapRel >= 0f) ? CapRel : ((float)((HealthChangeRel > 0f) ? 1 : 0))); float heal = HealthChangeRel * ((Dam_SyncedDamageBase)target.Damage).HealthMax * mod; HealManager.DoHeal(target, heal, num * ((Dam_SyncedDamageBase)target.Damage).HealthMax, this); if (StopBleed) { EECAPIWrapper.StopBleed(target); } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("HealthChangeRel", HealthChangeRel); writer.WriteNumber("CapRel", CapRel); writer.WriteBoolean("CancelRegen", CancelRegen); writer.WriteBoolean("StopBleed", StopBleed); writer.WriteBoolean("ApplyToTarget", ApplyToTarget); writer.WriteBoolean("EnableDamageFX", EnableDamageFX); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 9: switch (property[0]) { default: return; case 'h': break; case 's': if (property == "stopbleed") { StopBleed = reader.GetBoolean(); } return; } if (!(property == "healthrel")) { break; } goto IL_012c; case 6: { char c = property[0]; if (c != 'c') { if (c != 'h' || !(property == "health")) { break; } goto IL_012c; } if (!(property == "caprel")) { break; } goto IL_0139; } case 15: if (!(property == "healthchangerel")) { break; } goto IL_012c; case 12: if (!(property == "healthchange")) { break; } goto IL_012c; case 7: if (!(property == "healrel")) { break; } goto IL_012c; case 4: if (!(property == "heal")) { break; } goto IL_012c; case 3: if (!(property == "cap")) { break; } goto IL_0139; case 11: if (property == "cancelregen") { CancelRegen = reader.GetBoolean(); } break; case 13: if (property == "applytotarget") { ApplyToTarget = reader.GetBoolean(); } break; case 14: if (property == "enabledamagefx") { EnableDamageFX = reader.GetBoolean(); } break; case 5: case 8: case 10: break; IL_0139: CapRel = reader.GetSingle(); break; IL_012c: HealthChangeRel = reader.GetSingle(); break; } } } public sealed class HealthShotMod : Effect, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private Dam_PlayerDamageBase _damBase; public float ModAtMin { get; private set; } = 1f; public float ModAtMax { get; private set; } = 1f; public float HealthMinRel { get; private set; } public float HealthMaxRel { get; private set; } = 1f; public float Exponent { get; private set; } = 1f; public bool FlipExponent { get; private set; } public StatType StatType { get; private set; } public StackType StackLayer { get; private set; } = StackType.Multiply; public DamageType[] DamageType { get; private set; } = DamageTypeConst.Any; public bool StoreOnGroup { get; private set; } = true; public bool CalcWhenHit { get; private set; } public override bool ValidProperty() { if (base.CWC.Owner.IsType(OwnerType.Sentry) && (Object)(object)base.CWC.Owner.Player == (Object)null) { return false; } return base.ValidProperty(); } public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponShotGroupInitContext)) { if (!CalcWhenHit) { return StoreOnGroup; } return false; } if (contextType == typeof(WeaponShotInitContext)) { if (!CalcWhenHit) { return !StoreOnGroup; } return false; } if (contextType == typeof(WeaponStatContext)) { return CalcWhenHit; } return base.ShouldRegister(contextType); } public override void TriggerReset() { } public override void TriggerApply(List contexts) { } public void Invoke(WeaponCreatedContext context) { _damBase = base.CWC.Owner.Player.Damage; } public void Invoke(WeaponShotInitContext context) { context.Mod.Add(this, StatType, GetMod(), 0f, StackType.Override, StackLayer, null, DamageType); } public void Invoke(WeaponShotGroupInitContext context) { context.GroupMod.Add(this, StatType, GetMod(), 0f, StackType.Override, StackLayer, null, DamageType); } public void Invoke(WeaponStatContext context) { context.AddMod(StatType, GetMod(), StackLayer); } private float GetMod() { if (FlipExponent) { return (((Dam_SyncedDamageBase)_damBase).Health / ((Dam_SyncedDamageBase)_damBase).HealthMax).MapInverted(HealthMinRel, HealthMaxRel, ModAtMin, ModAtMax, Exponent); } return (((Dam_SyncedDamageBase)_damBase).Health / ((Dam_SyncedDamageBase)_damBase).HealthMax).Map(HealthMinRel, HealthMaxRel, ModAtMin, ModAtMax, Exponent); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("ModAtMin", ModAtMin); writer.WriteNumber("ModAtMax", ModAtMax); writer.WriteNumber("HealthMinRel", HealthMinRel); writer.WriteNumber("HealthMaxRel", HealthMaxRel); writer.WriteNumber("Exponent", Exponent); writer.WriteBoolean("FlipExponent", FlipExponent); writer.WriteString("StatType", StatType.ToString()); writer.WriteString("DamageType", DamageType[0].ToString()); writer.WriteString("StackLayer", StackLayer.ToString()); writer.WriteBoolean("StoreOnGroup", StoreOnGroup); writer.WriteBoolean("CalcWhenHit", CalcWhenHit); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 8: switch (property[6]) { default: return; case 'i': if (property == "modatmin") { ModAtMin = reader.GetSingle(); } return; case 'a': if (property == "modatmax") { ModAtMax = reader.GetSingle(); } return; case 'n': if (property == "exponent") { Exponent = reader.GetSingle(); } return; case 'p': break; } if (!(property == "stattype")) { return; } goto IL_02b2; case 12: { char c = property[7]; if ((uint)c <= 103u) { if (c != 'a') { if (c != 'g' || !(property == "storeongroup")) { return; } break; } if (!(property == "healthmaxrel")) { return; } goto IL_028b; } if (c != 'i') { if (c != 'o' || !(property == "flipexponent")) { return; } goto IL_02a5; } if (!(property == "healthminrel")) { return; } goto IL_027e; } case 9: { char c = property[7]; if (c != 'a') { if (c != 'i' || !(property == "healthmin")) { return; } goto IL_027e; } if (!(property == "healthmax")) { return; } goto IL_028b; } case 4: { char c = property[0]; if (c != 'f') { if (c != 's' || !(property == "stat")) { return; } goto IL_02b2; } if (!(property == "flip")) { return; } goto IL_02a5; } case 11: switch (property[0]) { default: return; case 'm': break; case 'c': if (property == "calcwhenhit") { CalcWhenHit = reader.GetBoolean(); } return; } if (!(property == "modstattype")) { return; } goto IL_02b2; case 10: { char c = property[0]; if (c != 'd') { if (c != 's' || !(property == "stacklayer")) { return; } goto IL_02d7; } if (!(property == "damagetype")) { return; } goto IL_02c5; } case 7: if (!(property == "modstat")) { return; } goto IL_02b2; case 13: if (!(property == "moddamagetype")) { return; } goto IL_02c5; case 5: if (!(property == "layer")) { return; } goto IL_02d7; case 15: if (!(property == "storemodongroup")) { return; } break; case 6: case 14: return; IL_028b: HealthMaxRel = reader.GetSingle(); return; IL_02d7: StackLayer = reader.GetString().ToEnum(StackType.Invalid); return; IL_02c5: DamageType = reader.GetString().ToDamageTypes(); return; IL_02a5: FlipExponent = reader.GetBoolean(); return; IL_02b2: StatType = reader.GetString().ToEnum(StatType.Damage); return; IL_027e: HealthMinRel = reader.GetSingle(); return; } StoreOnGroup = reader.GetBoolean(); } } public sealed class InfectionMod : Effect { public float InfectionChangeRel { get; private set; } public float CapRel { get; private set; } = -1f; public bool ApplyToTarget { get; private set; } public bool ApplyToBots { get; private set; } = true; public bool EnableFX { get; private set; } = true; public override void TriggerReset() { } public override void TriggerApply(List contexts) { //IL_0064: 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) if (ApplyToTarget) { foreach (TriggerContext context in contexts) { if (context.context is WeaponHitDamageableContextBase weaponHitDamageableContextBase && weaponHitDamageableContextBase.DamageType.HasFlag(DamageType.Player)) { PlayerAgent target = ((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable.GetBaseAgent()).Cast(); DoInfection(target, context.triggerAmt, weaponHitDamageableContextBase.Position, weaponHitDamageableContextBase.Direction); } else { PlayerAgent target = base.CWC.Owner.Player; if ((Object)(object)target != (Object)null) { DoInfection(target, context.triggerAmt); } } } return; } if ((Object)(object)base.CWC.Owner.Player != (Object)null) { DoInfection(base.CWC.Owner.Player, contexts.Sum((TriggerContext tContext) => tContext.triggerAmt)); } } private void DoInfection(PlayerAgent target, float mod, Vector3 pos, Vector3 dir) { //IL_002a: 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) //IL_0040: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0062: Unknown result type (might be due to invalid IL or missing references) if (!ApplyToBots && target.Owner.IsBot) { return; } float num = CalcInfection(target, mod); if (num == 0f) { return; } pInfection val = default(pInfection); val.amount = num; val.mode = (pInfectionMode)1; pInfection val2 = val; if (EnableFX && !target.Owner.IsBot) { if (num < 0f) { val2.effect = (pInfectionEffect)1; } else { InfectionManager.DoInfectFX(target, num, pos, dir); } } target.Damage.ModifyInfection(val2, true, true); } private void DoInfection(PlayerAgent target, float mod) { //IL_0014: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) float num = CalcInfection(target, mod); if (num == 0f) { return; } pInfection val = default(pInfection); val.amount = num; val.mode = (pInfectionMode)1; pInfection val2 = val; if (EnableFX) { if (num < 0f) { val2.effect = (pInfectionEffect)1; } else { InfectionManager.DoDirectInfectFX(target, num); } } target.Damage.ModifyInfection(val2, true, true); } private float CalcInfection(PlayerAgent target, float mod) { float num = ((CapRel >= 0f) ? CapRel : ((float)Math.Sign(InfectionChangeRel))); float num2 = InfectionChangeRel * mod; Dam_PlayerDamageBase damage = target.Damage; if (num2 > 0f) { if (damage.Infection >= num) { return 0f; } return Math.Min(num2, num - damage.Infection); } if (damage.Infection <= num) { return 0f; } return Math.Max(num2, num - damage.Infection); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("InfectionChangeRel", InfectionChangeRel); writer.WriteNumber("CapRel", CapRel); writer.WriteBoolean("ApplyToTarget", ApplyToTarget); writer.WriteBoolean("EnableFX", EnableFX); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 9: switch (property[6]) { default: return; case 'i': if (!(property == "infection")) { return; } break; case 'r': if (!(property == "infectrel")) { return; } break; } goto IL_0121; case 6: { char c = property[0]; if (c != 'c') { if (c != 'i' || !(property == "infect")) { break; } goto IL_0121; } if (!(property == "caprel")) { break; } goto IL_012e; } case 18: if (!(property == "infectionchangerel")) { break; } goto IL_0121; case 15: if (!(property == "infectionchange")) { break; } goto IL_0121; case 12: if (!(property == "infectionrel")) { break; } goto IL_0121; case 3: if (!(property == "cap")) { break; } goto IL_012e; case 13: if (property == "applytotarget") { ApplyToTarget = reader.GetBoolean(); } break; case 11: if (property == "applytobots") { ApplyToBots = reader.GetBoolean(); } break; case 8: if (property == "enablefx") { EnableFX = reader.GetBoolean(); } break; case 4: case 5: case 7: case 10: case 14: case 16: case 17: break; IL_012e: CapRel = reader.GetSingle(); break; IL_0121: InfectionChangeRel = reader.GetSingle(); break; } } } public sealed class Noise : Effect, IWeaponProperty, IWeaponProperty, ITriggerCallbackDirSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty { private readonly Dictionary, float> _alertProgress = new Dictionary, float>(); private bool _localSoundLegacy; private static readonly List s_wakeupList = new List(); private static readonly List s_alertList = new List(); private static readonly List s_fakeAlertList = new List(); private static Ray s_ray = new Ray(Vector3.zero, Vector3.forward); private const SearchSetting SearchSettings = SearchSetting.CheckDoors; private const float InstantWakeupOutput = 1000f; private const float WakeupOutput = 1.1f; private const float AlertOutput = 0.95f; public ushort SyncID { get; set; } public float FakeAlertRadius { get; private set; } public float AlertRadius { get; private set; } public float AlertAmount { get; private set; } public float WakeUpRadius { get; private set; } public uint SoundID { get; private set; } public uint LocalSoundID { get; private set; } public CrossDoorMode CrossDoorMode { get; private set; } public bool UseNoiseSystem { get; private set; } public bool FollowUser { get; private set; } private bool LocalSoundOnly { get { if (SoundID == 0) { return !CanAlert; } return false; } } private bool CanAlert { get { if (!(FakeAlertRadius > 0f) && !(WakeUpRadius > 0f)) { if (AlertRadius > 0f) { return AlertAmount > 0f; } return false; } return true; } } private static ObjectWrapper TempWrapper => ObjectWrapper.SharedInstance; public override bool ValidProperty() { if (!CanAlert) { if (SoundID == 0) { if (LocalSoundID != 0) { return base.CWC.Owner.IsType(OwnerType.Local); } return false; } return true; } return base.ValidProperty(); } public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponStealthUpdateContext)) { if (!UseNoiseSystem && SNet.IsMaster) { return CanAlert; } return false; } return base.ShouldRegister(contextType); } public override void TriggerApply(List triggerList) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) foreach (TriggerContext trigger in triggerList) { Vector3 position = ((!FollowUser && trigger.context is WeaponHitContextBase weaponHitContextBase) ? weaponHitContextBase.Position : base.CWC.Owner.FirePos); TriggerApplySync(position, Vector3.zero, trigger.triggerAmt); if (!LocalSoundOnly) { TriggerManager.SendInstance(this, position, Vector3.zero, trigger.triggerAmt); } if (UseNoiseSystem) { MakeNoise(position); } } } public void TriggerApplySync(Vector3 position, Vector3 dir, float mod) { //IL_0001: 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) PostSound(position); if (!UseNoiseSystem && CanAlert && SNet.IsMaster) { TriggerSound(position, mod); } } private void PostSound(Vector3 position) { //IL_004c: 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) uint num = ((base.CWC.Owner.IsType(OwnerType.Local) && LocalSoundID != 0) ? LocalSoundID : SoundID); if (FollowUser) { base.CWC.Weapon.Sound.Post(num, position); } else { CellSound.Post(num, position); } } public void TriggerResetSync() { _alertProgress.Clear(); } public override void TriggerReset() { _alertProgress.Clear(); } public void Invoke(WeaponStealthUpdateContext context) { TempWrapper.Set((Agent)(object)context.Enemy); if (!_alertProgress.TryGetValue(TempWrapper, out var value)) { return; } if (value >= 1000f) { context.Output = 1000f; _alertProgress.Remove(TempWrapper); return; } if (!context.Detecting) { _alertProgress.Remove(TempWrapper); return; } float num = ((value >= 1f) ? 1.1f : 0.95f); if (num > context.Output) { context.Output = num; } } private void TriggerSound(Vector3 position, float amount) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) if (!SNet.IsMaster) { return; } AIG_CourseNode courseNode = CourseNodeUtil.GetCourseNode(position, base.CWC.Owner.DimensionIndex); bool flag = AlertRadius > WakeUpRadius; bool flag2 = FakeAlertRadius > AlertRadius && FakeAlertRadius > WakeUpRadius; ((Ray)(ref s_ray)).origin = position; if (flag2) { s_fakeAlertList.Clear(); s_fakeAlertList.AddRange(SearchUtil.GetEnemiesInRange(s_ray, FakeAlertRadius, 180f, courseNode, SearchSetting.CheckDoors)); } if (flag) { foreach (ObjectWrapper item in _alertProgress.Keys.Where((ObjectWrapper key) => (Object)(object)key.Object == (Object)null || !key.Object.Alive).ToList()) { _alertProgress.Remove(item); } s_alertList.Clear(); s_alertList.AddRange(SearchUtil.GetEnemiesInRange(s_ray, AlertRadius, 180f, courseNode, SearchSetting.CheckDoors)); } s_wakeupList.Clear(); s_wakeupList.AddRange(SearchUtil.GetEnemiesInRange(s_ray, WakeUpRadius, 180f, courseNode, SearchSetting.CheckDoors)); for (int num = s_wakeupList.Count - 1; num >= 0; num--) { EnemyAgent val = s_wakeupList[num]; if (flag) { RemoveFromList(val, s_alertList); } if (flag2) { RemoveFromList(val, s_fakeAlertList); } if (EnemyCanHear(position, courseNode, val)) { TempWrapper.Set((Agent)(object)val); if (!_alertProgress.ContainsKey(TempWrapper)) { _alertProgress.Add(new ObjectWrapper((Agent)(object)val), 0f); } _alertProgress[TempWrapper] += 1000f; } } for (int num2 = s_alertList.Count - 1; num2 >= 0; num2--) { EnemyAgent val2 = s_alertList[num2]; if (flag2) { RemoveFromList(val2, s_fakeAlertList); } if (EnemyCanHear(position, courseNode, val2)) { TempWrapper.Set((Agent)(object)val2); if (!_alertProgress.ContainsKey(TempWrapper)) { _alertProgress.Add(new ObjectWrapper((Agent)(object)val2), 0f); } EnemyDetection detection = val2.AI.m_detection; if ((int)detection.m_noiseDetectionStatus == 0) { detection.m_statusTimerEnd = 0f; } else if (detection.m_noiseDetectionOn) { _alertProgress[TempWrapper] += AlertAmount * amount; } } } foreach (EnemyAgent s_fakeAlert in s_fakeAlertList) { if (EnemyCanHear(position, courseNode, s_fakeAlert)) { s_fakeAlert.AI.m_locomotion.Hibernate.Heartbeat(0.5f, base.CWC.Owner.FirePos); } } } private bool EnemyCanHear(Vector3 position, AIG_CourseNode node, EnemyAgent enemy) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!enemy.ListenerReady) { return false; } if (CrossDoorMode == CrossDoorMode.None && ((Agent)enemy).CourseNode.NodeID != node.NodeID) { return false; } float weaponDetectionDistanceMax = enemy.EnemyDetectionData.weaponDetectionDistanceMax; Vector3 val = position - enemy.Position; if (((Vector3)(ref val)).sqrMagnitude >= weaponDetectionDistanceMax * weaponDetectionDistanceMax) { return false; } return true; } private void RemoveFromList(EnemyAgent remove, List list) { for (int num = list.Count - 1; num >= 0; num--) { if (((Il2CppObjectBase)remove).Pointer == ((Il2CppObjectBase)list[num]).Pointer) { list.RemoveAt(num); break; } } } private void MakeNoise(Vector3 position) { //IL_001d: 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_0026: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (!(WakeUpRadius <= 0f) || !(FakeAlertRadius <= 0f)) { pNM_NoiseData val = default(pNM_NoiseData); val.position = position; val.radiusMin = WakeUpRadius; val.radiusMax = Math.Max(WakeUpRadius + 0.01f, FakeAlertRadius); val.yScale = 1f; val.includeToNeightbourAreas = CrossDoorMode != CrossDoorMode.None; val.raycastFirstNode = false; val.type = (NM_NoiseType)1; pNM_NoiseData val2 = val; ((pPlayerAgent)(ref val2.noiseMaker)).Set(base.CWC.Owner.Player); ((pCourseNode)(ref val2.node)).Set(CourseNodeUtil.GetCourseNode(position, base.CWC.Owner.DimensionIndex)); if (SNet.IsMaster) { NoiseManager.ReceiveNoise(val2); } else { NoiseManager.s_noisePacket.Send(val2, (SNet_ChannelType)4, SNet.Master); } } } public override WeaponPropertyBase Clone() { Noise noise = (Noise)base.Clone(); if (_localSoundLegacy) { noise.LocalSoundID = noise.SoundID; noise.SoundID = 0u; noise.AlertAmount = 0f; noise.FakeAlertRadius = 0f; noise.WakeUpRadius = 0f; } return noise; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("FakeAlertRadius", FakeAlertRadius); writer.WriteNumber("AlertRadius", AlertRadius); writer.WriteNumber("AlertAmount", AlertAmount); writer.WriteNumber("WakeUpRadius", WakeUpRadius); writer.WriteNumber("SoundID", SoundID); writer.WriteNumber("LocalSoundID", LocalSoundID); writer.WriteString("CrossDoorMode", CrossDoorMode.ToString()); writer.WriteBoolean("UseNoiseSystem", UseNoiseSystem); writer.WriteBoolean("FollowUser", FollowUser); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); string text = property.ToLowerInvariant(); if (text == null) { return; } switch (text.Length) { default: return; case 9: { char c = text[0]; if (c != 'c') { if (c != 'f' || !(text == "fakealert")) { return; } goto IL_0253; } if (!(text == "crossdoor")) { return; } goto IL_02f8; } case 11: { char c = text[5]; if (c != 'a') { if (c != 'r') { if (c != 's' || !(text == "noisesystem")) { return; } goto IL_030b; } if (!(text == "alertradius")) { return; } goto IL_0260; } if (text == "alertamount") { AlertAmount = reader.GetSingle(); } return; } case 5: { char c = text[0]; if (c != 'a') { if (c != 's' || !(text == "sound")) { return; } goto IL_0287; } if (!(text == "alert")) { return; } goto IL_0260; } case 12: { char c = text[0]; if (c != 'l') { if (c != 'w' || !(text == "wakeupradius")) { return; } goto IL_027a; } if (!(text == "localsoundid")) { return; } goto IL_02af; } case 6: { char c = text[0]; if (c != 'f') { if (c != 'w' || !(text == "wakeup")) { return; } goto IL_027a; } if (!(text == "follow")) { return; } break; } case 10: { char c = text[0]; if (c != 'c') { if (c != 'f') { if (c != 'l' || !(text == "localsound")) { return; } goto IL_02af; } if (!(text == "followuser")) { return; } break; } if (!(text == "crossdoors")) { return; } goto IL_02f8; } case 14: switch (text[0]) { default: return; case 'u': break; case 'l': if (text == "localsoundonly") { _localSoundLegacy = reader.GetBoolean(); } return; } if (!(text == "usenoisesystem")) { return; } goto IL_030b; case 15: if (!(text == "fakealertradius")) { return; } goto IL_0253; case 7: if (!(text == "soundid")) { return; } goto IL_0287; case 13: if (!(text == "crossdoormode")) { return; } goto IL_02f8; case 8: return; IL_0253: FakeAlertRadius = reader.GetSingle(); return; IL_027a: WakeUpRadius = reader.GetSingle(); return; IL_02af: if (reader.TokenType == JsonTokenType.True || reader.TokenType == JsonTokenType.False) { _localSoundLegacy = reader.GetBoolean(); } else if (reader.TokenType == JsonTokenType.String) { LocalSoundID = AkSoundEngine.GetIDFromString(reader.GetString()); } else { LocalSoundID = reader.GetUInt32(); } return; IL_030b: UseNoiseSystem = reader.GetBoolean(); return; IL_0260: AlertRadius = reader.GetSingle(); return; IL_02f8: CrossDoorMode = reader.GetString().ToEnum(CrossDoorMode.NoPenalty); return; IL_0287: if (reader.TokenType == JsonTokenType.String) { SoundID = AkSoundEngine.GetIDFromString(reader.GetString()); } else { SoundID = reader.GetUInt32(); } return; } FollowUser = reader.GetBoolean(); } } public enum CrossDoorMode { NoPenalty, None } public sealed class Push : Effect, ISyncProperty, IWeaponProperty { public ushort SyncPropertyID { get; set; } public float Force { get; private set; } public float[] Offset { get; private set; } = new float[2]; public float FrictionDelay { get; private set; } = 0.1f; public float RepeatFrictionDelay { get; private set; } = 0.1f; public float FrictionStrength { get; private set; } = 8f; public float ConstantFriction { get; private set; } = 1f; public float AirFrictionStrength { get; private set; } = 1f; public float AirConstantFriction { get; private set; } = 1f; public PushCap HorizontalCap { get; private set; } = new PushCap(); public PushCap VerticalCap { get; private set; } = new PushCap(); public float VerticalScale { get; private set; } = 1f; public bool NormalizeForce { get; private set; } = true; public bool ApplyToTarget { get; private set; } public override void TriggerApply(List contexts) { //IL_00f2: 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_008a: 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_0096: Unknown result type (might be due to invalid IL or missing references) if (ApplyToTarget) { foreach (TriggerContext context in contexts) { PlayerAgent val; Vector3 dir; if (context.context is WeaponHitDamageableContextBase weaponHitDamageableContextBase && weaponHitDamageableContextBase.DamageType.HasFlag(DamageType.Player)) { val = ((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable.GetBaseAgent()).Cast(); dir = weaponHitDamageableContextBase.Direction; } else { val = base.CWC.Owner.Player; dir = base.CWC.Owner.FireDir; } if ((Object)(object)val != (Object)null) { DoPush(val, dir, context.triggerAmt); } } return; } if ((Object)(object)base.CWC.Owner.Player != (Object)null) { DoPush(base.CWC.Owner.Player, base.CWC.Owner.FireDir, contexts.Sum((TriggerContext tContext) => tContext.triggerAmt)); } } private void DoPush(PlayerAgent target, Vector3 dir, float triggerAmt) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0054: 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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (target.Owner.IsBot) { return; } Vector3 val = dir; if (VerticalScale != 1f) { val.y *= VerticalScale; if (NormalizeForce) { val = ((Vector3)(ref val)).normalized; } } val = val.RotateBy(Offset[0], Offset[1]); val *= Force * triggerAmt; if (!(val == Vector3.zero)) { PushManager.DoPush(target, val, this); } } public override void TriggerReset() { } public override WeaponPropertyBase Clone() { Push obj = (Push)base.Clone(); obj.Offset = Offset; obj.HorizontalCap = HorizontalCap; obj.VerticalCap = VerticalCap; return obj; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Force", Force); EWCJson.Serialize(writer, "Offset", Offset); writer.WriteNumber("FrictionDelay", FrictionDelay); writer.WriteNumber("RepeatFrictionDelay", RepeatFrictionDelay); writer.WriteNumber("FrictionStrength", FrictionStrength); writer.WriteNumber("ConstantFriction", ConstantFriction); writer.WriteNumber("AirFrictionStrength", AirFrictionStrength); writer.WriteNumber("AirConstantFriction", AirConstantFriction); writer.WriteNumber("VerticalScale", VerticalScale); writer.WriteBoolean("NormalizeForce", NormalizeForce); writer.WritePropertyName("HorizontalCap"); HorizontalCap.Serialize(writer); writer.WritePropertyName("VerticalCap"); VerticalCap.Serialize(writer); writer.WriteBoolean("ApplyToTarget", ApplyToTarget); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 13: switch (property[0]) { default: return; case 'f': if (property == "frictiondelay") { FrictionDelay = reader.GetSingle(); } return; case 'h': if (property == "horizontalcap") { HorizontalCap.Deserialize(ref reader); } return; case 'v': break; case 'a': if (property == "applytotarget") { ApplyToTarget = reader.GetBoolean(); } return; } if (!(property == "verticalscale")) { break; } goto IL_0228; case 19: switch (property[3]) { case 'e': if (property == "repeatfrictiondelay") { RepeatFrictionDelay = reader.GetSingle(); } break; case 'f': if (property == "airfrictionstrength") { AirFrictionStrength = reader.GetSingle(); } break; case 'c': if (property == "airconstantfriction") { AirConstantFriction = reader.GetSingle(); } break; case 'd': break; } break; case 16: switch (property[0]) { case 'f': if (property == "frictionstrength") { FrictionStrength = reader.GetSingle(); } break; case 'c': if (property == "constantfriction") { ConstantFriction = reader.GetSingle(); } break; } break; case 5: if (property == "force") { Force = reader.GetSingle(); } break; case 6: if (property == "offset") { Offset = ReadOffset(ref reader); } break; case 11: if (property == "verticalcap") { VerticalCap.Deserialize(ref reader); } break; case 8: if (!(property == "vertical")) { break; } goto IL_0228; case 14: if (property == "normalizeforce") { NormalizeForce = reader.GetBoolean(); } break; case 7: case 9: case 10: case 12: case 15: case 17: case 18: break; IL_0228: VerticalScale = reader.GetSingle(); break; } } private static float[] ReadOffset(ref Utf8JsonReader reader) { if (reader.TokenType != JsonTokenType.StartArray) { throw new JsonException("Expected list object"); } float[] array = new float[2]; reader.Read(); if (reader.TokenType != JsonTokenType.Number) { throw new JsonException("Expected number for x offset"); } array[0] = reader.GetSingle(); reader.Read(); if (reader.TokenType != JsonTokenType.Number) { throw new JsonException("Expected number for y offset"); } array[1] = reader.GetSingle(); reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) { throw new JsonException("Expected EndArray token for [x,y] offset pair"); } return array; } } public sealed class RecoilMod : TriggerMod, IWeaponProperty, IWeaponProperty { private readonly TriggerStack _triggerStack; protected override OwnerType RequiredOwnerType => OwnerType.Local; protected override WeaponType RequiredWeaponType => WeaponType.Gun; public RecoilMod() { _triggerStack = new TriggerStack(this); } public override void TriggerReset() { _triggerStack.Clear(); } public override void TriggerApply(List contexts) { _triggerStack.Add(contexts); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? _ = null) { return _triggerStack.TryGetStacks(out stacks); } public void Invoke(WeaponRecoilContext context) { if (_triggerStack.TryGetMod(out var mod)) { context.AddMod(mod, base.StackLayer); } } } public sealed class ReferenceTrigger : Effect, IPropertyHolder, IWeaponProperty, IWeaponProperty, IWeaponProperty { [CompilerGenerated] private sealed class d__50 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public bool inProgress; public ReferenceTrigger <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__50(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown int num = <>1__state; ReferenceTrigger referenceTrigger = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (inProgress) { if (Clock.Time < referenceTrigger._nextLoopTime) { <>2__current = (object)new WaitForSeconds(referenceTrigger._nextLoopTime - Clock.Time); <>1__state = 1; return true; } break; } referenceTrigger._nextLoopTime = Clock.Time + referenceTrigger.LoopDelay; if (referenceTrigger.LoopDelay > 0f) { <>2__current = (object)new WaitForSeconds(referenceTrigger.LoopDelay); <>1__state = 2; return true; } break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; case 3: <>1__state = -1; break; } if (Clock.Time < referenceTrigger._endLoopTime) { referenceTrigger.SendApply(referenceTrigger._loopContexts); referenceTrigger._nextLoopTime = Clock.Time + referenceTrigger.LoopInterval; <>2__current = (object)new WaitForSeconds(referenceTrigger.LoopInterval); <>1__state = 3; return true; } referenceTrigger._loopRoutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private List? _callbackProperties; private float _endLoopTime; private float _nextLoopTime; private List? _loopContexts; private Coroutine? _loopRoutine; public PropertyList Properties { get; private set; } = new PropertyList(); public bool ResetOnTrigger { get; private set; } public bool SendToTrigger { get; private set; } public bool SendReset { get; private set; } = true; public float LoopDuration { get; private set; } public float LoopInterval { get; private set; } = 1f; public float LoopDelay { get; private set; } public bool LoopAddNewTriggers { get; private set; } public PropertyNode? Node { get; set; } protected override bool IsTriggerValid { get { TriggerCoordinator? trigger = base.Trigger; if (trigger == null || !trigger.Activate.Triggers.Any()) { return base.Trigger?.Reset != null; } return true; } } public override bool ShouldRegister(Type contextType) { if (LoopDuration <= 0f) { if (contextType == typeof(WeaponSetupContext)) { return false; } if (contextType == typeof(WeaponClearContext)) { return false; } } return base.ShouldRegister(contextType); } public void Invoke(WeaponSetupContext context) { if (Clock.Time < _endLoopTime) { _loopRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(LoopUpdate(inProgress: true)), (Action)null); } } public void Invoke(WeaponClearContext context) { CoroutineUtil.Stop(ref _loopRoutine); } public override void TriggerApply(List contexts) { if (LoopDuration <= 0f) { SendApply(contexts); return; } if (_loopContexts == null) { _loopContexts = contexts; } else if (LoopAddNewTriggers) { _loopContexts.AddRange(contexts); } StartLoop(); } private void SendApply(List contexts) { foreach (ITriggerCallback item in _callbackProperties.OrEmptyIfNull()) { if (!ResetOnTrigger) { if (SendToTrigger && item.Trigger != null) { item.Trigger.RemoteActivateTrigger(contexts); } else { item.TriggerApply(contexts); } } else if (SendToTrigger && item.Trigger != null) { item.Trigger.RemoteResetTrigger(contexts); } else { item.RemoteReset(); } } } public override void TriggerReset() { CoroutineUtil.Stop(ref _loopRoutine); _loopContexts = null; if (!SendReset) { return; } foreach (ITriggerCallback item in _callbackProperties.OrEmptyIfNull()) { item.RemoteReset(); } } private void StartLoop() { _endLoopTime = Clock.Time + LoopDuration; if (_loopRoutine == null) { _loopRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(LoopUpdate()), (Action)null); } } [IteratorStateMachine(typeof(d__50))] private IEnumerator LoopUpdate(bool inProgress = false) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__50(0) { <>4__this = this, inProgress = inProgress }; } private void AddTriggerCallback(ITriggerCallback callback) { if (_callbackProperties == null) { _callbackProperties = new List(); } _callbackProperties.Add(callback); } public override void OnPropertiesSetup() { foreach (WeaponPropertyBase property in Properties) { if (property is ITriggerCallback callback) { AddTriggerCallback(callback); } else { EWCLogger.Warning("ReferenceTrigger contains a non-trigger property: " + property.GetType().Name); } } base.OnPropertiesSetup(); } public override WeaponPropertyBase Clone() { ReferenceTrigger obj = (ReferenceTrigger)base.Clone(); obj.Properties = Properties.Clone(); return obj; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); EWCJson.Serialize(writer, "Properties", Properties); writer.WriteBoolean("ResetOnTrigger", ResetOnTrigger); writer.WriteBoolean("SendToTrigger", SendToTrigger); writer.WriteBoolean("SendReset", SendReset); writer.WriteNumber("LoopDuration", LoopDuration); writer.WriteNumber("LoopInterval", LoopInterval); writer.WriteNumber("LoopDelay", LoopDelay); writer.WriteBoolean("LoopAddNewTriggers", LoopAddNewTriggers); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 10: switch (property[0]) { default: return; case 'r': if (!(property == "references")) { return; } break; case 'p': if (!(property == "properties")) { return; } break; } Properties = EWCJson.Deserialize(ref reader); return; case 14: switch (property[0]) { default: return; case 'r': if (property == "resetontrigger") { ResetOnTrigger = reader.GetBoolean(); } return; case 'a': break; } if (!(property == "addnewtriggers")) { return; } break; case 9: switch (property[0]) { default: return; case 's': if (property == "sendreset") { SendReset = reader.GetBoolean(); } return; case 'l': break; } if (!(property == "loopdelay")) { return; } goto IL_01f4; case 12: { char c = property[4]; if (c != 'd') { if (c != 'i' || !(property == "loopinterval")) { return; } goto IL_01e7; } if (!(property == "loopduration")) { return; } goto IL_01da; } case 8: { char c = property[0]; if (c != 'd') { if (c != 'i' || !(property == "interval")) { return; } goto IL_01e7; } if (!(property == "duration")) { return; } goto IL_01da; } case 13: if (!(property == "sendtotrigger")) { return; } goto IL_01c0; case 11: if (!(property == "sendtrigger")) { return; } goto IL_01c0; case 5: if (!(property == "delay")) { return; } goto IL_01f4; case 18: if (!(property == "loopaddnewtriggers")) { return; } break; case 6: case 7: case 15: case 16: case 17: return; IL_01c0: SendToTrigger = reader.GetBoolean(); return; IL_01f4: LoopDelay = reader.GetSingle(); return; IL_01da: LoopDuration = reader.GetSingle(); return; IL_01e7: LoopInterval = reader.GetSingle(); return; } LoopAddNewTriggers = reader.GetBoolean(); } } public sealed class ReloadMod : TriggerMod, IWeaponProperty, IWeaponProperty { private readonly TriggerStack _triggerStack; protected override OwnerType RequiredOwnerType => OwnerType.Managed; protected override WeaponType RequiredWeaponType => WeaponType.Gun; public ReloadMod() { _triggerStack = new TriggerStack(this); } public override void TriggerReset() { _triggerStack.Clear(); } public override void TriggerApply(List contexts) { _triggerStack.Add(contexts); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? _ = null) { return _triggerStack.TryGetStacks(out stacks); } public void Invoke(WeaponReloadContext context) { if (_triggerStack.TryGetMod(out var mod)) { context.AddMod(mod, base.StackLayer); } } } public sealed class ShotMod : TriggerMod, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private readonly TriggerStack _triggerStack; public StatType StatType { get; private set; } public DamageType[] DamageType { get; private set; } = DamageTypeConst.Any; public bool StoreOnGroup { get; private set; } = true; public bool CalcWhenHit { get; private set; } public ShotMod() { _triggerStack = new TriggerStack(this); } public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponShotGroupInitContext)) { if (!CalcWhenHit) { return StoreOnGroup; } return false; } if (contextType == typeof(WeaponShotInitContext)) { if (!CalcWhenHit) { return !StoreOnGroup; } return false; } if (contextType == typeof(WeaponStatContext)) { return CalcWhenHit; } return base.ShouldRegister(contextType); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? _ = null) { return _triggerStack.TryGetStacks(out stacks); } public override void TriggerReset() { _triggerStack.Clear(); } public override void TriggerApply(List contexts) { if (!CalcWhenHit) { float mod = CalculateMod(Count(contexts)); foreach (TriggerContext context in contexts) { if (context.context is WeaponHitContextBase weaponHitContextBase) { if (StoreOnGroup) { weaponHitContextBase.ShotInfo.Orig.GroupMod.Add(this, StatType, mod, null, DamageType); } else { weaponHitContextBase.ShotInfo.Orig.Mod.Add(this, StatType, mod, null, DamageType); } } } } _triggerStack.Add(contexts); } public void Invoke(WeaponShotInitContext context) { if (_triggerStack.TryGetMod(out var mod)) { context.Mod.Add(this, StatType, mod, null, DamageType); } } public void Invoke(WeaponShotGroupInitContext context) { if (_triggerStack.TryGetMod(out var mod)) { context.GroupMod.Add(this, StatType, mod, null, DamageType); } } public void Invoke(WeaponStatContext context) { if (context.DamageType.HasFlagIn(DamageType) && _triggerStack.TryGetMod(out var mod)) { context.AddMod(StatType, mod, base.StackLayer); } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteString("StatType", StatType.ToString()); writer.WriteString("DamageType", DamageType[0].ToString()); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteBoolean("StoreOnGroup", StoreOnGroup); writer.WriteBoolean("CalcWhenHit", CalcWhenHit); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 11: switch (property[0]) { case 'm': break; case 'c': if (property == "calcwhenhit") { CalcWhenHit = reader.GetBoolean(); } return; default: return; } if (!(property == "modstattype")) { return; } goto IL_00e4; case 8: if (!(property == "stattype")) { return; } goto IL_00e4; case 7: if (!(property == "modstat")) { return; } goto IL_00e4; case 4: if (!(property == "stat")) { return; } goto IL_00e4; case 13: if (!(property == "moddamagetype")) { return; } goto IL_00f7; case 10: if (!(property == "damagetype")) { return; } goto IL_00f7; case 15: if (!(property == "storemodongroup")) { return; } break; case 12: if (!(property == "storeongroup")) { return; } break; case 5: case 6: case 9: case 14: return; IL_00f7: DamageType = reader.GetString().ToDamageTypes(); return; IL_00e4: StatType = reader.GetString().ToEnum(StatType.Damage); return; } StoreOnGroup = reader.GetBoolean(); } } public sealed class ShotModDebuff : TriggerModDebuff { public StatType StatType { get; private set; } public DamageType[] DamageType { get; private set; } = DamageTypeConst.Any; protected override DebuffModifierBase AddModifier(IDamageable damageable) { return DebuffManager.AddShotModDebuff(damageable, 1f, StatType, base.StackLayer, DamageType, base.DebuffID); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteString("StatType", StatType.ToString()); writer.WriteString("DamageType", DamageType[0].ToString()); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteNumber("DebuffID", base.DebuffID); writer.WriteNumber("GlobalID", base.GlobalID); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property) { case "modstattype": case "stattype": case "modstat": case "stat": StatType = reader.GetString().ToEnum(StatType.Damage); break; case "moddamagetype": case "damagetype": DamageType = reader.GetString().ToDamageTypes(); break; } } } public sealed class ShotModPerTarget : TriggerMod, IWeaponProperty, IWeaponProperty, IWeaponProperty, IWeaponProperty { private readonly Dictionary _triggerStacks = new Dictionary(); private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; public StatType StatType { get; private set; } public DamageType[] DamageType { get; private set; } = DamageTypeConst.Any; public bool StoreOnGroup { get; private set; } = true; public bool CalcWhenHit { get; private set; } public override bool IsPerTarget => true; public ShotModPerTarget() { if (base.Trigger == null) { TriggerCoordinator triggerCoordinator2 = (base.Trigger = new TriggerCoordinator(ITrigger.GetTrigger(TriggerName.Hit))); } SetValidTriggers(ITrigger.HitTriggers); } public override bool ShouldRegister(Type contextType) { if (contextType == typeof(WeaponShotGroupInitContext)) { if (!CalcWhenHit) { return StoreOnGroup; } return false; } if (contextType == typeof(WeaponShotInitContext)) { if (!CalcWhenHit) { return !StoreOnGroup; } return false; } if (contextType == typeof(WeaponStatContext)) { return CalcWhenHit; } return base.ShouldRegister(contextType); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? damageable = null) { if (damageable == null) { stacks = 0f; return false; } if (!_triggerStacks.TryGetValue(damageable, out TriggerStack value)) { stacks = 0f; return false; } return value.TryGetStacks(out stacks); } public override void TriggerReset() { _triggerStacks.Clear(); } public override void TriggerApply(List contexts) { if (contexts.Count > 5) { Dictionary dictionary = new Dictionary(); foreach (TriggerContext context in contexts) { WeaponHitDamageableContextBase weaponHitDamageableContextBase = (WeaponHitDamageableContextBase)context.context; IDamageable damageable = weaponHitDamageableContextBase.Damageable; if (damageable != null) { TempWrapper.Set(damageable); if (!dictionary.TryGetValue(TempWrapper, out var value)) { dictionary.Add(new BaseDamageableWrapper(TempWrapper), (context.triggerAmt, weaponHitDamageableContextBase.ShotInfo.Orig)); } else { dictionary[TempWrapper] = (Combine(value.Item1, context.triggerAmt), value.Item2); } } } { foreach (KeyValuePair item in dictionary) { item.Deconstruct(out var key, out var value2); (float, ShotInfo) tuple = value2; BaseDamageableWrapper wrapper = key; var (triggerAmt, shotInfo) = tuple; AddTriggerInstance(wrapper, triggerAmt, shotInfo); } return; } } foreach (TriggerContext context2 in contexts) { WeaponHitDamageableContextBase weaponHitDamageableContextBase2 = (WeaponHitDamageableContextBase)context2.context; IDamageable damageable2 = weaponHitDamageableContextBase2.Damageable; if (damageable2 != null) { AddTriggerInstance(new BaseDamageableWrapper(damageable2), context2.triggerAmt, weaponHitDamageableContextBase2.ShotInfo.Orig); } } } private void AddTriggerInstance(BaseDamageableWrapper wrapper, float triggerAmt, ShotInfo shotInfo) { if (!_triggerStacks.ContainsKey(wrapper)) { _triggerStacks.Keys.Where((BaseDamageableWrapper wrapper) => !wrapper.Alive).ToList().ForEach(delegate(BaseDamageableWrapper wrapper) { _triggerStacks.Remove(wrapper); }); _triggerStacks[wrapper] = new TriggerStack(this); } if (!CalcWhenHit) { float mod = CalculateMod(triggerAmt); if (StoreOnGroup) { shotInfo.GroupMod.Add(this, StatType, mod, wrapper.Object, DamageType); } else { shotInfo.Mod.Add(this, StatType, mod, wrapper.Object, DamageType); } } _triggerStacks[wrapper].Add(triggerAmt); } public void Invoke(WeaponShotGroupInitContext context) { foreach (var (baseDamageableWrapper2, triggerStack2) in _triggerStacks) { if (triggerStack2.TryGetMod(out var mod)) { context.GroupMod.Add(this, StatType, mod, baseDamageableWrapper2.Object, DamageType); } } } public void Invoke(WeaponShotInitContext context) { foreach (var (baseDamageableWrapper2, triggerStack2) in _triggerStacks) { if (triggerStack2.TryGetMod(out var mod)) { context.Mod.Add(this, StatType, mod, baseDamageableWrapper2.Object, DamageType); } } } public void Invoke(WeaponStatContext context) { if (context.DamageType.HasFlagIn(DamageType)) { TempWrapper.Set(context.Damageable); if (_triggerStacks.TryGetValue(TempWrapper, out TriggerStack value) && value.TryGetMod(out var mod)) { context.AddMod(StatType, mod, base.StackLayer); } } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteString("StatType", StatType.ToString()); writer.WriteString("DamageType", DamageType[0].ToString()); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteBoolean("StoreOnGroup", StoreOnGroup); writer.WriteBoolean("CalcWhenHit", CalcWhenHit); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 11: switch (property[0]) { case 'm': break; case 'c': if (property == "calcwhenhit") { CalcWhenHit = reader.GetBoolean(); } return; default: return; } if (!(property == "modstattype")) { return; } goto IL_00e4; case 8: if (!(property == "stattype")) { return; } goto IL_00e4; case 7: if (!(property == "modstat")) { return; } goto IL_00e4; case 4: if (!(property == "stat")) { return; } goto IL_00e4; case 13: if (!(property == "moddamagetype")) { return; } goto IL_00f7; case 10: if (!(property == "damagetype")) { return; } goto IL_00f7; case 15: if (!(property == "storemodongroup")) { return; } break; case 12: if (!(property == "storeongroup")) { return; } break; case 5: case 6: case 9: case 14: return; IL_00f7: DamageType = reader.GetString().ToDamageTypes(); return; IL_00e4: StatType = reader.GetString().ToEnum(StatType.Damage); return; } StoreOnGroup = reader.GetBoolean(); } } public sealed class Shrapnel : Effect, IWeaponProperty, IWeaponProperty, ITriggerCallbackImpactSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IPropertyHolder { private const float WallHitBuffer = 0.03f; private CustomShotSettings _shotSettings; private int _friendlyMask; public ushort SyncID { get; set; } public int Count { get; private set; } public uint ArchetypeID { get; private set; } public float MaxRange { get; private set; } public float MaxAngle { get; private set; } = 180f; public float[] Offsets { get; private set; } = Array.Empty(); public float Damage { get; private set; } public Vector2 DamageFalloff { get; private set; } = new Vector2(100f, 100f); public float PrecisionDamageMulti { get; private set; } = 1f; public float StaggerDamageMulti { get; private set; } = 1f; public float FriendlyDamageMulti { get; private set; } = 1f; public int PierceLimit { get; private set; } = 1; public FireSetting FireFrom { get; private set; } = FireSetting.HitNormal; public ShrapnelFallback WallHandling { get; private set; } = ShrapnelFallback.Avoid; public float WallHandlingDist { get; private set; } = 1f; public bool IgnoreFalloff { get; private set; } public bool DamageLimb { get; private set; } = true; public bool IgnoreArmor { get; private set; } public bool IgnoreBackstab { get; private set; } public bool IgnoreShotMods { get; private set; } public bool UseParentShotMod { get; private set; } = true; public bool DamageFriendly { get; private set; } = true; public bool DamageOwner { get; private set; } = true; public bool DamageObjects { get; private set; } = true; public PropertyList Properties { get; private set; } = new PropertyList(); public bool TriggerScaleCount { get; private set; } = true; public bool HitTriggerTarget { get; private set; } public bool RunHitTriggers { get; private set; } = true; public bool ApplyAttackCooldown { get; private set; } = true; public TriggerPosMode ApplyPositionMode { get; private set; } public bool SearchEnabled { get; private set; } public int SearchCap { get; private set; } public int SearchCapPerTarget { get; private set; } = 1; public bool ScaleSearchCapPerTarget { get; private set; } = true; public bool SearchOverflow { get; private set; } = true; public float SearchRange { get; private set; } public float SearchAngle { get; private set; } public float SearchShotMaxAngle { get; private set; } public TargetingMode SearchTargetMode { get; private set; } = TargetingMode.ClosestLimb; public TargetingPriority SearchTargetPriority { get; private set; } = TargetingPriority.Distance; private bool FireFromGun { get { if (ApplyPositionMode == TriggerPosMode.User) { return FireFrom == FireSetting.HitPos; } return false; } } public PropertyNode? Node { get; set; } public Shrapnel() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) _shotSettings = new CustomShotSettings(null, null, null, DoHit); if (base.Trigger == null) { TriggerCoordinator triggerCoordinator2 = (base.Trigger = new TriggerCoordinator(ITrigger.GetTrigger(TriggerName.BulletLanded))); } SetValidTriggers(DamageType.Shrapnel); } public void Invoke(WeaponCreatedContext context) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (ArchetypeID != 0) { ArchetypeDataBlock block = GameDataBlockBase.GetBlock(ArchetypeID); if (block == null) { EWCLogger.Error($"Shrapnel: Unable to find Archetype block with ID {ArchetypeID}!"); } else { Damage = block.Damage; DamageFalloff = block.DamageFalloff; PrecisionDamageMulti = block.PrecisionDamageMulti; StaggerDamageMulti = block.StaggerDamageMulti; PierceLimit = block.PierceLimit(); } } } public override void TriggerApply(List contexts) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_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_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0153: 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) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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_00ec: Unknown result type (might be due to invalid IL or missing references) foreach (TriggerContext context in contexts) { if (TriggerScaleCount && context.triggerAmt * (float)Count < 1f) { continue; } ShotInfo shotInfo = null; IntPtr ignoreEnt = IntPtr.Zero; float falloff = 1f; Vector3 normal = Vector3.zero; Vector3 val; Vector3 dir; if (ApplyPositionMode != TriggerPosMode.User && context.context is IPositionContext positionContext) { shotInfo = positionContext.ShotInfo.Orig; val = positionContext.Position; dir = positionContext.Direction; falloff = positionContext.Falloff; if (positionContext is WeaponHitDamageableContextBase weaponHitDamageableContextBase) { if (!HitTriggerTarget) { ignoreEnt = ((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable.GetBaseDamagable()).Pointer; } Agent baseAgent = weaponHitDamageableContextBase.Damageable.GetBaseAgent(); if (ApplyPositionMode == TriggerPosMode.Relative && (Object)(object)baseAgent != (Object)null) { val = weaponHitDamageableContextBase.LocalPosition + baseAgent.Position; } } else { val += positionContext.Normal * 0.03f; normal = positionContext.Normal; } } else { val = base.CWC.Owner.FirePos; dir = base.CWC.Owner.FireDir; } dir = ComputeBaseDir(dir, normal); if (_shotSettings.projectile != null) { TriggerManager.SendInstance(this, val, dir, normal, context.triggerAmt); } DoShrapnel(val, dir, normal, context.triggerAmt, falloff, shotInfo, ignoreEnt); } } public void TriggerApplySync(Vector3 position, Vector3 direction, Vector3 normal, float triggerAmt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) DoShrapnelVisual(position, direction, normal, triggerAmt); } public override void TriggerReset() { } public void TriggerResetSync() { } private bool ForceRandomDir(Vector3 normal) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) bool flag = MaxAngle >= 180f; if (!flag) { bool flag2 = FireFrom != FireSetting.HitPos && normal == Vector3.zero; flag = flag2; } return flag; } private Vector3 ComputeBaseDir(Vector3 dir, Vector3 normal) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_002e: 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_004c: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) Vector3 result = dir; if (!ForceRandomDir(normal)) { switch (FireFrom) { case FireSetting.HitNormal: result = normal; break; case FireSetting.HitReflect: result = Vector3.Reflect(dir, normal); break; case FireSetting.HitPos: result = ((normal == Vector3.zero) ? dir : Vector3.Reflect(dir, normal)); break; } } return result; } private List GenerateRayDirs(Vector3 position, Vector3 dir, Vector3 normal, float triggerAmt) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) if (!TriggerScaleCount) { triggerAmt = 1f; } int num = (int)Math.Round((float)Count * triggerAmt); List list; if (SearchEnabled && base.CWC.Owner.IsType(OwnerType.Managed)) { list = GetBestEnemyDirs(position, dir, triggerAmt); for (int i = 0; i < list.Count; i++) { list[i] = CustomShotComponent.CalcRayDir(list[i], 0f, 0f, SearchShotMaxAngle); } if (!SearchOverflow) { return list; } list.EnsureCapacity(num); } else { list = new List(num); } for (int j = list.Count; j < num; j++) { Vector3 val; if (ForceRandomDir(normal)) { val = Random.onUnitSphere; } else { (float x, float y) offsetAt = GetOffsetAt(j); float item = offsetAt.x; float item2 = offsetAt.y; val = CustomShotComponent.CalcRayDir(dir, item, item2, MaxAngle); } if (normal != Vector3.zero && Vector3.Dot(val, normal) < 0f) { if (FireFrom == FireSetting.HitReflect || FireFrom == FireSetting.HitPos) { val = Vector3.Reflect(val, normal); } else if (FireFrom == FireSetting.HitNormal) { val = -val; } } list.Add(val); } return list; } private (float x, float y) GetOffsetAt(int i) { if (Offsets.Length == 0) { return (0f, 0f); } return (Offsets[i * 2 % Offsets.Length], Offsets[(i * 2 + 1) % Offsets.Length]); } private void DoShrapnelVisual(Vector3 position, Vector3 direction, Vector3 normal, float triggerAmt) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_005b: 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_0079: 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_007b: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) HitData hitData = new HitData(DamageType.Shrapnel) { owner = base.CWC.Owner.Player, pierceLimit = 1, damage = Damage }; if (!TriggerScaleCount) { hitData.damage *= triggerAmt; } Ray val = default(Ray); ((Ray)(ref val))..ctor(position, direction); Vector3 fxPos = (FireFromGun ? base.CWC.Owner.MuzzleAlign.position : ((Ray)(ref val)).origin); List list = GenerateRayDirs(position, direction, normal, triggerAmt); for (int i = 0; i < list.Count; i++) { ((Ray)(ref val)).direction = list[i]; CustomShotComponent shotComponent = base.CWC.ShotComponent; Ray fireRay = val; CustomShotSettings shotSettings = _shotSettings; shotComponent.FireCustom(fireRay, fxPos, hitData, -1, (IntPtr)0, shotSettings); } } private void DoShrapnel(Vector3 position, Vector3 dir, Vector3 normal, float triggerAmt, float falloff, ShotInfo? shotInfo = null, IntPtr ignoreEnt = default(IntPtr)) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: 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_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) float num = Damage; if (!TriggerScaleCount) { num *= triggerAmt; } Ray val = default(Ray); ((Ray)(ref val))..ctor(position, dir); Vector3 fxPos = (FireFromGun ? base.CWC.Owner.MuzzleAlign.position : ((Ray)(ref val)).origin); List list = GenerateRayDirs(position, dir, normal, triggerAmt); for (int i = 0; i < list.Count; i++) { HitData hitData = new HitData(DamageType.Shrapnel); hitData.owner = base.CWC.Owner.Player; hitData.shotInfo.Reset(num, PrecisionDamageMulti, StaggerDamageMulti, base.CWC, shotInfo, UseParentShotMod); hitData.falloff = (IgnoreFalloff ? 1f : falloff); hitData.pierceLimit = PierceLimit; hitData.damage = hitData.shotInfo.OrigDamage; hitData.damageFalloff = DamageFalloff; hitData.staggerMulti = hitData.shotInfo.OrigStagger; hitData.precisionMulti = PrecisionDamageMulti; hitData.maxRayDist = MaxRange; RaycastHit rayHit = (hitData.RayHit = default(RaycastHit)); ((Ray)(ref val)).direction = list[i]; switch (WallHandling) { case ShrapnelFallback.Avoid: if (CheckNearbyWall(val, out rayHit)) { ((Ray)(ref val)).direction = ((normal != Vector3.zero) ? Vector3.Reflect(-((Ray)(ref val)).direction, normal) : (-((Ray)(ref val)).direction)); } break; case ShrapnelFallback.Ricochet: { if (_shotSettings.projectile == null && CheckNearbyWall(val, out var rayHit2)) { hitData.maxRayDist = ((RaycastHit)(ref rayHit2)).distance; ToggleShotModifiers(enable: false); hitData.pierceLimit = base.CWC.ShotComponent.FireCustom(val, fxPos, hitData, _friendlyMask, ignoreEnt, _shotSettings); ToggleShotModifiers(enable: true); if (hitData.pierceLimit == 0) { continue; } ((Ray)(ref val)).origin = ((RaycastHit)(ref rayHit2)).point + ((RaycastHit)(ref rayHit2)).normal * 0.03f; ((Ray)(ref val)).direction = Vector3.Reflect(((Ray)(ref val)).direction, ((RaycastHit)(ref rayHit2)).normal); hitData.maxRayDist = MaxRange - ((RaycastHit)(ref rayHit2)).distance; } break; } } ToggleShotModifiers(enable: false); base.CWC.ShotComponent.FireCustom(val, fxPos, hitData, _friendlyMask, ignoreEnt, _shotSettings); ToggleShotModifiers(enable: true); } } private bool CheckNearbyWall(Ray ray, out RaycastHit rayHit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_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) if (Physics.Raycast(ray, ref rayHit, MaxRange, LayerUtil.MaskWorld)) { return Vector3.Dot(((Ray)(ref ray)).direction * ((RaycastHit)(ref rayHit)).distance, -((RaycastHit)(ref rayHit)).normal) <= WallHandlingDist; } return false; } private void ToggleShotModifiers(bool enable) { if (!enable) { _shotSettings.projectile?.SetOverrides(DoProjectileHit, _shotSettings.wallPierce, !FireFromGun); } else { _shotSettings.projectile?.DisableOverrides(); } if (!RunHitTriggers) { base.CWC.RunHitTriggers = enable; } } private bool DoHit(IWeaponComp _, HitData hitData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //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_006d: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) hitData.ResetDamage(); RaycastHit rayHit = hitData.RayHit; GameObject gameObject = ((Component)((RaycastHit)(ref rayHit)).collider).gameObject; ColliderMaterial component = gameObject.GetComponent(); bool flag = (LayerUtil.MaskDecalValid & gameObject.gameObject.layer) == 0; FX_GroupName val = (FX_GroupName)1; if ((Object)(object)component != (Object)null) { val = (FX_GroupName)component.MaterialId; } else { IDamageable? damageable = hitData.damageable; if (damageable != null) { Agent baseAgent = damageable.GetBaseAgent(); if (((baseAgent != null) ? new AgentType?(baseAgent.Type) : null) == (AgentType?)0) { val = (FX_GroupName)12; } } } FX_GroupName val2 = val; rayHit = hitData.RayHit; Vector3 point = ((RaycastHit)(ref rayHit)).point; rayHit = hitData.RayHit; FX_Manager.PlayEffect(false, val2, (Transform)null, point, Quaternion.LookRotation(((RaycastHit)(ref rayHit)).normal), flag); return ShrapnelHitManager.DoHit(this, hitData, base.CWC.GetContextController()); } private bool DoProjectileHit(HitData hitData, ContextController cc) { return ShrapnelHitManager.DoHit(this, hitData, cc, calcFalloff: false); } private List GetBestEnemyDirs(Vector3 position, Vector3 dir, float triggerScale) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) int num = (int)Math.Round((float)Count * triggerScale); List list = new List(num); int num2 = (int)Math.Round((float)SearchCap * triggerScale); if (SearchCap > 0 && num2 < num) { num = num2; } if (num == 0) { return list; } int num3 = (ScaleSearchCapPerTarget ? ((int)Math.Round((float)SearchCapPerTarget * triggerScale)) : SearchCapPerTarget); if (SearchCapPerTarget > 0 && num3 == 0) { return list; } float range = ((_shotSettings.projectile == null) ? Math.Max(MaxRange, SearchRange) : ((SearchRange > 0f) ? Math.Min(MaxRange, SearchRange) : MaxRange)); float angle = ((SearchAngle > 0f) ? Math.Min(MaxAngle, SearchAngle) : MaxAngle); List<(EnemyAgent, RaycastHit)> list2; if (SearchTargetMode == TargetingMode.ClosestLimb) { SearchSetting settings = SearchSetting.ClosestHit | SearchSetting.CheckLOS; SearchUtil.SightBlockLayer = LayerUtil.MaskWorld; list2 = SearchUtil.GetEnemyHitsInRange(new Ray(position, dir), range, angle, CourseNodeUtil.GetCourseNode(position, base.CWC.Owner.DimensionIndex), settings); } else { list2 = SearchUtil.GetEnemiesInRange(new Ray(position, dir), range, angle, CourseNodeUtil.GetCourseNode(position, base.CWC.Owner.DimensionIndex)).ConvertAll((Converter)((EnemyAgent enemy) => (enemy, default(RaycastHit)))); } switch (SearchTargetPriority) { case TargetingPriority.Distance: { List<((EnemyAgent enemy, RaycastHit hit), float)> list5 = list2.ConvertAll(delegate((EnemyAgent enemy, RaycastHit hit) pair) { //IL_0003: 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_000e: 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) Vector3 val4 = GetTargetPos(pair) - position; return (pair, ((Vector3)(ref val4)).sqrMagnitude); }); list5.Sort(SortUtil.FloatTuple); SortUtil.CopySortedList<(EnemyAgent, RaycastHit)>(list5, list2); break; } case TargetingPriority.Health: { List<((EnemyAgent enemy, RaycastHit hit), float, float)> list4 = list2.ConvertAll(((EnemyAgent enemy, RaycastHit hit) pair) => (pair, ((Dam_SyncedDamageBase)pair.enemy.Damage).HealthMax, 180f - Vector3.Angle(dir, GetTargetPos(pair) - position))); list4.Sort(SortUtil.FloatTuple); list4.Reverse(); SortUtil.CopySortedList<(EnemyAgent, RaycastHit)>(list4, list2); break; } default: { List<((EnemyAgent enemy, RaycastHit hit), float)> list3 = list2.ConvertAll(((EnemyAgent enemy, RaycastHit hit) pair) => (pair, Vector3.Angle(dir, GetTargetPos(pair) - position))); list3.Sort(SortUtil.FloatTuple); SortUtil.CopySortedList<(EnemyAgent, RaycastHit)>(list3, list2); break; } } for (int i = 0; i < list2.Count; i++) { if (list.Count >= num) { break; } (EnemyAgent, RaycastHit) pair2 = list2[i]; Vector3 val; if (SearchTargetMode == TargetingMode.Weakspot) { if (TryGetClosestWeakspotPos(pair2, out var pos2)) { val = pos2 - position; list.Add(((Vector3)(ref val)).normalized); } continue; } Vector3 val2 = GetTargetPos(pair2); if (SearchTargetMode == TargetingMode.ClosestLimb || !Physics.Linecast(position, val2, LayerUtil.MaskWorld)) { val = val2 - position; list.Add(((Vector3)(ref val)).normalized); } } if (num3 * list.Count < num) { num = num3 * list.Count; } if (list.Count == num) { return list; } list.EnsureCapacity(num); int count = list.Count; int num4 = 0; while (list.Count < num) { list.Add(list[num4 % count]); num4++; } return list; Vector3 GetTargetPos((EnemyAgent enemy, RaycastHit hit) pair) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0035: 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_0048: Unknown result type (might be due to invalid IL or missing references) return (Vector3)(SearchTargetMode switch { TargetingMode.Body => ((Agent)pair.enemy).AimTargetBody.position, TargetingMode.ClosestLimb => ((RaycastHit)(ref pair.hit)).point, _ => ((Agent)pair.enemy).AimTarget.position, }); } bool TryGetClosestWeakspotPos((EnemyAgent enemy, RaycastHit hit) pair, out Vector3 pos) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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) float num5 = float.MaxValue; pos = default(Vector3); foreach (Dam_EnemyDamageLimb item in (Il2CppArrayBase)(object)pair.enemy.Damage.DamageLimbs) { if (((Component)(object)item).TryGetComp(out var result) && result.enabled && (int)item.m_type == 1) { Vector3 val3 = item.DamageTargetPos - position; float magnitude = ((Vector3)(ref val3)).magnitude; if (num5 > magnitude && !Physics.Linecast(position, item.DamageTargetPos, LayerUtil.MaskWorld)) { num5 = magnitude; pos = item.DamageTargetPos; } } } return num5 < float.MaxValue; } } public override void OnPropertiesSetup() { Properties.Values.RemoveAll((WeaponPropertyBase prop) => !CheckAndSetTrait(prop)); base.OnPropertiesSetup(); } public override WeaponPropertyBase Clone() { Shrapnel obj = (Shrapnel)base.Clone(); obj.Properties = Properties.Clone(); obj._friendlyMask = _friendlyMask; return obj; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Count", Count); writer.WriteNumber("MaxRange", MaxRange); writer.WriteNumber("MaxAngle", MaxAngle); EWCJson.Serialize(writer, "Offsets", Offsets); writer.WriteNumber("ArchetypeID", ArchetypeID); writer.WriteNumber("Damage", Damage); SerializeFalloff(writer); writer.WriteNumber("PrecisionDamageMulti", PrecisionDamageMulti); writer.WriteNumber("StaggerDamageMulti", StaggerDamageMulti); writer.WriteNumber("FriendlyDamageMulti", FriendlyDamageMulti); writer.WriteNumber("PierceLimit", PierceLimit); writer.WriteString("WallHandling", WallHandling.ToString()); writer.WriteNumber("WallHandlingDist", WallHandlingDist); writer.WriteBoolean("IgnoreFalloff", IgnoreFalloff); writer.WriteBoolean("DamageLimb", DamageLimb); writer.WriteBoolean("IgnoreArmor", IgnoreArmor); writer.WriteBoolean("IgnoreBackstab", IgnoreBackstab); writer.WriteBoolean("IgnoreShotMods", IgnoreShotMods); writer.WriteBoolean("UseParentShotMod", UseParentShotMod); writer.WriteBoolean("DamageFriendly", DamageFriendly); writer.WriteBoolean("DamageOwner", DamageOwner); writer.WriteBoolean("DamageObjects", DamageObjects); EWCJson.Serialize(writer, "Traits", Properties); writer.WriteBoolean("TriggerScaleCount", TriggerScaleCount); writer.WriteBoolean("HitTriggerTarget", HitTriggerTarget); writer.WriteBoolean("RunHitTriggers", RunHitTriggers); writer.WriteBoolean("ApplyAttackCooldown", ApplyAttackCooldown); writer.WriteString("ApplyPositionMode", ApplyPositionMode.ToString()); writer.WriteBoolean("SearchEnabled", SearchEnabled); writer.WriteNumber("SearchCap", SearchCap); writer.WriteNumber("SearchCapPerTarget", SearchCapPerTarget); writer.WriteBoolean("ScaleSearchCapPerTarget", ScaleSearchCapPerTarget); writer.WriteBoolean("SearchOverflow", SearchOverflow); writer.WriteNumber("SearchRange", SearchRange); writer.WriteNumber("SearchAngle", SearchAngle); writer.WriteNumber("SearchShotMaxAngle", SearchShotMaxAngle); writer.WriteString("SearchTargetMode", SearchTargetMode.ToString()); writer.WriteString("SearchTargetPriority", SearchTargetPriority.ToString()); SerializeTrigger(writer); writer.WriteEndObject(); } private void SerializeFalloff(Utf8JsonWriter writer) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) writer.WritePropertyName("DamageFalloff"); writer.WriteStartObject(); writer.WriteNumber("x", DamageFalloff.x); writer.WriteNumber("y", DamageFalloff.y); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { //IL_0880: Unknown result type (might be due to invalid IL or missing references) base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 5: { char c = property[0]; if (c != 'a') { switch (c) { default: return; case 'c': if (property == "count") { Count = Math.Max(0, reader.GetInt32()); } return; case 'r': break; } if (!(property == "range")) { break; } goto IL_083d; } if (!(property == "angle")) { break; } goto IL_084a; } case 8: { char c = property[3]; if ((uint)c <= 101u) { switch (c) { default: return; case 'a': break; case 'e': if (property == "firefrom") { FireFrom = reader.GetString().ToEnum(FireSetting.HitNormal); if (FireFrom == FireSetting.User) { FireFrom = FireSetting.HitPos; } } return; } if (!(property == "maxangle")) { break; } goto IL_084a; } if (c != 'l') { if (c != 'r' || !(property == "maxrange")) { break; } goto IL_083d; } if (!(property == "walldist")) { break; } goto IL_08f7; } case 6: switch (property[0]) { case 's': break; case 'a': goto IL_03ec; case 'd': if (property == "damage") { Damage = reader.GetSingle(); } return; case 'p': goto IL_040e; case 't': if (property == "traits") { Properties = EWCJson.Deserialize(ref reader); } return; default: return; } if (property == "spread") { goto IL_084a; } if (!(property == "search")) { break; } goto IL_09f9; case 7: switch (property[0]) { default: return; case 'o': if (property == "offsets") { Offsets = JsonUtil.ReadPairs(ref reader); } return; case 's': break; } if (!(property == "stagger")) { break; } goto IL_0898; case 11: switch (property[7]) { case 'p': break; case 'm': goto IL_0463; case 'i': goto IL_0474; case 'r': if (property == "ignorearmor") { IgnoreArmor = reader.GetBoolean(); } return; case 'w': goto IL_0496; case 'o': goto IL_04a7; case 'g': goto IL_04b8; case 'u': if (property == "applyonuser") { ApplyPositionMode = TriggerPosMode.User; } return; case 'a': if (property == "searchrange") { SearchRange = reader.GetSingle(); } return; case 'n': if (property == "searchangle") { SearchAngle = reader.GetSingle(); } return; default: return; } if (!(property == "archetypeid")) { break; } goto IL_0864; case 9: { char c = property[0]; if (c != 'a') { switch (c) { default: return; case 'p': break; case 's': if (property == "searchcap") { SearchCap = reader.GetInt32(); } return; } if (!(property == "precision")) { break; } goto IL_088b; } if (!(property == "archetype")) { break; } goto IL_0864; } case 13: { char c = property[2]; if ((uint)c <= 105u) { if (c != 'a') { if (c != 'e') { if (c != 'i' || !(property == "friendlymulti")) { break; } goto IL_08a5; } if (!(property == "precisionmult")) { break; } goto IL_088b; } if (!(property == "searchenabled")) { break; } goto IL_09f9; } if (c != 'm') { if (c != 'n') { if (c != 'r' || !(property == "parentshotmod")) { break; } goto IL_0945; } if (!(property == "ignorefalloff")) { if (!(property == "ignoreshotmod")) { break; } goto IL_0938; } IgnoreFalloff = reader.GetBoolean(); break; } if (!(property == "damagefalloff")) { if (!(property == "damageobjects")) { break; } goto IL_0990; } DamageFalloff = EWCJson.Deserialize(ref reader); break; } case 20: { char c = property[0]; if (c != 'a') { if (c != 'p') { if (c != 's' || !(property == "searchtargetpriority")) { break; } goto IL_0a79; } if (!(property == "precisiondamagemulti")) { break; } goto IL_088b; } if (!(property == "applyattackcooldowns")) { break; } goto IL_09d1; } case 14: { char c = property[6]; if ((uint)c <= 105u) { if (c != 'b') { if (c != 'f') { if (c != 'i' || !(property == "precisionmulti")) { break; } goto IL_088b; } if (!(property == "damagefriendly")) { break; } goto IL_0952; } if (!(property == "ignorebackstab")) { break; } goto IL_092b; } if (c != 'o') { if (c != 's') { if (c != 't' || !(property == "runhittriggers")) { break; } goto IL_09c4; } if (!(property == "ignoreshotmods")) { break; } goto IL_0938; } if (property == "searchoverflow") { SearchOverflow = reader.GetBoolean(); } break; } case 18: { char c = property[6]; if (c != 'c') { if (c != 'r') { if (c != 's' || !(property == "searchshotmaxangle")) { break; } goto IL_0a54; } if (!(property == "staggerdamagemulti")) { break; } goto IL_0898; } if (property == "searchcappertarget") { SearchCapPerTarget = reader.GetInt32(); } break; } case 12: { char c = property[8]; if ((uint)c <= 108u) { switch (c) { default: return; case 'l': if (property == "wallhandling") { WallHandling = reader.GetString().ToEnum(ShrapnelFallback.None); } return; case 'f': break; } if (!(property == "friendlyfire")) { break; } goto IL_0952; } if (c != 'm') { if (c != 'u' || !(property == "staggermulti")) { break; } goto IL_0898; } if (!(property == "friendlymult")) { break; } goto IL_08a5; } case 19: { char c = property[0]; if (c != 'a') { if (c != 'f') { if (c != 's' || !(property == "searchtargetingmode")) { break; } goto IL_0a61; } if (!(property == "friendlydamagemulti")) { break; } goto IL_08a5; } if (!(property == "applyattackcooldown")) { break; } goto IL_09d1; } case 16: switch (property[6]) { case 'n': break; case 'b': goto IL_072b; case 'd': goto IL_073c; case 'e': goto IL_074d; case 'g': if (property == "hittriggertarget") { HitTriggerTarget = reader.GetBoolean(); } return; case 's': goto IL_076f; case 't': goto IL_0780; default: return; } if (!(property == "wallhandlingdist")) { break; } goto IL_08f7; case 10: switch (property[6]) { default: return; case 'l': if (property == "damagelimb") { DamageLimb = reader.GetBoolean(); } return; case 'u': break; } if (!(property == "damageuser")) { break; } goto IL_0971; case 15: { char c = property[6]; if (c != 'b') { if (c != 'd') { if (c != 's' || !(property == "searchshotangle")) { break; } goto IL_0a54; } if (!(property == "ignoredamagemod")) { break; } goto IL_0938; } if (!(property == "ignorebackbonus")) { break; } goto IL_092b; } case 17: switch (property[0]) { case 't': if (property == "triggerscalecount") { TriggerScaleCount = reader.GetBoolean(); } break; case 'a': if (property == "applypositionmode") { ApplyPositionMode = reader.GetString().ToEnum(TriggerPosMode.Relative); } break; } break; case 23: switch (property[1]) { default: return; case 'c': if (property == "scalesearchcappertarget") { ScaleSearchCapPerTarget = reader.GetBoolean(); } return; case 'e': break; } if (!(property == "searchtargetingpriority")) { break; } goto IL_0a79; case 4: if (!(property == "arch")) { break; } goto IL_0864; case 24: if (!(property == "piercingdamagecountlimit")) { break; } goto IL_08b2; case 21: case 22: break; IL_040e: if (!(property == "pierce")) { break; } goto IL_08b2; IL_08f7: WallHandlingDist = reader.GetSingle(); break; IL_0864: ArchetypeID = EWCJson.Deserialize(ref reader); break; IL_083d: MaxRange = reader.GetSingle(); break; IL_0780: if (!(property == "searchtargetmode")) { break; } goto IL_0a61; IL_076f: if (!(property == "searchshotspread")) { break; } goto IL_0a54; IL_074d: if (!(property == "useparentshotmod")) { break; } goto IL_0945; IL_073c: if (!(property == "ignoredamagemods")) { break; } goto IL_0938; IL_072b: if (!(property == "ignorebackdamage")) { break; } goto IL_092b; IL_088b: PrecisionDamageMulti = reader.GetSingle(); break; IL_09c4: RunHitTriggers = reader.GetBoolean(); break; IL_04b8: if (!(property == "hittriggers")) { break; } goto IL_09c4; IL_0a61: SearchTargetMode = reader.GetString().ToEnum(SearchTargetMode); break; IL_0a79: SearchTargetPriority = reader.GetString().ToEnum(SearchTargetPriority); break; IL_09f9: SearchEnabled = reader.GetBoolean(); break; IL_09d1: ApplyAttackCooldown = reader.GetBoolean(); break; IL_04a7: if (!(property == "damagelocks")) { break; } goto IL_0990; IL_0474: if (!(property == "piercelimit")) { break; } goto IL_08b2; IL_0496: if (!(property == "damageowner")) { break; } goto IL_0971; IL_084a: MaxAngle = reader.GetSingle(); break; IL_0463: if (!(property == "staggermult")) { break; } goto IL_0898; IL_0990: DamageObjects = reader.GetBoolean(); break; IL_0a54: SearchShotMaxAngle = reader.GetSingle(); break; IL_0971: DamageOwner = reader.GetBoolean(); _friendlyMask |= LayerUtil.MaskLocal; break; IL_08a5: FriendlyDamageMulti = reader.GetSingle(); break; IL_0898: StaggerDamageMulti = reader.GetSingle(); break; IL_0945: UseParentShotMod = reader.GetBoolean(); break; IL_08b2: PierceLimit = reader.GetInt32(); break; IL_03ec: if (!(property == "archid")) { break; } goto IL_0864; IL_0938: IgnoreShotMods = reader.GetBoolean(); break; IL_0952: DamageFriendly = reader.GetBoolean(); _friendlyMask |= LayerUtil.MaskFriendly; break; IL_092b: IgnoreBackstab = reader.GetBoolean(); break; } } private bool CheckAndSetTrait(WeaponPropertyBase property) { if (property is ThickBullet thickBullet) { _shotSettings.thickBullet = thickBullet; } else if (property is WallPierce wallPierce) { _shotSettings.wallPierce = wallPierce; } else { if (!(property is Projectile projectile)) { EWCLogger.Warning($"Shrapnel has trait of type {property.GetType().Name}, expected any of [{typeof(ThickBullet).Name}, {typeof(WallPierce).Name}, {typeof(Projectile)}]"); return false; } _shotSettings.projectile = projectile; } return true; } } public enum ShrapnelFallback { None, Avoid, Ricochet } public sealed class SpeedMod : TriggerModTimed, ITriggerCallbackBasicSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty { private const string APIGroup = "EWC"; private IStatModifier _speedModifier; public ushort SyncID { get; set; } public bool ApplyToTarget { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; private static ObjectWrapper TempWrapper => ObjectWrapper.SharedInstance; public override bool ValidProperty() { if (!ApplyToTarget && !base.CWC.Owner.IsType(OwnerType.Local)) { return false; } return base.ValidProperty(); } protected override void OnUpdate(float mod) { _speedModifier.Enable(mod); } protected override void OnDisable() { _speedModifier.Disable(); } public override void TriggerApply(List contexts) { if (!ApplyToTarget) { base.TriggerApply(contexts); return; } if (contexts.Count == 1) { TriggerContext tContext = contexts[0]; if (TryGetPlayer(tContext, out PlayerAgent player)) { SpeedManager.ApplySpeedMod(player.Owner, this, tContext.triggerAmt); } else { TriggerApplySync(tContext.triggerAmt); } return; } float num = 0f; Dictionary, float> dictionary = new Dictionary, float>(); foreach (TriggerContext context in contexts) { float value; if (!TryGetPlayer(context, out PlayerAgent player2)) { num = Combine(num, context.triggerAmt); } else if (dictionary.TryGetValue(TempWrapper.Set(player2.Owner), out value)) { dictionary[TempWrapper] = Combine(value, context.triggerAmt); } else { dictionary[new ObjectWrapper(TempWrapper)] = context.triggerAmt; } } if (num > 0f) { TriggerApplySync(num); } foreach (var (objectWrapper2, num3) in dictionary) { SpeedManager.ApplySpeedMod(triggerAmt: num3, player: objectWrapper2.Object, speedMod: this); } } private bool TryGetPlayer(TriggerContext tContext, [MaybeNullWhen(false)] out PlayerAgent player) { if (tContext.context is WeaponHitDamageableContextBase weaponHitDamageableContextBase && weaponHitDamageableContextBase.DamageType.HasFlag(DamageType.Player)) { player = ((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable.GetBaseAgent()).Cast(); return Object.op_Implicit((Object)(object)player); } player = null; return false; } public override WeaponPropertyBase Clone() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) SpeedMod obj = (SpeedMod)base.Clone(); obj._speedModifier = MoveSpeedAPI.AddModifier(1f, LayerToAPILayer(), "EWC"); obj._speedModifier.Disable(); return obj; } private StackLayer LayerToAPILayer() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) return (StackLayer)(base.StackLayer switch { StackType.Override => 4, StackType.Max => 2, StackType.Min => 3, StackType.Multiply => 0, StackType.Add => 1, _ => 0, }); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("InnerStackType", base.InnerStackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteBoolean("ApplyToTarget", ApplyToTarget); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "applytotarget") { ApplyToTarget = reader.GetBoolean(); } } bool ITriggerCallback.get_UseZeroAmountTrigger() { return UseZeroAmountTrigger; } } public sealed class SpreadMod : TriggerModTimed { public bool UpdateCrosshair { get; private set; } = true; protected override void OnUpdate(float mod) { base.CWC.SpreadController.SetMod(this, mod, UpdateCrosshair); } protected override void OnDisable() { base.CWC.SpreadController.ClearMod(this, UpdateCrosshair); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteString("StackLayer", base.StackLayer.ToString()); writer.WriteBoolean("UpdateCrosshair", UpdateCrosshair); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == "updatecrosshair") { UpdateCrosshair = reader.GetBoolean(); } } } public sealed class StaminaMod : Effect { public float StaminaChange { get; private set; } public float Cap { get; private set; } = -1f; public bool CancelRegen { get; private set; } public bool ApplyToTarget { get; private set; } protected override OwnerType RequiredOwnerType => OwnerType.Managed; public override bool ValidProperty() { if (!ApplyToTarget && !base.CWC.Owner.IsType(OwnerType.Local)) { return false; } return base.ValidProperty(); } public override void TriggerReset() { } public override void TriggerApply(List contexts) { float cap = ((Cap >= 0f) ? Cap : ((float)((StaminaChange > 0f) ? 1 : 0))); if (ApplyToTarget) { foreach (TriggerContext context in contexts) { PlayerAgent val = (PlayerAgent)((!(context.context is WeaponHitDamageableContextBase weaponHitDamageableContextBase) || !weaponHitDamageableContextBase.DamageType.HasFlag(DamageType.Player)) ? ((object)base.CWC.Owner.Player) : ((object)((Il2CppObjectBase)weaponHitDamageableContextBase.Damageable.GetBaseAgent()).Cast())); if ((Object)(object)val != (Object)null) { StaminaManager.DoStaminaChange(val, StaminaChange * context.triggerAmt, cap, this); } } return; } if ((Object)(object)base.CWC.Owner.Player != (Object)null) { StaminaManager.DoStaminaChange(base.CWC.Owner.Player, StaminaChange * contexts.Sum((TriggerContext tContext) => tContext.triggerAmt), cap, this); } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("StaminaChange", StaminaChange); writer.WriteNumber("Cap", Cap); writer.WriteBoolean("CancelRegen", CancelRegen); writer.WriteBoolean("ApplyToTarget", ApplyToTarget); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { case 13: switch (property[0]) { default: return; case 's': break; case 'a': if (property == "applytotarget") { ApplyToTarget = reader.GetBoolean(); } return; } if (!(property == "staminachange")) { break; } goto IL_00d2; case 16: if (!(property == "staminachangerel")) { break; } goto IL_00d2; case 10: if (!(property == "staminarel")) { break; } goto IL_00d2; case 7: if (!(property == "stamina")) { break; } goto IL_00d2; case 6: if (!(property == "caprel")) { break; } goto IL_00df; case 3: if (!(property == "cap")) { break; } goto IL_00df; case 11: { if (property == "cancelregen") { CancelRegen = reader.GetBoolean(); } break; } IL_00d2: StaminaChange = reader.GetSingle(); break; IL_00df: Cap = reader.GetSingle(); break; } } } public sealed class TempProperties : Effect, ITriggerCallbackBasicSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty, IPropertyHolder { private List? _callbackProperties; private PropertyNode? _node; private readonly DelayedCallback _applyCallback; public ushort SyncID { get; set; } public PropertyList Properties { get; private set; } = new PropertyList(); public float Duration { get; private set; } public bool Override { get; private set; } public bool ResetTriggersOnEnd { get; private set; } public PropertyNode? Node { get { return _node; } set { _node = value; _node.Override = Override; } } public TempProperties() { _applyCallback = new DelayedCallback(() => Duration, ApplyProperties, RemoveProperties); } public override void TriggerApply(List contexts) { TriggerApplySync(); TriggerManager.SendInstance(this); foreach (ITriggerCallback item in _callbackProperties.OrEmptyIfNull()) { if (item.Trigger == null) { item.TriggerApply(contexts); } } } public void TriggerApplySync(float mod = 1f) { base.CWC.StartDelayedCallback(_applyCallback); } public override void TriggerReset() { TriggerResetSync(); TriggerManager.SendReset(this); foreach (ITriggerCallback item in _callbackProperties.OrEmptyIfNull()) { if (item.Trigger == null) { item.TriggerReset(); } } } public void TriggerResetSync() { _applyCallback.Stop(); } private void ApplyProperties() { base.CWC.ActivateNode(Node); } private void RemoveProperties() { base.CWC.DeactivateNode(Node); if (!ResetTriggersOnEnd || _callbackProperties == null) { return; } foreach (ITriggerCallback callbackProperty in _callbackProperties) { callbackProperty.RemoteReset(); } } public override WeaponPropertyBase Clone() { TempProperties obj = (TempProperties)base.Clone(); obj.Properties = Properties.Clone(); return obj; } public void AddTriggerCallback(ITriggerCallback callback) { if (_callbackProperties == null) { _callbackProperties = new List(); } _callbackProperties.Add(callback); } public override void OnPropertiesSetup() { foreach (WeaponPropertyBase property in Properties) { if (property is ITriggerCallback callback) { AddTriggerCallback(callback); } } base.OnPropertiesSetup(); } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); EWCJson.Serialize(writer, "Properties", Properties); writer.WriteNumber("Duration", Duration); writer.WriteBoolean("Override", Override); writer.WriteBoolean("ResetTriggersOnEnd", ResetTriggersOnEnd); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); switch (property) { case "properties": Properties = EWCJson.Deserialize(ref reader); break; case "duration": Duration = reader.GetSingle(); break; case "override": Override = reader.GetBoolean(); break; case "resettriggersonend": ResetTriggersOnEnd = reader.GetBoolean(); break; } } } } namespace EWC.CustomWeapon.Properties.Effects.TriggerModifier { public abstract class TriggerMod : Effect { protected struct TriggerInstance { public float triggerAmt; public float endTime; public TriggerInstance(float triggerAmt, float endTime) { this.triggerAmt = 1f; this.endTime = 0f; this.triggerAmt = triggerAmt; this.endTime = endTime; } } protected class TriggerStack { private float _currentStacks; private float _lastStackTime; private float _lastUpdateTime; private readonly Queue _expireTimes = new Queue(); private readonly TriggerMod _parent; public TriggerStack(TriggerMod parent) { _parent = parent; } public void Clear() { _expireTimes.Clear(); _currentStacks = 0f; } public void Add(List contexts) { Add(_parent.Count(contexts)); } public void Add(float num) { if (_parent.CombineModifiers) { RefreshStackMod(); _lastStackTime = Clock.Time; if (_parent.StackType == StackType.Override) { _currentStacks = num; } else { _currentStacks = ((_parent.CombineCap > 0f) ? Math.Min(_parent.CombineCap, _currentStacks + num) : (_currentStacks + num)); } } else { if (_parent.StackType == StackType.Override) { _expireTimes.Clear(); } float endTime = Clock.Time + _parent.Duration; _expireTimes.Enqueue(new TriggerInstance(num, endTime)); } } public bool TryGetStacks(out float stacks) { stacks = 0f; if (_parent.CombineModifiers) { if (_currentStacks == 0f) { return false; } RefreshStackMod(); stacks = _currentStacks; return stacks != 0f; } TriggerInstance result; while (_expireTimes.TryPeek(out result) && result.endTime < Clock.Time) { _expireTimes.Dequeue(); } if (_expireTimes.Count == 0) { return false; } stacks = _parent.Count(_expireTimes); return true; } public bool TryGetMod(out float mod) { if (!TryGetStacks(out var stacks)) { mod = 1f; return false; } mod = _parent.CalculateMod(stacks); return true; } private void RefreshStackMod() { float time = Clock.Time; float num = _lastStackTime + _parent.Duration; if (num > time) { return; } if (num > _lastUpdateTime) { _lastUpdateTime = num; } float num2 = time - _lastUpdateTime; if (num2 > 0f) { if (_parent.CombineDecayTime <= 0f) { _currentStacks = 0f; } else { _currentStacks = Math.Max(0f, _currentStacks - num2 / _parent.CombineDecayTime); } } _lastUpdateTime = time; } } public float Mod { get; private set; } = 1f; public float Cap { get; private set; } public float Duration { get; private set; } public bool CombineModifiers { get; private set; } public float CombineDecayTime { get; private set; } public float CombineCap { get; private set; } public StackType StackType { get; private set; } = StackType.Add; public StackType InnerStackType { get; private set; } public StackType StackLayer { get; private set; } = StackType.Multiply; public virtual bool UseZeroAmountTrigger => StackType == StackType.Override; public virtual bool IsPerTarget => false; private StackType CalculateStackType { get { StackType stackType = StackType; if ((uint)(stackType - 1) <= 1u) { return StackType; } return InnerStackType; } } public abstract bool TryGetStacks(out float stacks, BaseDamageableWrapper? damageable = null); private float ClampToCap(float mod) { if (Cap > 1f) { return Math.Min(mod, Cap); } return Math.Max(mod, Cap); } protected float CalculateMod(IEnumerable contexts, bool clamped = true) { float num = Count(contexts); if (num == 0f) { return 1f; } float num2 = CalculateMod(num); if (!clamped) { return num2; } return ClampToCap(num2); } protected float CalculateMod(float num, bool clamped = true) { return CalculateMod(CalculateStackType, num, clamped); } protected float CalculateMod(StackType type, float num, bool clamped = true) { float num2 = type switch { StackType.Override => Mod, StackType.Multiply => (float)Math.Pow(Mod, num), StackType.Add => 1f + (Mod - 1f) * num, _ => 1f, }; if (!clamped) { return num2; } return ClampToCap(num2); } protected float Combine(float triggerAmtA, float triggerAmtB) { switch (StackType) { case StackType.Override: return triggerAmtA; case StackType.Add: case StackType.Multiply: return triggerAmtA + triggerAmtB; case StackType.Max: return (triggerAmtA > triggerAmtB) ? triggerAmtA : triggerAmtB; case StackType.Min: return (triggerAmtA > triggerAmtB) ? triggerAmtB : triggerAmtA; default: return 0f; } } protected float Count(IEnumerable contexts) { if (!contexts.Any()) { return 0f; } switch (StackType) { case StackType.Override: return contexts.First().triggerAmt; case StackType.Add: case StackType.Multiply: return contexts.Sum((TriggerInstance context) => context.triggerAmt); case StackType.Max: return contexts.Max((TriggerInstance x) => x.triggerAmt); case StackType.Min: return contexts.Min((TriggerInstance x) => x.triggerAmt); default: return 0f; } } protected float Count(IEnumerable contexts) { if (!contexts.Any()) { return 0f; } switch (StackType) { case StackType.Override: return contexts.First().triggerAmt; case StackType.Add: case StackType.Multiply: return contexts.Sum((TriggerContext context) => context.triggerAmt); case StackType.Max: return contexts.Max((TriggerContext x) => x.triggerAmt); case StackType.Min: return contexts.Min((TriggerContext x) => x.triggerAmt); default: return 0f; } } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", Mod); writer.WriteNumber("Cap", Cap); writer.WriteNumber("Duration", Duration); writer.WriteBoolean("CombineModifiers", CombineModifiers); writer.WriteNumber("CombineDecayTime", CombineDecayTime); writer.WriteString("StackType", StackType.ToString()); writer.WriteString("InnerStackType", InnerStackType.ToString()); writer.WriteString("StackLayer", StackLayer.ToString()); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (property == null) { return; } switch (property.Length) { default: return; case 3: switch (property[0]) { case 'm': if (property == "mod") { Mod = reader.GetSingle(); } break; case 'c': if (property == "cap") { Cap = reader.GetSingle(); } break; } return; case 16: { char c = property[7]; if (c != 'd') { if (c != 'm' || !(property == "combinemodifiers")) { return; } goto IL_0234; } if (!(property == "combinedecaytime")) { return; } goto IL_0241; } case 9: { char c = property[0]; if (c != 'd') { if (c != 's' || !(property == "stacktype")) { return; } goto IL_025b; } if (!(property == "decaytime")) { return; } goto IL_0241; } case 5: { char c = property[0]; if (c != 'd') { if (c != 'l') { if (c != 's' || !(property == "stack")) { return; } goto IL_025b; } if (!(property == "layer")) { return; } break; } if (!(property == "decay")) { return; } goto IL_0241; } case 10: { char c = property[0]; if (c != 'c') { if (c != 'i') { if (c != 's' || !(property == "stacklayer")) { return; } break; } if (!(property == "innerstack")) { return; } goto IL_026e; } if (property == "combinecap") { CombineCap = reader.GetSingle(); } return; } case 8: if (property == "duration") { Duration = reader.GetSingle(); } return; case 7: if (!(property == "combine")) { return; } goto IL_0234; case 12: if (!(property == "combinedecay")) { return; } goto IL_0241; case 17: if (!(property == "overridestacktype")) { return; } goto IL_026e; case 13: if (!(property == "overridestack")) { return; } goto IL_026e; case 14: if (!(property == "innerstacktype")) { return; } goto IL_026e; case 4: case 6: case 11: case 15: return; IL_0241: CombineDecayTime = reader.GetSingle(); return; IL_0234: CombineModifiers = reader.GetBoolean(); return; IL_026e: InnerStackType = reader.GetString().ToEnum(StackType.Invalid); return; IL_025b: StackType = reader.GetString().ToEnum(StackType.Invalid); return; } StackLayer = reader.GetString().ToEnum(StackType.Invalid); } } public abstract class TriggerModDebuff : TriggerMod, ITriggerCallbackAgentSync, ITriggerCallbackSync, ITriggerCallback, IWeaponProperty, IWeaponProperty, IWeaponProperty { [CompilerGenerated] private sealed class d__32 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TriggerModDebuff <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__32(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; TriggerModDebuff triggerModDebuff = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (triggerModDebuff._activeDebuffs.Count > 0) { KeyValuePair[] array = triggerModDebuff._activeDebuffs.ToArray(); foreach (KeyValuePair keyValuePair in array) { keyValuePair.Deconstruct(out var key, out var value); (TriggerStack, DebuffModifierBase) tuple = value; BaseDamageableWrapper key2 = key; var (triggerStack, debuffModifierBase) = tuple; if (triggerStack.TryGetMod(out var mod)) { debuffModifierBase.Mod = mod; continue; } debuffModifierBase.Disable(); triggerModDebuff._activeDebuffs.Remove(key2); } <>2__current = null; <>1__state = 1; return true; } triggerModDebuff._activeDebuffs.Clear(); triggerModDebuff._updateRoutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly Dictionary _storedDebuffs = new Dictionary(); private readonly Dictionary _activeDebuffs = new Dictionary(); private static readonly Dictionary> s_globalStacks = new Dictionary>(); private Coroutine? _updateRoutine; public ushort SyncID { get; set; } public uint DebuffID { get; private set; } public uint GlobalID { get; private set; } private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; public override bool IsPerTarget => true; public TriggerModDebuff() { if (base.Trigger == null) { TriggerCoordinator triggerCoordinator2 = (base.Trigger = new TriggerCoordinator(ITrigger.GetTrigger(TriggerName.Hit))); } SetValidTriggers(ITrigger.HitTriggers); } [InvokeOnCleanup(false)] private static void ClearGlobal() { s_globalStacks.Clear(); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? damageable = null) { if (damageable == null) { stacks = 0f; return false; } if (!_activeDebuffs.TryGetValue(damageable, out (TriggerStack, DebuffModifierBase) value)) { stacks = 0f; return false; } return value.Item1.TryGetStacks(out stacks); } protected abstract DebuffModifierBase AddModifier(IDamageable damageable); public void Invoke(WeaponDestroyedContext context) { TriggerResetSync(); } public override void TriggerReset() { TriggerResetSync(); } public void TriggerResetSync() { foreach (var value in _storedDebuffs.Values) { var (triggerStack, _) = value; value.modifier.Disable(); triggerStack.Clear(); } CoroutineUtil.Stop(ref _updateRoutine); _activeDebuffs.Clear(); } public override void TriggerApply(List contexts) { if (contexts.Count > 1) { Dictionary dictionary = new Dictionary(); foreach (TriggerContext context in contexts) { IDamageable damageable = ((WeaponHitDamageableContextBase)context.context).Damageable; if (damageable != null) { TempWrapper.Set(damageable); if (!dictionary.TryGetValue(TempWrapper, out var value)) { dictionary.Add(new BaseDamageableWrapper(TempWrapper), context.triggerAmt); } else { dictionary[TempWrapper] = Combine(value, context.triggerAmt); } } } { foreach (var (baseDamageableWrapper2, num2) in dictionary) { AddTriggerInstance(baseDamageableWrapper2, num2); TriggerManager.SendInstance(this, baseDamageableWrapper2.Object.GetBaseAgent(), num2); } return; } } IDamageable damageable2 = ((WeaponHitDamageableContextBase)contexts[0].context).Damageable; if (damageable2 != null) { float triggerAmt = contexts[0].triggerAmt; AddTriggerInstance(new BaseDamageableWrapper(damageable2), triggerAmt); TriggerManager.SendInstance(this, damageable2.GetBaseAgent(), triggerAmt); } } public void TriggerApplySync(Agent target, float mod) { AddTriggerInstance(new BaseDamageableWrapper(((Component)target).GetComponent()), mod); } protected void AddTriggerInstance(BaseDamageableWrapper wrapper, float triggerAmt) { if (!_storedDebuffs.TryGetValue(wrapper, out (TriggerStack, DebuffModifierBase) value)) { _storedDebuffs.Keys.Where((BaseDamageableWrapper wrapper) => !wrapper.Alive).ToList().ForEach(delegate(BaseDamageableWrapper wrapper) { _storedDebuffs[wrapper].modifier.Disable(); _storedDebuffs.Remove(wrapper); _activeDebuffs.Remove(wrapper); }); _storedDebuffs.Add(wrapper, value = GetNewDebuff(wrapper)); } _activeDebuffs[wrapper] = value; value.Item1.Add(triggerAmt); if (value.Item1.TryGetMod(out var mod)) { value.Item2.Enable(mod); StartUpdate(); } } private (TriggerStack stack, DebuffModifierBase modifier) GetNewDebuff(BaseDamageableWrapper wrapper) { if (GlobalID == 0) { return (new TriggerStack((TriggerMod)Clone()), AddModifier(wrapper.Object)); } if (!s_globalStacks.TryGetValue(GlobalID, out Dictionary debuffDict)) { s_globalStacks.Add(GlobalID, debuffDict = new Dictionary()); } if (!debuffDict.TryGetValue(wrapper, out (TriggerStack, DebuffModifierBase) value)) { debuffDict.Keys.Where((BaseDamageableWrapper wrapper) => !wrapper.Alive).ToList().ForEach(delegate(BaseDamageableWrapper wrapper) { debuffDict.Remove(wrapper); }); Dictionary dictionary = debuffDict; value = (new TriggerStack((TriggerMod)Clone()), AddModifier(wrapper.Object)); dictionary.Add(wrapper, value); } return value; } private void StartUpdate() { if (_updateRoutine == null) { _updateRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DelayedUpdate()), (Action)null); } } [IteratorStateMachine(typeof(d__32))] private IEnumerator DelayedUpdate() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__32(0) { <>4__this = this }; } public override void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteString("Name", GetType().Name); writer.WriteNumber("Mod", base.Mod); writer.WriteNumber("Cap", base.Cap); writer.WriteNumber("Duration", base.Duration); writer.WriteBoolean("CombineModifiers", base.CombineModifiers); writer.WriteNumber("CombineDecayTime", base.CombineDecayTime); writer.WriteString("StackType", base.StackType.ToString()); writer.WriteNumber("DebuffID", DebuffID); writer.WriteNumber("GlobalID", GlobalID); SerializeTrigger(writer); writer.WriteEndObject(); } public override void DeserializeProperty(string property, ref Utf8JsonReader reader) { base.DeserializeProperty(property, ref reader); if (!(property == "debuffids")) { if (property == "globalid") { if (reader.TokenType == JsonTokenType.String) { GlobalID = DebuffManager.StringIDToInt(reader.GetString()); } else { GlobalID = reader.GetUInt32(); } } } else if (reader.TokenType == JsonTokenType.String) { DebuffID = DebuffManager.StringIDToInt(reader.GetString()); } else { DebuffID = reader.GetUInt32(); } } bool ITriggerCallback.get_UseZeroAmountTrigger() { return UseZeroAmountTrigger; } } public abstract class TriggerModTimed : TriggerMod, IWeaponProperty, IWeaponProperty, IWeaponProperty { [CompilerGenerated] private sealed class d__14 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TriggerModTimed <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown int num = <>1__state; TriggerModTimed triggerModTimed = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } if (triggerModTimed._triggerStack.TryGetMod(out var mod)) { triggerModTimed.OnUpdate(mod); float result; while (triggerModTimed._updateTimes.TryPeek(out result) && result <= Clock.Time) { triggerModTimed._updateTimes.Dequeue(); } if (triggerModTimed._updateTimes.Count > 0) { <>2__current = (object)new WaitForSeconds(result - Clock.Time); <>1__state = 1; return true; } <>2__current = null; <>1__state = 2; return true; } triggerModTimed.OnDisable(); triggerModTimed._updateTimes.Clear(); triggerModTimed._updateRoutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly TriggerStack _triggerStack; private Coroutine? _updateRoutine; private readonly Queue _updateTimes; public TriggerModTimed() { _updateTimes = new Queue(); _triggerStack = new TriggerStack(this); } public override bool TryGetStacks(out float stacks, BaseDamageableWrapper? _ = null) { return _triggerStack.TryGetStacks(out stacks); } protected abstract void OnUpdate(float mod); protected abstract void OnDisable(); public override void TriggerReset() { TriggerResetSync(); } public void TriggerResetSync() { _triggerStack.Clear(); _updateTimes.Clear(); CoroutineUtil.Stop(ref _updateRoutine); OnDisable(); } public override void TriggerApply(List contexts) { TriggerApplySync(Count(contexts)); } public void TriggerApplySync(float amount) { _triggerStack.Add(amount); if (_triggerStack.TryGetMod(out var mod)) { OnUpdate(mod); EnqueueUpdate(); } else if (CoroutineUtil.Stop(ref _updateRoutine)) { OnDisable(); } } public void Invoke(WeaponSetupContext context) { if (!_triggerStack.TryGetMod(out var mod)) { _updateTimes.Clear(); return; } OnUpdate(mod); if (_updateRoutine == null) { _updateRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DelayedUpdate()), (Action)null); } } public void Invoke(WeaponClearContext context) { CoroutineUtil.Stop(ref _updateRoutine); OnDisable(); } private void EnqueueUpdate() { if (base.CombineModifiers) { _updateTimes.TryDequeue(out var _); } _updateTimes.Enqueue(Clock.Time + base.Duration); if (_updateRoutine == null) { _updateRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DelayedUpdate()), (Action)null); } } [IteratorStateMachine(typeof(d__14))] private IEnumerator DelayedUpdate() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__14(0) { <>4__this = this }; } } } namespace EWC.CustomWeapon.Properties.Effects.Stamina { public static class StaminaManager { private static readonly StaminaSync _sync = new StaminaSync(); [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); } public static void DoStaminaChange(PlayerAgent player, float change, float cap, StaminaMod sBase) { if (change != 0f) { StaminaData staminaData = default(StaminaData); staminaData.cancelRegen = sBase.CancelRegen; StaminaData packetData = staminaData; packetData.mod.Set(change, 1f); packetData.cap.Set(cap, 1f); _sync.Send(packetData, player.Owner, (SNet_ChannelType)4); } } internal static void Internal_ReceiveStamina(float stamChange, float cap, bool cancelRegen) { if (!PlayerManager.HasLocalPlayerAgent()) { return; } PlayerStamina stamina = PlayerManager.GetLocalPlayerAgent().Stamina; if (stamChange > 0f) { if (DramaManager.InActionState) { cap = Math.Min(cap, stamina.PlayerData.StaminaMaximumCapWhenInCombat); } if (stamina.Stamina >= cap) { return; } stamina.Stamina = Math.Min(cap, stamina.Stamina + stamChange); } else { if (!DramaManager.InActionState) { cap = Math.Max(cap, stamina.PlayerData.StaminaMinimumCapWhenNotInCombat); } if (stamina.Stamina <= cap) { return; } stamina.Stamina = Math.Max(cap, stamina.Stamina + stamChange); } if (cancelRegen) { stamina.m_lastExertion = Clock.Time; } } } public struct StaminaData { public SFloat16b mod; public UFloat8b cap; public bool cancelRegen; } internal sealed class StaminaSync : SyncedEvent { public override string GUID => "STAMINA"; protected override void Receive(StaminaData packet) { StaminaManager.Internal_ReceiveStamina(packet.mod.Get(1f), packet.cap.Get(1f), packet.cancelRegen); } } } namespace EWC.CustomWeapon.Properties.Effects.Speed { public static class SpeedManager { private static readonly SpeedSync _sync = new SpeedSync(); private const float MaxMod = 256f; [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); } public static void ApplySpeedMod(SNet_Player player, SpeedMod speedMod, float triggerAmt) { if (triggerAmt != 0f && !player.IsBot) { SpeedData speedData = default(SpeedData); speedData.propertyID = speedMod.SyncID; SpeedData packetData = speedData; packetData.cwc.Set(speedMod.CWC); packetData.mod.Set(triggerAmt, 256f); _sync.Send(packetData, player, (SNet_ChannelType)4); } } internal static void Internal_ReceiveSpeed(SpeedData data) { if (TryGetSpeedMod(data, out SpeedMod speedMod)) { speedMod.TriggerApplySync(data.mod.Get(256f)); } } private static bool TryGetSpeedMod(SpeedData data, [MaybeNullWhen(false)] out SpeedMod speedMod) { if (!data.cwc.TryGet(out CustomWeaponComponent comp)) { speedMod = null; return false; } speedMod = comp.GetTriggerSync(data.propertyID) as SpeedMod; return speedMod != null; } } public struct SpeedData { public pCWC cwc; public ushort propertyID; public UFloat16b mod; } internal sealed class SpeedSync : SyncedEvent { public override string GUID => "SPEED"; protected override void Receive(SpeedData packet) { SpeedManager.Internal_ReceiveSpeed(packet); } } } namespace EWC.CustomWeapon.Properties.Effects.ShrapnelHit { public static class ShrapnelHitManager { private static readonly ShrapnelHitSync _sync = new ShrapnelHitSync(); private static readonly ShrapnelHitPlayerSync _playerSync = new ShrapnelHitPlayerSync(); [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); _playerSync.Setup(); } public static bool DoHit(Shrapnel shrapnel, HitData hitData, ContextController cc, bool calcFalloff = true) { //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_00f6: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Invalid comparison between Unknown and I4 //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Invalid comparison between Unknown and I4 if (hitData.damage <= 0f) { return true; } if (hitData.damageable == null || hitData.damageType.HasFlag(DamageType.Dead)) { cc.Invoke(new WeaponHitContext(hitData)); return true; } float damage = hitData.damage; float num = hitData.precisionMulti; float num2 = hitData.staggerMulti; float num3 = hitData.falloff; if (calcFalloff) { num3 *= hitData.CalcFalloff(); } IDamageable damageable = hitData.damageable; float num4 = 1f; float num5 = 1f; bool flag = hitData.damageType.HasFlag(DamageType.Enemy); Dam_EnemyDamageLimb val = null; RaycastHit rayHit; if (flag) { val = ((Il2CppObjectBase)damageable).Cast(); if (!shrapnel.IgnoreBackstab && shrapnel.CWC.Weapon.AllowBackstab) { float value = cc.Invoke(new WeaponBackstabContext()).Value; Dam_EnemyDamageLimb obj = val; Vector3 hitPos = hitData.hitPos; rayHit = hitData.RayHit; num5 = obj.ApplyDamageFromBehindBonus(1f, hitPos, ((RaycastHit)(ref rayHit)).point - shrapnel.CWC.Owner.FirePos, 1f); num4 = num5.Map(1f, 2f, 1f, value); } } float falloff = hitData.falloff; hitData.falloff = num3; WeaponPreHitDamageableContext weaponPreHitDamageableContext = new WeaponPreHitDamageableContext(hitData, num4, num5); hitData.falloff = falloff; cc.Invoke(weaponPreHitDamageableContext); WeaponStatContext weaponStatContext = new WeaponStatContext(hitData, shrapnel.CWC.DebuffIDs); cc.Invoke(weaponStatContext); if (!shrapnel.IgnoreShotMods) { damage = weaponStatContext.Damage; num = weaponStatContext.Precision; num2 = weaponStatContext.Stagger; } if (damage <= 0f) { return true; } hitData.shotInfo.AddHit(weaponPreHitDamageableContext.DamageType); damage = damage * num3 + 0.001f; damage *= hitData.shotInfo.ExternalDamageMod * hitData.shotInfo.InnateDamageMod; num2 *= hitData.shotInfo.InnateStaggerMod; PlayerAgent player = shrapnel.CWC.Owner.Player; Agent baseAgent = damageable.GetBaseAgent(); if (hitData.damageType.HasFlag(DamageType.Player)) { if ((Object)(object)baseAgent == (Object)(object)player) { if (!shrapnel.DamageOwner) { return false; } } else if (!shrapnel.DamageFriendly) { return false; } if (player != null && ((Agent)player).IsLocallyOwned) { GuiManager.CrosshairLayer.PopFriendlyTarget(); } Dam_PlayerDamageBase val2 = ((Il2CppObjectBase)damageable.GetBaseDamagable()).Cast(); damage *= val2.m_playerData.friendlyFireMulti * shrapnel.FriendlyDamageMulti; cc.Invoke(new WeaponHitDamageableContext(damage, weaponPreHitDamageableContext)); ShrapnelHitPlayerData shrapnelHitPlayerData = default(ShrapnelHitPlayerData); shrapnelHitPlayerData.damage = damage; ShrapnelHitPlayerData packetData = shrapnelHitPlayerData; ((pPlayerAgent)(ref packetData.target)).Set(val2.Owner); packetData.cwc.Set(shrapnel.CWC); packetData.dir.Value = hitData.fireDir; _playerSync.Send(packetData, null, (SNet_ChannelType)4); return true; } if (hitData.damageType.HasFlag(DamageType.Object)) { if (!shrapnel.DamageObjects) { return false; } cc.Invoke(new WeaponHitDamageableContext(damage, weaponPreHitDamageableContext)); float num6 = damage; Vector3 hitPos2 = hitData.hitPos; Vector3 fireDir = hitData.fireDir; rayHit = hitData.RayHit; damageable.BulletDamage(num6, (Agent)(object)player, hitPos2, fireDir, ((RaycastHit)(ref rayHit)).normal, false, 1f, 1f, 0u); return true; } if (!flag) { return false; } Dam_EnemyDamageBase @base = val.m_base; Vector3 vec = hitData.hitPos - @base.Owner.Position; ShrapnelHitData packet = default(ShrapnelHitData); ((pEnemyAgent)(ref packet.target)).Set(@base.Owner); packet.cwc.Set(shrapnel.CWC); packet.limbID = (byte)val.m_limbID; packet.damageLimb = shrapnel.DamageLimb; packet.localPosition.Set(vec, 10f); packet.dir.Value = hitData.fireDir; packet.staggerMult = num2; packet.setCooldowns = shrapnel.ApplyAttackCooldown; bool num7 = (int)val.m_type == 1; float armorMulti = (shrapnel.IgnoreArmor ? 1f : val.m_armorDamageMulti); DebuffManager.GetAndApplyArmorShredDebuff(ref armorMulti, damageable, shrapnel.CWC.DebuffIDs); float num8 = (num7 ? Math.Max(val.m_weakspotDamageMulti * num, 1f) : 1f); float num9 = damage * num8 * armorMulti * num4; if (!weaponStatContext.BypassTumorCap && (int)val.DestructionType == 1) { num9 = Math.Min(num9, val.m_healthMax + 1f); } packet.damage = num9; WeaponHitDamageableContext weaponHitDamageableContext = cc.Invoke(new WeaponHitDamageableContext(num9, weaponPreHitDamageableContext)); bool willKill = ((Dam_SyncedDamageBase)@base).WillDamageKill(num9); HitTrackerManager.RegisterHit(shrapnel.CWC.Owner, shrapnel.CWC, weaponHitDamageableContext); ShotManager.DoHitmarker(shrapnel.CWC, cc, val, num9 > damage, willKill, weaponHitDamageableContext.Position, armorMulti < 1f || @base.IsImortal); _sync.Send(packet, (SNet_ChannelType)4); return true; } internal static void Internal_ReceiveShrapnelDamagePlayer(PlayerAgent target, PlayerAgent? source, OwnerType ownerType, float damage, Vector3 direction) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ShotManager.ReceivePlayerDamage(target, damage, PlayerDamageType.Shrapnel, direction); if (((Agent)target).IsLocallyOwned) { target.Sound.Post(EVENTS.BULLETHITPLAYERSYNC, true); if (ownerType.HasFlag(OwnerType.Sentry) || (Object)(object)source == (Object)null || ((Il2CppObjectBase)source).Pointer != ((Il2CppObjectBase)target).Pointer) { PlayerDialogManager.WantToStartDialog(152u, target.CharacterID, false, false); GameEventManager.PostEvent((eGameEvent)14, target, damage, "", (Dictionary)null); } } } internal static void Internal_ReceiveShrapnelDamage(EnemyAgent target, PlayerAgent? source, OwnerType ownerType, int limbID, bool damageLimb, Vector3 localPos, Vector3 direction, float damage, float staggerMult, bool setCooldowns) { //IL_004f: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00a3: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) Dam_EnemyDamageBase damage2 = target.Damage; Dam_EnemyDamageLimb val = ((Il2CppArrayBase)(object)damage2.DamageLimbs)[limbID]; if (!(((Dam_SyncedDamageBase)damage2).Health <= 0f) && ((Agent)damage2.Owner).Alive && !damage2.IsImortal) { DamageAPI.FirePreShrapnelCallbacks(damage, target, val, source, ownerType); ES_HitreactType hitreact = (ES_HitreactType)((!(staggerMult > 0f)) ? 1 : 3); bool tryForceHitreact = false; bool flag = ((Dam_SyncedDamageBase)damage2).WillDamageKill(damage); CD_DestructionSeverity val2; if (flag) { tryForceHitreact = true; hitreact = (ES_HitreactType)4; val2 = (CD_DestructionSeverity)3; } else { val2 = (CD_DestructionSeverity)2; } EXPAPIWrapper.RegisterDamage(target, source, damage, flag); if (damageLimb && (flag || val.DoDamage(damage))) { damage2.CheckDestruction(val, ref localPos, ref direction, limbID, ref val2, ref tryForceHitreact, ref hitreact); } Vector3 position = localPos + target.Position; ProcessReceivedShrapnelDamage(damage2, damage, (Agent?)(object)source, position, direction, hitreact, tryForceHitreact, staggerMult, setCooldowns); DamageSyncWrapper.RunDamageSync(target, damageLimb ? limbID : (-1)); DamageAPI.FirePostShrapnelCallbacks(damage, target, val, source, ownerType); } } private static void ProcessReceivedShrapnelDamage(Dam_EnemyDamageBase damBase, float damage, Agent? damageSource, Vector3 position, Vector3 direction, ES_HitreactType hitreact, bool tryForceHitreact = false, float staggerDamageMulti = 1f, bool setCooldowns = true) { //IL_001a: 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_0060: 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_0088: 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_009b: 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_00a0: Unknown result type (might be due to invalid IL or missing references) EnemyAgent owner = damBase.Owner; bool num = ((Dam_SyncedDamageBase)damBase).RegisterDamage(damage); ((Agent)owner).RegisterDamageInflictor(damageSource); bool flag = false; if (num) { hitreact = (ES_HitreactType)5; flag = true; } else { damBase.m_damBuildToHitreact += damage * staggerDamageMulti; if (tryForceHitreact || damBase.m_damBuildToHitreact >= owner.EnemyBalancingData.Health.DamageUntilHitreact) { flag = true; damBase.m_damBuildToHitreact = 0f; } } owner.OnTakeCustomDamage(damage, damageSource, position, direction, hitreact, setCooldowns); if (flag && owner.Locomotion.Hitreact.CanHitreact(hitreact, tryForceHitreact)) { ImpactDirection direction2 = ES_Hitreact.GetDirection(((Component)owner).transform, direction); owner.Locomotion.Hitreact.ActivateState(hitreact, direction2, true, damageSource, position, (DamageNoiseLevel)0); } } } public struct ShrapnelHitData { public pEnemyAgent target; public pCWC cwc; public byte limbID; public bool damageLimb; public Vector3_32b localPosition; public Vector3_24b_Normalized dir; public float damage; public float staggerMult; public bool setCooldowns; } public struct ShrapnelHitPlayerData { public pPlayerAgent target; public pCWC cwc; public float damage; public Vector3_24b_Normalized dir; } internal sealed class ShrapnelHitSync : SyncedEventMasterOnly { public override string GUID => "SHPHIT"; protected override void Receive(ShrapnelHitData packet) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) EnemyAgent target = default(EnemyAgent); if (((pEnemyAgent)(ref packet.target)).TryGet(ref target)) { packet.cwc.TryGetSource(out PlayerAgent comp); ShrapnelHitManager.Internal_ReceiveShrapnelDamage(target, comp, packet.cwc.ownerType, packet.limbID, packet.damageLimb, packet.localPosition.Get(10f), packet.dir.Value, packet.damage, packet.staggerMult, packet.setCooldowns); } } } internal sealed class ShrapnelHitPlayerSync : SyncedEvent { public override string GUID => "SHPHITP"; protected override void Receive(ShrapnelHitPlayerData packet) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) PlayerAgent target = default(PlayerAgent); if (((pPlayerAgent)(ref packet.target)).TryGet(ref target)) { packet.cwc.TryGetSource(out PlayerAgent comp); ShrapnelHitManager.Internal_ReceiveShrapnelDamagePlayer(target, comp, packet.cwc.ownerType, packet.damage, packet.dir.Value); } } protected override void ReceiveLocal(ShrapnelHitPlayerData packet) { Receive(packet); } } } namespace EWC.CustomWeapon.Properties.Effects.PlayerPush { public class PushCap { private const float CapSteerStrength = 0.25f; public float Cap { get; private set; } public float SoftCap { get; private set; } public float SoftCapMod { get; private set; } = 0.5f; public bool IncludeVelocity { get; private set; } = true; public Vector3 AddAndCap(Vector3 current, Vector3 force, Vector3 velocity) { //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_0010: 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_0018: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00ba: 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_00f3: 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_00ea: 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_0101: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) Vector3 normalized = ((Vector3)(ref force)).normalized; float num = ((Vector3)(ref force)).magnitude; float num2 = Vector3.Dot(current, normalized); float num3 = Vector3.Dot(velocity, normalized); float num4 = num + num2 + num3; if (SoftCap > 0f && num4 > SoftCap) { float num5 = Math.Min(num4 - SoftCap, num); num -= (1f - SoftCapMod) * num5; num4 = num + num2 + num3; } if (Cap > 0f && num4 > Cap) { float num6; float num7; if (num2 + num3 >= Cap) { num6 = num2; num7 = num; } else { num6 = Math.Min(num2 + num, Cap - num3); num7 = num2 + num - num6; } Vector3 val = current - normalized * num2; float magnitude = ((Vector3)(ref val)).magnitude; magnitude = Math.Max(0f, magnitude - num7 * 0.25f); val = ((magnitude > 0.01f) ? (((Vector3)(ref val)).normalized * magnitude) : Vector3.zero); return normalized * num6 + val; } return current + normalized * num; } public float AddAndCap(float current, float force) { if (SoftCap > 0f && force + current > SoftCap) { float num = Math.Min(force + current - SoftCap, force); force -= (1f - SoftCapMod) * num; } if (Cap > 0f && force + current > Cap) { return Math.Max(current, Cap); } return current + force; } public void Serialize(Utf8JsonWriter writer) { writer.WriteStartObject(); writer.WriteNumber("Cap", Cap); writer.WriteNumber("SoftCap", SoftCap); writer.WriteNumber("SoftCapMod", SoftCapMod); writer.WriteBoolean("IncludeVelocity", IncludeVelocity); writer.WriteEndObject(); } private void DeserializeProperty(string propertyName, ref Utf8JsonReader reader) { switch (propertyName) { case "cap": Cap = reader.GetSingle(); break; case "softcap": SoftCap = reader.GetSingle(); break; case "softcapmod": SoftCapMod = reader.GetSingle(); break; case "includevelocity": IncludeVelocity = reader.GetBoolean(); break; } } public void Deserialize(ref Utf8JsonReader reader) { if (reader.TokenType == JsonTokenType.Number) { Cap = reader.GetSingle(); return; } if (reader.TokenType != JsonTokenType.StartObject) { throw new Exception("Expected number or StartObject token"); } while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); DeserializeProperty(@string.ToLowerInvariant().Replace(" ", ""), ref reader); } throw new JsonException("Expected EndObject token"); } } public sealed class PushHandler : MonoBehaviour { private class PushInstance { private Vector3 _force; private float _frictionStartTime; private readonly Push _settings; private readonly PlayerLocomotion _locomotion; private readonly PlayerCharacterController _controller; private readonly PLOC_Fall _fall; public Vector3 Force => _force; public PushInstance(Push settings) { //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) _locomotion = Current._player.Locomotion; _controller = Current._player.PlayerCharacterController; _fall = ((Il2CppObjectBase)((StateMachine)(object)_locomotion).GetState(4)).Cast(); _settings = settings; _frictionStartTime = Clock.Time + settings.FrictionDelay; _force = Vector3.zero; } public Vector3 AddForce(Vector3 force) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00a7: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) _frictionStartTime = Math.Max(_frictionStartTime, Clock.Time + _settings.RepeatFrictionDelay); ApplyVerticalForce(force.y); force.y = 0f; Vector3 velocity = Vector3.zero; if (_settings.HorizontalCap.IncludeVelocity) { velocity = Current._totalForce - _force + _locomotion.HorizontalVelocity + _locomotion.VerticalVelocity; velocity.y = 0f; } Vector3 force2 = _force; _force = _settings.HorizontalCap.AddAndCap(force2, force, velocity); return _force - force2; } public Vector3 OnWallCollision(Vector3 normal) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) float num = Vector3.Dot(_force, normal); if (num < 0f) { _force -= normal * num; } return _force; } public bool UpdateCheckDone() { //IL_0007: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0098: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //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) _controller.Move(_force * Clock.FixedDelta); if (_frictionStartTime > Clock.Time) { return false; } PLOC_State currentStateEnum = _locomotion.m_currentStateEnum; float num; float num2; if (currentStateEnum - 3 <= 1) { num = _settings.AirFrictionStrength; num2 = _settings.AirConstantFriction; } else { num = _settings.FrictionStrength; num2 = _settings.ConstantFriction; } Vector3 normalized = ((Vector3)(ref _force)).normalized; num *= Clock.FixedDelta; num2 *= Clock.FixedDelta; _force *= 1f - num; _force -= normalized * num2; return ((Vector3)(ref _force)).sqrMagnitude <= num2 * num2 + 0.01f; } private void ApplyVerticalForce(float force) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_0038: 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_0027: Invalid comparison between Unknown and I4 //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_00be: Unknown result type (might be due to invalid IL or missing references) if (force == 0f) { return; } Vector3 verticalVelocity = _locomotion.VerticalVelocity; PLOC_State currentStateEnum = _locomotion.m_currentStateEnum; if ((int)currentStateEnum != 3) { if ((int)currentStateEnum == 4) { _fall.m_enterTime = Clock.Time; verticalVelocity.y = _settings.VerticalCap.AddAndCap(verticalVelocity.y, force); if (verticalVelocity.y > 0f) { _locomotion.ChangeState((PLOC_State)3, true); } } else { if (force <= 0f) { return; } verticalVelocity.y = _settings.VerticalCap.AddAndCap(0f, force); if (verticalVelocity.y <= 0f) { return; } _locomotion.ChangeState((PLOC_State)3, true); } } else { verticalVelocity.y = _settings.VerticalCap.AddAndCap(verticalVelocity.y, force); } _locomotion.VerticalVelocity = verticalVelocity; } } private PlayerAgent _player; private CharacterController _controller; private readonly Dictionary _instances = new Dictionary(); private readonly List _finished = new List(); private Vector3 _totalForce; public static PushHandler Current { get; private set; } [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } [InvokeOnCleanup(false)] private static void Cleanup() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Current != (Object)null) { Current._instances.Clear(); Current._totalForce = Vector3.zero; ((Behaviour)Current).enabled = false; } } public PushHandler(IntPtr ptr) : base(ptr) { } public void Awake() { //IL_0030: 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) Current = this; ((Behaviour)this).enabled = false; _player = ((Component)this).GetComponent(); _controller = _player.PlayerCharacterController.m_characterController; _totalForce = Vector3.zero; } public static void AddInstance(Vector3 force, Push settings) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Current == (Object)null) { if (!PlayerManager.HasLocalPlayerAgent()) { return; } ((Component)PlayerManager.GetLocalPlayerAgent()).gameObject.AddComponent(); } Current.AddInstance_Internal(force, settings); } [HideFromIl2Cpp] private void AddInstance_Internal(Vector3 force, Push settings) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!_instances.TryGetValue(settings.SyncPropertyID, out PushInstance value)) { _instances.Add(settings.SyncPropertyID, value = new PushInstance(settings)); } _totalForce += value.AddForce(force); ((Behaviour)this).enabled = true; } private void OnControllerColliderHit(ControllerColliderHit hit) { //IL_0006: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if ((_controller.collisionFlags & 1) == 0) { return; } Vector3 normal = hit.normal; normal.y = 0f; if (((Vector3)(ref normal)).sqrMagnitude < 0.01f) { return; } ((Vector3)(ref normal)).Normalize(); _totalForce = Vector3.zero; foreach (PushInstance value in _instances.Values) { _totalForce += value.OnWallCollision(normal); } } private void FixedUpdate() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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) _totalForce = Vector3.zero; foreach (var (item, pushInstance2) in _instances) { if (pushInstance2.UpdateCheckDone()) { _finished.Add(item); } else { _totalForce += pushInstance2.Force; } } foreach (ushort item2 in _finished) { _instances.Remove(item2); } _finished.Clear(); if (_instances.Count == 0) { ((Behaviour)this).enabled = false; } } } public static class PushManager { private static readonly PushSync _sync = new PushSync(); [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); } public static void DoPush(PlayerAgent player, Vector3 force, Push settings) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) if (!(force == Vector3.zero)) { PushData pushData = default(PushData); pushData.force = force; pushData.propertyID = settings.SyncPropertyID; PushData packetData = pushData; _sync.Send(packetData, player.Owner, (SNet_ChannelType)4); } } internal static void Internal_ReceivePush(Vector3 force, Push settings) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) PushHandler.AddInstance(force, settings); } } public struct PushData { public Vector3 force; public ushort propertyID; } internal sealed class PushSync : SyncedEvent { public override string GUID => "PUSH"; protected override void Receive(PushData packet) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (PlayerManager.HasLocalPlayerAgent() && CustomDataManager.TryGetSyncProperty(packet.propertyID, out var property)) { PushManager.Internal_ReceivePush(packet.force, property); } } } } namespace EWC.CustomWeapon.Properties.Effects.Infection { internal sealed class InfectionFXSync : SyncedEvent { public override string GUID => "INFFX"; protected override void Receive(InfectionFXData data) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) PlayerAgent player = default(PlayerAgent); if (((pPlayerAgent)(ref data.player)).TryGet(ref player)) { InfectionManager.Internal_ReceiveInfectionFX(player, data.localPos.Get(10f), data.dir.Value); } } } internal sealed class DirectInfectionFXSync : SyncedEvent { public override string GUID => "DINFFX"; protected override void Receive(pPlayerAgent pPlayer) { PlayerAgent player = default(PlayerAgent); if (((pPlayerAgent)(ref pPlayer)).TryGet(ref player)) { InfectionManager.Internal_ReceiveDirectInfectionFX(player); } } } public static class InfectionManager { private static readonly InfectionFXSync _fxSync = new InfectionFXSync(); private static readonly DirectInfectionFXSync _directFXSync = new DirectInfectionFXSync(); [InvokeOnAssetLoad] private static void Init() { _fxSync.Setup(); _directFXSync.Setup(); } public static void DoInfectFX(PlayerAgent player, float infect, Vector3 pos, Vector3 dir) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) if (infect != 0f && !player.Owner.IsBot) { InfectionFXData infectionFXData = default(InfectionFXData); infectionFXData.isDirect = false; InfectionFXData packetData = infectionFXData; ((pPlayerAgent)(ref packetData.player)).Set(player); packetData.localPos.Set(pos - ((Agent)player).Position, 10f); packetData.dir.Value = dir; _fxSync.Send(packetData, player.Owner, (SNet_ChannelType)4); } } public static void DoDirectInfectFX(PlayerAgent player, float infect) { //IL_0018: 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) if (infect != 0f && !player.Owner.IsBot) { pPlayerAgent packetData = default(pPlayerAgent); ((pPlayerAgent)(ref packetData)).Set(player); _directFXSync.Send(packetData, player.Owner, (SNet_ChannelType)4); } } internal static void Internal_ReceiveInfectionFX(PlayerAgent player, Vector3 localPos, Vector3 dir) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_000d: Unknown result type (might be due to invalid IL or missing references) ScreenLiquidManager.Apply((ScreenLiquidSettingName)4, localPos + ((Agent)player).Position, dir); player.Sound.Post(EVENTS.VISOR_SPLATTER_INFECTION, true); } internal static void Internal_ReceiveDirectInfectionFX(PlayerAgent player) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) ScreenLiquidManager.DirectApply((ScreenLiquidSettingName)4, new Vector2(0.5f, 0.5f), Vector2.zero); player.Sound.Post(EVENTS.VISOR_SPLATTER_INFECTION, true); } } public struct InfectionFXData { public pPlayerAgent player; public Vector3_32b localPos; public Vector3_24b_Normalized dir; public bool isDirect; } } namespace EWC.CustomWeapon.Properties.Effects.Heal { internal sealed class HealFXSync : SyncedEvent { public override string GUID => "HEALFX"; protected override void Receive(float damage) { HealManager.Internal_ReceiveHealDamage(damage); } } public static class HealManager { private static readonly HealSync _sync = new HealSync(); private static readonly HealFXSync _fxSync = new HealFXSync(); private const float SingleVal = 1.5259022E-05f; private const float FLASH_CONVERSION = 6f; [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); _fxSync.Setup(); } public static void DoHeal(PlayerAgent player, float heal, float cap, HealthMod hBase) { if (heal != 0f) { HealData healData = default(HealData); healData.cancelRegen = hBase.CancelRegen; healData.damageFX = hBase.EnableDamageFX && !player.Owner.IsBot; HealData packet = healData; ((pPlayerAgent)(ref packet.player)).Set(player); packet.heal.Set(heal, ((Dam_SyncedDamageBase)player.Damage).HealthMax); packet.cap.Set(cap, ((Dam_SyncedDamageBase)player.Damage).HealthMax); _sync.Send(packet, (SNet_ChannelType)4); } } internal static void Internal_ReceiveHeal(PlayerAgent player, float heal, float cap, bool cancelRegen, bool showDamageFX) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) Dam_PlayerDamageBase damage = player.Damage; if (heal > 0f) { heal = Math.Min(heal, cap + 1.5259022E-05f - ((Dam_SyncedDamageBase)damage).Health); if (!(heal <= 0f)) { ((Dam_SyncedDamageBase)damage).SendSetHealth(Math.Min(((Dam_SyncedDamageBase)damage).Health + heal, ((Dam_SyncedDamageBase)player.Damage).HealthMax)); if (cancelRegen) { damage.m_nextRegen = Clock.Time + player.PlayerData.healthRegenStartDelayAfterDamage * EXPAPIWrapper.GetHealthRegenMod(player); } } return; } heal = Math.Min(0f - heal, ((Dam_SyncedDamageBase)damage).Health - (cap - 1.5259022E-05f)); if (!(heal <= 0f)) { float nextRegen = damage.m_nextRegen; ShotManager.ReceivePlayerDamage(player, heal, PlayerDamageType.Heal, Vector3.zero, cameraShake: false); damage.m_nextRegen = (cancelRegen ? (Clock.Time + player.PlayerData.healthRegenStartDelayAfterDamage * EXPAPIWrapper.GetHealthRegenMod(player)) : nextRegen); if (showDamageFX) { _fxSync.Send(heal, player.Owner, (SNet_ChannelType)4); } } } internal static void Internal_ReceiveHealDamage(float damage) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); localPlayerAgent.FPSCamera.AddHitReact(damage / ((Dam_SyncedDamageBase)localPlayerAgent.Damage).HealthMax * 6f, Vector3.up, 0f, true, true); } } public struct HealData { public pPlayerAgent player; public SFloat16b heal; public UFloat16b cap; public bool cancelRegen; public bool damageFX; } internal sealed class HealSync : SyncedEventMasterOnly { public override string GUID => "HEAL"; protected override void Receive(HealData packet) { PlayerAgent val = default(PlayerAgent); if (((pPlayerAgent)(ref packet.player)).TryGet(ref val)) { HealManager.Internal_ReceiveHeal(val, packet.heal.Get(((Dam_SyncedDamageBase)val.Damage).HealthMax), packet.cap.Get(((Dam_SyncedDamageBase)val.Damage).HealthMax), packet.cancelRegen, packet.damageFX); } } } } namespace EWC.CustomWeapon.Properties.Effects.Debuff { public class DebuffBasicHolder : DebuffHolderBase { public class DebuffBasicGroup : IDebuffGroup { public class DebuffModifier : DebuffModifierBase { private readonly DebuffBasicGroup _group; public DebuffModifier(float mod, DebuffBasicGroup group) : base(mod) { _group = group; } protected override void AddToGroup() { _group._modifiers.Add(this); } protected override void RemoveFromGroup() { _group._modifiers.Remove(this); } protected override void RefreshGroup() { _group.Refresh(); } } private readonly HashSet _modifiers = new HashSet(); private readonly DebuffBasicHolder _holder; private float _mod = 1f; private bool _needRecompute; public DebuffBasicGroup(DebuffBasicHolder holder) { _holder = holder; } public float GetMod() { if (!_needRecompute) { return _mod; } _mod = 1f; foreach (DebuffModifier modifier in _modifiers) { _mod *= modifier.Mod; } _needRecompute = false; return _mod; } void IDebuffGroup.Reset() { foreach (DebuffModifier modifier in _modifiers) { modifier.Active = false; } _modifiers.Clear(); _mod = 1f; } private void Refresh() { _needRecompute = true; _holder.NeedRecompute = true; } } private float _mod = 1f; public DebuffModifierBase AddModifier(float mod, uint group) { DebuffBasicGroup.DebuffModifier debuffModifier = new DebuffBasicGroup.DebuffModifier(mod, GetGroup(group)); debuffModifier.Enable(); return debuffModifier; } public float GetMod(HashSet groups) { if (!NeedRecompute && GroupsMatch(groups)) { return _mod; } SetActiveGroups(groups); _mod = 1f; foreach (DebuffBasicGroup activeGroup in ActiveGroups) { _mod *= activeGroup.GetMod(); } NeedRecompute = false; return _mod; } protected override DebuffBasicGroup CreateGroup() { return new DebuffBasicGroup(this); } protected override void OnReset() { _mod = 1f; } } public abstract class DebuffHolderBase where T : IDebuffGroup { private static readonly HashSet s_emptyGroup = new HashSet(); protected readonly Dictionary Groups = new Dictionary(); private HashSet _currentGroup = s_emptyGroup; protected readonly HashSet ActiveGroups = new HashSet(); protected bool NeedRecompute; internal void Reset() { foreach (T value in Groups.Values) { value.Reset(); } NeedRecompute = false; OnReset(); } protected bool GroupsMatch(HashSet groups) { if (_currentGroup == groups || (_currentGroup.Count == groups.Count && _currentGroup.SetEquals(groups))) { _currentGroup = groups; return true; } return false; } protected void SetActiveGroups(HashSet groups) { if (GroupsMatch(groups)) { return; } _currentGroup = groups; ActiveGroups.Clear(); ActiveGroups.EnsureCapacity(groups.Count); foreach (uint group in groups) { if (Groups.TryGetValue(group, out var value)) { ActiveGroups.Add(value); } } } protected T GetGroup(uint id) { if (!Groups.TryGetValue(id, out var value)) { Groups.Add(id, value = CreateGroup()); } return value; } protected abstract T CreateGroup(); protected abstract void OnReset(); } public static class DebuffManager { private static readonly Dictionary _shotMods = new Dictionary(); private static readonly Dictionary _armorShreds = new Dictionary(); private static readonly Dictionary _armorMods = new Dictionary(); public const uint DefaultGroup = 0u; public static readonly HashSet DefaultGroupSet = new HashSet(1) { 0u }; private static readonly Dictionary s_stringToIDDict = new Dictionary(); private static uint s_nextID = uint.MaxValue; private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; [InvokeOnCleanup(false)] private static void Reset() { _shotMods.Clear(); _armorShreds.Clear(); } public static DebuffModifierBase AddShotModDebuff(IDamageable damageable, float mod, StatType statType, StackType layer, DamageType[] damageType, uint group) { if (!_shotMods.TryGetValue(TempWrapper.Set(damageable), out DebuffShotHolder[] value)) { _shotMods.Where>((KeyValuePair kv) => !kv.Key.Alive).ToList().ForEach(delegate(KeyValuePair kv) { DebuffShotHolder[] value2 = kv.Value; for (int i = 0; i < value2.Length; i++) { value2[i]?.Reset(); } _shotMods.Remove(kv.Key); }); _shotMods.Add(new BaseDamageableWrapper(TempWrapper), value = new DebuffShotHolder[StatTypeConst.Count]); } DebuffShotHolder[] array = value; if (array[(int)statType] == null) { array[(int)statType] = new DebuffShotHolder(); } return value[(int)statType].AddModifier(mod, layer, damageType, group); } public static bool TryGetShotModDebuff(IDamageable damageable, StatType statType, DamageType damageType, HashSet groups, out StackValue mod) { if (_shotMods.TryGetValue(TempWrapper.Set(damageable), out DebuffShotHolder[] value) && value[(int)statType] != null) { mod = value[(int)statType].GetMod(damageType, groups); return true; } mod = default(StackValue); return false; } public static DebuffModifierBase AddArmorModBuff(IDamageable damageable, float mod, StackType layer, PlayerDamageType[] damageType) { if (!_armorMods.TryGetValue(TempWrapper.Set(damageable), out DebuffPlayerShotHolder value)) { _armorMods.Where>((KeyValuePair kv) => !kv.Key.Alive).ToList().ForEach(delegate(KeyValuePair kv) { kv.Value.Reset(); _armorMods.Remove(kv.Key); }); _armorMods.Add(new BaseDamageableWrapper(TempWrapper), value = new DebuffPlayerShotHolder()); } return value.AddModifier(mod, layer, damageType); } public static DebuffModifierBase AddArmorImmuneBuff(IDamageable damageable, PlayerDamageType[] damageType) { if (!_armorMods.TryGetValue(TempWrapper.Set(damageable), out DebuffPlayerShotHolder value)) { _armorMods.Where>((KeyValuePair kv) => !kv.Key.Alive).ToList().ForEach(delegate(KeyValuePair kv) { kv.Value.Reset(); _armorMods.Remove(kv.Key); }); _armorMods.Add(new BaseDamageableWrapper(TempWrapper), value = new DebuffPlayerShotHolder()); } return value.AddImmuneModifier(damageType); } public static bool TryGetArmorModBuff(IDamageable damageable, PlayerDamageType damageType, out bool immune, out float mod) { if (_armorMods.TryGetValue(TempWrapper.Set(damageable), out DebuffPlayerShotHolder value)) { if (value.IsImmune(damageType)) { immune = true; mod = 0f; } else { immune = false; mod = value.GetMod(damageType).Value; } return true; } mod = 0f; immune = false; return false; } public static DebuffModifierBase AddArmorShredDebuff(IDamageable damageable, float mod, StackType layer, uint group) { if (!_armorShreds.TryGetValue(TempWrapper.Set(damageable), out DebuffStackHolder value)) { _armorShreds.Where>((KeyValuePair kv) => !kv.Key.Alive).ToList().ForEach(delegate(KeyValuePair kv) { kv.Value.Reset(); _armorShreds.Remove(kv.Key); }); _armorShreds.Add(new BaseDamageableWrapper(TempWrapper), value = new DebuffStackHolder()); } return value.AddModifier(mod, layer, group); } public static bool TryGetArmorShredDebuff(IDamageable damageable, HashSet groups, out float mod) { if (_armorShreds.TryGetValue(TempWrapper.Set(damageable), out DebuffStackHolder value)) { mod = Math.Max(0f, value.GetMod(groups).Value - 1f); return true; } mod = 0f; return false; } public static void ApplyArmorShredDebuff(ref float armorMulti, float mod) { if (armorMulti >= 1f) { armorMulti = Math.Max(armorMulti, mod); } else if (mod < 1f) { armorMulti += (1f - armorMulti) * mod; } else { armorMulti = mod; } } public static void GetAndApplyArmorShredDebuff(ref float armorMulti, IDamageable damageable, HashSet groups) { if (TryGetArmorShredDebuff(damageable, groups, out var mod)) { ApplyArmorShredDebuff(ref armorMulti, mod); } } public static uint StringIDToInt(string id) { if (!s_stringToIDDict.ContainsKey(id)) { s_stringToIDDict.Add(id, s_nextID--); } return s_stringToIDDict[id]; } } public abstract class DebuffModifierBase { private float _mod; public float Mod { get { return _mod; } set { float mod = _mod; _mod = value; if (Active && mod != _mod) { RefreshGroup(); } } } public bool Active { get; internal set; } public DebuffModifierBase(float mod) { Active = false; _mod = mod; } protected abstract void RefreshGroup(); protected abstract void AddToGroup(); protected abstract void RemoveFromGroup(); public void Enable() { if (!Active) { Active = true; AddToGroup(); RefreshGroup(); } } public void Enable(float mod) { if (!Active) { _mod = mod; Enable(); } else { Mod = mod; } } public void Disable() { if (Active) { Active = false; RemoveFromGroup(); RefreshGroup(); } } } public class DebuffPlayerShotHolder : DebuffHolderBase { public class DebuffPlayerShotGroup : IDebuffGroup { public class DebuffModifier : DebuffModifierBase { private readonly StackType _layer; private readonly DebuffPlayerShotGroup _group; private readonly bool _hasType; public PlayerDamageType[] DamageType { get; } public DebuffModifier(float mod, StackType layer, PlayerDamageType[] damageType, DebuffPlayerShotGroup group) : base(mod) { DamageType = damageType; _group = group; _layer = layer; _hasType = damageType.Length > 1 || (damageType.Length == 1 && damageType[0] != PlayerDamageType.Any); } protected override void RefreshGroup() { PlayerDamageType[] damageType = DamageType; foreach (PlayerDamageType damageType2 in damageType) { _group.Refresh(_layer, damageType2); } } protected override void AddToGroup() { _group.GetLayer(_layer).Add(this); if (_hasType) { _group.NeedType = true; } } protected override void RemoveFromGroup() { _group.GetLayer(_layer).Remove(this); if (_hasType) { _group.NeedType = false; } } } public class ImmuneModifier : DebuffModifierBase { private readonly DebuffPlayerShotGroup _group; private readonly bool _hasType; public PlayerDamageType[] DamageType { get; } public ImmuneModifier(PlayerDamageType[] damageType, DebuffPlayerShotGroup group) : base(1f) { DamageType = damageType; _group = group; _hasType = damageType.Length > 1 || (damageType.Length == 1 && damageType[0] != PlayerDamageType.Any); } protected override void RefreshGroup() { PlayerDamageType[] damageType = DamageType; foreach (PlayerDamageType damageType2 in damageType) { _group.RefreshImmune(damageType2); } } protected override void AddToGroup() { _group._immunities.Add(this); if (_hasType) { _group.NeedType = true; } } protected override void RemoveFromGroup() { _group._immunities.Remove(this); if (_hasType) { _group.NeedType = false; } } } private readonly HashSet[] _layers = new HashSet[StackTypeConst.Count]; private readonly HashSet _immunities = new HashSet(); private StackValue _mod = new StackValue(); private bool _immune; private PlayerDamageType _currentType; private int _needTypeStack; private uint _recomputeMask; private bool _recomputeImmune; private bool NeedType { get { return _needTypeStack > 0; } set { _needTypeStack += (value ? 1 : (-1)); } } public bool IsImmune(PlayerDamageType damageType) { bool flag = !NeedType || _currentType == damageType; if (_recomputeImmune || !flag) { RecomputeImmunity(damageType); } return _immune; } public StackValue GetMod(PlayerDamageType damageType) { bool flag = !NeedType || _currentType == damageType; if (_recomputeMask == 0 && flag) { return _mod; } _currentType = damageType; if (!flag) { _recomputeMask = 0u; for (int i = 0; i < StackTypeConst.Count; i++) { Recompute((StackType)i, damageType); } } else { uint num = 0u; while (_recomputeMask != 0) { if ((_recomputeMask & (true ? 1u : 0u)) != 0) { Recompute((StackType)num, damageType); } _recomputeMask >>= 1; num++; } } return _mod; } public void Reset() { HashSet[] layers = _layers; foreach (HashSet hashSet in layers) { if (hashSet == null) { continue; } foreach (DebuffModifier item in hashSet) { item.Active = false; } hashSet.Clear(); } _mod.Reset(); _needTypeStack = 0; _currentType = PlayerDamageType.Any; _recomputeMask = 0u; } private HashSet GetLayer(StackType layer) { return _layers[(int)layer] ?? (_layers[(int)layer] = new HashSet()); } private void Refresh(StackType layer, PlayerDamageType damageType) { if ((!NeedType || _currentType.HasFlag(damageType)) && _layers[(int)layer] != null) { _recomputeMask |= (uint)(1 << (int)layer); } } private void RefreshImmune(PlayerDamageType damageType) { if (!NeedType || _currentType.HasFlag(damageType)) { _recomputeImmune = true; } } private void Recompute(StackType layer, PlayerDamageType damageType) { if (_layers[(int)layer] == null) { return; } _mod.Reset(layer); foreach (DebuffModifier item in GetLayer(layer)) { if (damageType.HasFlagIn(item.DamageType)) { _mod.Add(item.Mod, layer); } } } private void RecomputeImmunity(PlayerDamageType damageType) { _immune = false; foreach (ImmuneModifier immunity in _immunities) { if (damageType.HasFlagIn(immunity.DamageType)) { _immune = true; break; } } } } private StackValue _mod = new StackValue(); private readonly DebuffPlayerShotGroup _group; public DebuffPlayerShotHolder() { _group = new DebuffPlayerShotGroup(); } public DebuffModifierBase AddModifier(float mod, StackType layer, PlayerDamageType[] damageType) { DebuffPlayerShotGroup.DebuffModifier debuffModifier = new DebuffPlayerShotGroup.DebuffModifier(mod, layer, damageType, _group); debuffModifier.Enable(); return debuffModifier; } public DebuffModifierBase AddImmuneModifier(PlayerDamageType[] damageType) { DebuffPlayerShotGroup.ImmuneModifier immuneModifier = new DebuffPlayerShotGroup.ImmuneModifier(damageType, _group); immuneModifier.Enable(); return immuneModifier; } public bool IsImmune(PlayerDamageType damageType) { return _group.IsImmune(damageType); } public StackValue GetMod(PlayerDamageType damageType) { return _group.GetMod(damageType); } protected override DebuffPlayerShotGroup CreateGroup() { return _group; } protected override void OnReset() { _mod.Reset(); } } public class DebuffShotHolder : DebuffHolderBase { public class DebuffShotGroup : IDebuffGroup { public class DebuffModifier : DebuffModifierBase { private readonly StackType _layer; private readonly DebuffShotGroup _group; private readonly bool _hasType; public DamageType[] DamageType { get; } public DebuffModifier(float mod, StackType layer, DamageType[] damageType, DebuffShotGroup group) : base(mod) { DamageType = damageType; _group = group; _layer = layer; _hasType = damageType.Length > 1 || (damageType.Length == 1 && damageType[0] != EWC.CustomWeapon.Enums.DamageType.Any); } protected override void RefreshGroup() { DamageType[] damageType = DamageType; foreach (DamageType damageType2 in damageType) { _group.Refresh(_layer, damageType2); } } protected override void AddToGroup() { _group.GetLayer(_layer).Add(this); if (_hasType) { _group.NeedType = true; } } protected override void RemoveFromGroup() { _group.GetLayer(_layer).Remove(this); if (_hasType) { _group.NeedType = false; } } } private readonly HashSet[] _layers = new HashSet[StackTypeConst.Count]; private readonly DebuffShotHolder _holder; private StackValue _mod = new StackValue(); private DamageType _currentType; private int _needTypeStack; private uint _recomputeMask; private bool NeedType { get { return _needTypeStack > 0; } set { if (value) { if (_needTypeStack++ == 0) { _holder.NeedType = true; } } else if (--_needTypeStack == 0) { _holder.NeedType = false; } } } public DebuffShotGroup(DebuffShotHolder holder) { _holder = holder; } public StackValue GetMod(DamageType damageType) { bool flag = !NeedType || _currentType == damageType; if (_recomputeMask == 0 && flag) { return _mod; } _currentType = damageType; if (!flag) { _recomputeMask = 0u; for (int i = 0; i < StackTypeConst.Count; i++) { Recompute((StackType)i, damageType); } } else { uint num = 0u; while (_recomputeMask != 0) { if ((_recomputeMask & (true ? 1u : 0u)) != 0) { Recompute((StackType)num, damageType); } _recomputeMask >>= 1; num++; } } return _mod; } public void Reset() { HashSet[] layers = _layers; foreach (HashSet hashSet in layers) { if (hashSet == null) { continue; } foreach (DebuffModifier item in hashSet) { item.Active = false; } hashSet.Clear(); } _mod.Reset(); _needTypeStack = 0; _currentType = DamageType.Any; _recomputeMask = 0u; } private HashSet GetLayer(StackType layer) { return _layers[(int)layer] ?? (_layers[(int)layer] = new HashSet()); } private void Refresh(StackType layer, DamageType damageType) { if ((!NeedType || _currentType.HasFlag(damageType)) && _layers[(int)layer] != null) { _recomputeMask |= (uint)(1 << (int)layer); _holder.NeedRecompute = true; } } private void Recompute(StackType layer, DamageType damageType) { if (_layers[(int)layer] == null) { return; } _mod.Reset(layer); foreach (DebuffModifier item in GetLayer(layer)) { if (damageType.HasFlagIn(item.DamageType)) { _mod.Add(item.Mod, layer); } } } } private StackValue _mod = new StackValue(); private DamageType _currentType; private int _needTypeStack; private bool NeedType { get { return _needTypeStack > 0; } set { _needTypeStack += (value ? 1 : (-1)); } } public DebuffModifierBase AddModifier(float mod, StackType layer, DamageType[] damageType, uint group) { DebuffShotGroup.DebuffModifier debuffModifier = new DebuffShotGroup.DebuffModifier(mod, layer, damageType, GetGroup(group)); debuffModifier.Enable(); return debuffModifier; } public StackValue GetMod(DamageType damageType, HashSet groups) { if (!NeedRecompute && (!NeedType || _currentType == damageType) && GroupsMatch(groups)) { return _mod; } SetActiveGroups(groups); _mod.Reset(); foreach (DebuffShotGroup activeGroup in ActiveGroups) { _mod.Combine(activeGroup.GetMod(damageType)); } _currentType = damageType; NeedRecompute = false; return _mod; } protected override DebuffShotGroup CreateGroup() { return new DebuffShotGroup(this); } protected override void OnReset() { _mod.Reset(); _needTypeStack = 0; _currentType = DamageType.Any; } } public class DebuffStackHolder : DebuffHolderBase { public class DebuffStackGroup : IDebuffGroup { public class DebuffModifier : DebuffModifierBase { private readonly StackType _layer; private readonly DebuffStackGroup _group; public DebuffModifier(float mod, StackType layer, DebuffStackGroup group) : base(mod) { _group = group; _layer = layer; } protected override void RefreshGroup() { _group.Refresh(_layer); } protected override void AddToGroup() { _group.GetLayer(_layer).Add(this); } protected override void RemoveFromGroup() { _group.GetLayer(_layer).Remove(this); } } private readonly HashSet[] _layers = new HashSet[StackTypeConst.Count]; private readonly DebuffStackHolder _holder; private StackValue _mod = new StackValue(); private uint _recomputeMask; public DebuffStackGroup(DebuffStackHolder holder) { _holder = holder; } public StackValue GetMod() { if (_recomputeMask == 0) { return _mod; } uint num = 0u; while (_recomputeMask != 0) { if ((_recomputeMask & (true ? 1u : 0u)) != 0) { Recompute((StackType)num); } _recomputeMask >>= 1; num++; } return _mod; } public void Reset() { HashSet[] layers = _layers; foreach (HashSet hashSet in layers) { if (hashSet == null) { continue; } foreach (DebuffModifier item in hashSet) { item.Active = false; } hashSet.Clear(); } _mod.Reset(); _recomputeMask = 0u; } private HashSet GetLayer(StackType layer) { return _layers[(int)layer] ?? (_layers[(int)layer] = new HashSet()); } private void Refresh(StackType layer) { if (_layers[(int)layer] != null) { _recomputeMask |= (uint)(1 << (int)layer); _holder.NeedRecompute = true; } } private void Recompute(StackType layer) { if (_layers[(int)layer] == null) { return; } _mod.Reset(layer); foreach (DebuffModifier item in GetLayer(layer)) { _mod.Add(item.Mod, layer); } } } private StackValue _mod = new StackValue(); public DebuffModifierBase AddModifier(float mod, StackType layer, uint group) { DebuffStackGroup.DebuffModifier debuffModifier = new DebuffStackGroup.DebuffModifier(mod, layer, GetGroup(group)); debuffModifier.Enable(); return debuffModifier; } public StackValue GetMod(HashSet groups) { if (!NeedRecompute && GroupsMatch(groups)) { return _mod; } SetActiveGroups(groups); _mod.Reset(); foreach (DebuffStackGroup activeGroup in ActiveGroups) { _mod.Combine(activeGroup.GetMod()); } NeedRecompute = false; return _mod; } protected override DebuffStackGroup CreateGroup() { return new DebuffStackGroup(this); } protected override void OnReset() { _mod.Reset(); } } public interface IDebuffGroup { void Reset(); } } namespace EWC.CustomWeapon.Properties.Effects.Hit.Explosion { internal sealed class ExplosionDamageSync : SyncedEventMasterOnly { public override string GUID => "EXPDMG"; protected override void Receive(ExplosionDamageData packet) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) EnemyAgent target = default(EnemyAgent); if (((pEnemyAgent)(ref packet.target)).TryGet(ref target)) { packet.cwc.TryGetSource(out PlayerAgent comp); ExplosionManager.Internal_ReceiveExplosionDamage(target, comp, packet.cwc.ownerType, packet.limbID, packet.damageLimb, packet.localPosition.Get(10f), packet.direction.Value, packet.damage, packet.staggerMult, packet.setCooldowns); } } } internal sealed class ExplosionDamagePlayerSync : SyncedEvent { public override string GUID => "EXPDMGP"; protected override void Receive(ExplosionDamagePlayerData packet) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) PlayerAgent target = default(PlayerAgent); if (((pPlayerAgent)(ref packet.target)).TryGet(ref target)) { packet.cwc.TryGetSource(out PlayerAgent comp); ExplosionManager.Internal_ReceiveExplosionDamagePlayer(target, comp, packet.cwc.ownerType, packet.damage, packet.direction.Value); } } protected override void ReceiveLocal(ExplosionDamagePlayerData packet) { Receive(packet); } } internal static class ExplosionFXManager { private static readonly ExplosionFXSync _sync = new ExplosionFXSync(); private static FX_Pool _mineFXPool = null; private static float _lastSoundTime = 0f; private static int _soundShotOverride = 0; private static Quaternion _mineFXRotation; public const float MaxGlowDuration = 50f; public const float MaxGlowIntensity = 512f; [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); _mineFXPool = FX_Manager.GetEffectPool(AssetShardManager.GetLoadedAsset("Assets/AssetPrefabs/FX_Effects/FX_Tripmine.prefab", false)); } public static void DoExplosionFX(Vector3 position, Vector3 normal, Explosive eBase) { //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_0026: Unknown result type (might be due to invalid IL or missing references) ExplosionFXData explosionFXData = default(ExplosionFXData); explosionFXData.position = position; explosionFXData.propertyID = eBase.SyncPropertyID; ExplosionFXData packetData = explosionFXData; packetData.normal.Value = normal; _sync.Send(packetData, null, (SNet_ChannelType)4); } internal static void Internal_ReceiveExplosionFX(Vector3 position, Vector3 normal, Explosive eBase) { //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_008f: 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_00be: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: 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) if (Configuration.PlayExplosionSFX) { _soundShotOverride++; if (eBase.SoundID != 0 && (_soundShotOverride > Configuration.ExplosionSFXShotOverride || Clock.Time - _lastSoundTime > Configuration.ExplosionSFXCooldown)) { CellSound.Post(eBase.SoundID, position); _soundShotOverride = 0; _lastSoundTime = Clock.Time; } } if (Configuration.ShowExplosionEffect && eBase.Radius > 0f) { if (eBase.EnableMineFX) { ((Quaternion)(ref _mineFXRotation)).SetLookRotation(normal); ((FX_EffectBase)_mineFXPool.AquireEffect()).Play((FX_Trigger)null, position, _mineFXRotation); } if (eBase.GlowDuration > 0f && eBase.GlowIntensity > 0f) { ExplosionEffectData data = default(ExplosionEffectData); data.position = position; data.flashColor = eBase.GlowColor; data.intensity = eBase.GlowIntensity; data.range = eBase.Radius; data.duration = eBase.GlowDuration; data.fadeDuration = eBase.GlowFadeDuration; ExplosionEffectPooling.TryDoEffect(data); } } if (Configuration.PlayExplosionShake && eBase.ScreenShakeIntensity > 0f && eBase.ScreenShakeDuration > 0f) { float fromMin = ((eBase.ScreenShakeInnerRadius > 0f) ? eBase.ScreenShakeInnerRadius : eBase.InnerRadius); float num = ((eBase.ScreenShakeRadius > 0f) ? eBase.ScreenShakeRadius : eBase.Radius); PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); Vector3 val = position - ((Agent)localPlayerAgent).Position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < num) { float num2 = magnitude.MapInverted(fromMin, num, eBase.ScreenShakeIntensity, 0f, eBase.Exponent); localPlayerAgent.FPSCamera.Shake(eBase.ScreenShakeDuration, num2, eBase.ScreenShakeFrequency, ((Vector3)(ref val)).normalized); } } ExplosionAPI.FireExplosionSpawnedCallback(position, eBase); } } public struct ExplosionFXData { public Vector3 position; public Vector3_24b_Normalized normal; public ushort propertyID; } internal sealed class ExplosionFXSync : SyncedEvent { public override string GUID => "EXPFX"; protected override void Receive(ExplosionFXData packet) { //IL_0011: 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) if (CustomDataManager.TryGetSyncProperty(packet.propertyID, out var property)) { ExplosionFXManager.Internal_ReceiveExplosionFX(packet.position, packet.normal.Value, property); } } protected override void ReceiveLocal(ExplosionFXData packet) { Receive(packet); } } public static class ExplosionManager { private static readonly ExplosionDamageSync _sync = new ExplosionDamageSync(); private static readonly ExplosionDamagePlayerSync _playerSync = new ExplosionDamagePlayerSync(); private const SearchSetting BaseSettings = SearchSetting.ClosestHit | SearchSetting.CheckLOS; [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); _playerSync.Setup(); } public static void DoExplosion(Vector3 position, Vector3 direction, Vector3 normal, float falloffMod, Explosive eBase, float triggerAmt, ShotInfo? triggerInfo = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (eBase.CWC.Owner.IsType(OwnerType.Managed)) { ExplosionFXManager.DoExplosionFX(position, (normal != Vector3.zero) ? normal : direction, eBase); DoExplosionDamage(position, direction, falloffMod, eBase, triggerAmt, triggerInfo); } } internal static void DoExplosionDamage(Vector3 position, Vector3 direction, float falloffMod, Explosive explosiveBase, float triggerAmt, ShotInfo? triggerInfo) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0186: 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) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: 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) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) if (explosiveBase.Radius == 0f || (explosiveBase.MaxDamage == 0f && explosiveBase.MinDamage == 0f)) { return; } AIG_CourseNode courseNode = CourseNodeUtil.GetCourseNode(position, explosiveBase.CWC.Owner.DimensionIndex); if (courseNode == null) { EWCLogger.Error($"Unable to find node containing position [{position}] for an explosion."); return; } Ray ray = default(Ray); ((Ray)(ref ray))..ctor(position, direction); SearchSetting searchSetting = SearchSetting.ClosestHit | SearchSetting.CheckLOS; if (explosiveBase.DamageOwner) { searchSetting |= SearchSetting.CheckOwner; } if (explosiveBase.DamageFriendly) { searchSetting |= SearchSetting.CheckFriendly; } List list = new List(); SearchUtil.SightBlockLayer = LayerUtil.MaskWorldExcProj; foreach (var item3 in SearchUtil.GetEnemyHitsInRange(ray, explosiveBase.Radius, 180f, courseNode, searchSetting)) { RaycastHit item = item3.hit; list.Add(item); } PlayerAgent source = (explosiveBase.CWC.Owner.IsType(OwnerType.Player) ? explosiveBase.CWC.Owner.Player : null); if (explosiveBase.DamageFriendly || explosiveBase.DamageOwner) { foreach (var item4 in SearchUtil.GetPlayerHitsInRange(ray, explosiveBase.Radius, 180f, source, searchSetting)) { RaycastHit item2 = item4.hit; list.Add(item2); } } if (explosiveBase.DamageLocks) { list.AddRange(SearchUtil.GetLockHitsInRange(ray, explosiveBase.Radius, 180f, searchSetting)); } if (explosiveBase.HitClosestFirst) { list.Sort(SortUtil.Rayhit); } ShotInfo shotInfo = ((triggerInfo == null) ? new ShotInfo(explosiveBase.CWC, modOnly: true) : new ShotInfo(triggerInfo, modOnly: true, explosiveBase.UseParentShotMod)); ShotInfo.Const state = shotInfo.State; foreach (RaycastHit item5 in list) { RaycastHit current = item5; Vector3 val = ((RaycastHit)(ref current)).point - position; Vector3 normalized = ((Vector3)(ref val)).normalized; SendExplosionDamage(((Component)((RaycastHit)(ref current)).collider).GetComponent(), ((RaycastHit)(ref current)).point, explosiveBase.HitFromExplosionPos ? normalized : direction, normalized, ((RaycastHit)(ref current)).normal, ((RaycastHit)(ref current)).distance, falloffMod, shotInfo, explosiveBase, triggerAmt); } explosiveBase.CWC.Invoke(new WeaponShotEndContext(DamageType.Explosive, shotInfo.State, state)); } internal static void SendExplosionDamage(IDamageable damageable, Vector3 position, Vector3 direction, Vector3 blastDir, Vector3 normal, float distance, float falloffMod, ShotInfo info, Explosive eBase, float triggerAmt) { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Invalid comparison between Unknown and I4 //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Invalid comparison between Unknown and I4 float num = distance.MapInverted(eBase.InnerRadius, eBase.Radius, eBase.MaxDamage, eBase.MinDamage, eBase.Exponent); float num2 = num / eBase.MaxDamage; num *= triggerAmt; float num3 = eBase.PrecisionDamageMulti; float num4 = eBase.StaggerDamageMulti; float num5 = 1f; float num6 = 1f; bool flag = damageable.IsEnemy(); Dam_EnemyDamageLimb val = null; if (flag) { val = ((Il2CppObjectBase)damageable).Cast(); if (!eBase.IgnoreBackstab && eBase.CWC.Weapon.AllowBackstab) { if (eBase.CacheBackstab > 0f) { num5 = eBase.CacheBackstab; } else { float value = eBase.CWC.Invoke(new WeaponBackstabContext()).Value; num6 = val.ApplyDamageFromBehindBonus(1f, position, direction, 1f); num5 = num6.Map(1f, 2f, 1f, value); } } } if (num <= 0f) { return; } WeaponPreHitDamageableContext weaponPreHitDamageableContext = eBase.CWC.Invoke(new WeaponPreHitDamageableContext(damageable, position, direction, normal, num5, num6, falloffMod * num2, info, DamageType.Explosive)); WeaponStatContext weaponStatContext = new WeaponStatContext(num, num3, num4, weaponPreHitDamageableContext.DamageType, damageable, info, eBase.CWC.DebuffIDs); eBase.CWC.Invoke(weaponStatContext); if (!eBase.IgnoreShotMods) { num = weaponStatContext.Damage; num3 = weaponStatContext.Precision; num4 = weaponStatContext.Stagger; } if (num <= 0f) { return; } info.AddHit(weaponPreHitDamageableContext.DamageType); num = falloffMod * num + 0.001f; num *= info.ExternalDamageMod * info.InnateDamageMod; num4 *= info.InnateStaggerMod; PlayerAgent player = eBase.CWC.Owner.Player; Agent baseAgent = damageable.GetBaseAgent(); if (baseAgent != null && (int)baseAgent.Type == 0) { if ((Object)(object)baseAgent == (Object)(object)player) { if (!eBase.DamageOwner) { return; } } else if (!eBase.DamageFriendly) { return; } Dam_PlayerDamageBase val2 = ((Il2CppObjectBase)damageable.GetBaseDamagable()).Cast(); num *= val2.m_playerData.friendlyFireMulti * eBase.FriendlyDamageMulti; num *= EXPAPIWrapper.GetExplosionResistanceMod(val2.Owner); eBase.CWC.Invoke(new WeaponHitDamageableContext(num, weaponPreHitDamageableContext)); if (num != 0f) { ExplosionDamagePlayerData packetData = default(ExplosionDamagePlayerData); ((pPlayerAgent)(ref packetData.target)).Set(val2.Owner); packetData.cwc.Set(eBase.CWC); packetData.damage = num; packetData.direction.Value = blastDir; if (player != null && ((Agent)player).IsLocallyOwned) { GuiManager.CrosshairLayer.PopFriendlyTarget(); } _playerSync.Send(packetData, null, (SNet_ChannelType)4); } } else if ((Object)(object)baseAgent == (Object)null) { eBase.CWC.Invoke(new WeaponHitDamageableContext(num, weaponPreHitDamageableContext)); damageable.BulletDamage(num, (Agent)(object)player, Vector3.zero, Vector3.zero, Vector3.zero, false, 1f, 1f, 0u); } else if (flag) { Dam_EnemyDamageBase @base = val.m_base; Vector3 vec = position - @base.Owner.Position; ExplosionDamageData packet = default(ExplosionDamageData); ((pEnemyAgent)(ref packet.target)).Set(@base.Owner); packet.cwc.Set(eBase.CWC); packet.limbID = (byte)val.m_limbID; packet.damageLimb = eBase.DamageLimb; packet.localPosition.Set(vec, 10f); packet.direction.Value = blastDir; packet.staggerMult = num4; packet.setCooldowns = eBase.ApplyAttackCooldown; bool num7 = (int)val.m_type == 1; float armorMulti = (eBase.IgnoreArmor ? 1f : val.m_armorDamageMulti); DebuffManager.GetAndApplyArmorShredDebuff(ref armorMulti, damageable, eBase.CWC.DebuffIDs); float num8 = (num7 ? Math.Max(val.m_weakspotDamageMulti * num3, 1f) : 1f); float num9 = num * num8 * armorMulti * num5; if (!weaponStatContext.BypassTumorCap && (int)val.DestructionType == 1) { num9 = Math.Min(num9, val.m_healthMax + 1f); } packet.damage = num9; WeaponHitDamageableContext weaponHitDamageableContext = eBase.CWC.Invoke(new WeaponHitDamageableContext(num9, weaponPreHitDamageableContext)); bool willKill = ((Dam_SyncedDamageBase)@base).WillDamageKill(num9); HitTrackerManager.RegisterHit(eBase.CWC.Owner, eBase.CWC, weaponHitDamageableContext); ShotManager.DoHitmarker(eBase.CWC, eBase.CWC.GetContextController(), val, num9 > num, willKill, weaponHitDamageableContext.Position, armorMulti < 1f || @base.IsImortal); _sync.Send(packet, (SNet_ChannelType)4); } } internal static void Internal_ReceiveExplosionDamage(EnemyAgent target, PlayerAgent? source, OwnerType ownerType, int limbID, bool damageLimb, Vector3 localPos, Vector3 direction, float damage, float staggerMult, bool setCooldowns) { //IL_004f: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00a3: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) Dam_EnemyDamageBase damage2 = target.Damage; Dam_EnemyDamageLimb val = ((Il2CppArrayBase)(object)damage2.DamageLimbs)[limbID]; if (!(((Dam_SyncedDamageBase)damage2).Health <= 0f) && ((Agent)damage2.Owner).Alive && !damage2.IsImortal) { DamageAPI.FirePreExplosiveCallbacks(damage, target, val, source, ownerType); ES_HitreactType hitreact = (ES_HitreactType)((!(staggerMult > 0f)) ? 1 : 3); bool tryForceHitreact = false; bool flag = ((Dam_SyncedDamageBase)damage2).WillDamageKill(damage); CD_DestructionSeverity val2; if (flag) { tryForceHitreact = true; hitreact = (ES_HitreactType)4; val2 = (CD_DestructionSeverity)3; } else { val2 = (CD_DestructionSeverity)2; } EXPAPIWrapper.RegisterDamage(target, source, damage, flag); if (damageLimb && (flag || val.DoDamage(damage))) { damage2.CheckDestruction(val, ref localPos, ref direction, limbID, ref val2, ref tryForceHitreact, ref hitreact); } Vector3 position = localPos + target.Position; ProcessReceivedExplosiveDamage(damage2, damage, (Agent?)(object)source, position, direction, hitreact, tryForceHitreact, staggerMult, setCooldowns); DamageSyncWrapper.RunDamageSync(target, damageLimb ? limbID : (-1)); DamageAPI.FirePostExplosiveCallbacks(damage, target, val, source, ownerType); } } private static void ProcessReceivedExplosiveDamage(Dam_EnemyDamageBase damBase, float damage, Agent? damageSource, Vector3 position, Vector3 direction, ES_HitreactType hitreact, bool tryForceHitreact = false, float staggerDamageMulti = 1f, bool setCooldowns = true) { //IL_001a: 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_0060: 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_0088: 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_009b: 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_00a0: Unknown result type (might be due to invalid IL or missing references) EnemyAgent owner = damBase.Owner; bool num = ((Dam_SyncedDamageBase)damBase).RegisterDamage(damage); ((Agent)owner).RegisterDamageInflictor(damageSource); bool flag = false; if (num) { hitreact = (ES_HitreactType)5; flag = true; } else { damBase.m_damBuildToHitreact += damage * staggerDamageMulti; if (tryForceHitreact || damBase.m_damBuildToHitreact >= owner.EnemyBalancingData.Health.DamageUntilHitreact) { flag = true; damBase.m_damBuildToHitreact = 0f; } } owner.OnTakeCustomDamage(damage, damageSource, position, direction, hitreact, setCooldowns); if (flag && owner.Locomotion.Hitreact.CanHitreact(hitreact, tryForceHitreact)) { ImpactDirection direction2 = ES_Hitreact.GetDirection(((Component)owner).transform, direction); owner.Locomotion.Hitreact.ActivateState(hitreact, direction2, true, damageSource, position, (DamageNoiseLevel)0); } } internal static void Internal_ReceiveExplosionDamagePlayer(PlayerAgent target, PlayerAgent? source, OwnerType ownerType, float damage, Vector3 direction) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ShotManager.ReceivePlayerDamage(target, damage, PlayerDamageType.Player | PlayerDamageType.Explosive, direction); if (((Agent)target).IsLocallyOwned) { target.Sound.Post(EVENTS.BULLETHITPLAYERSYNC, true); if (ownerType.HasFlag(OwnerType.Sentry) || (Object)(object)source == (Object)null || ((Il2CppObjectBase)source).Pointer != ((Il2CppObjectBase)target).Pointer) { PlayerDialogManager.WantToStartDialog(152u, target.CharacterID, false, false); GameEventManager.PostEvent((eGameEvent)14, target, damage, "", (Dictionary)null); } } } } public struct ExplosionDamageData { public pEnemyAgent target; public pCWC cwc; public byte limbID; public bool damageLimb; public Vector3_32b localPosition; public Vector3_24b_Normalized direction; public float damage; public float staggerMult; public bool setCooldowns; } public struct ExplosionDamagePlayerData { public pPlayerAgent target; public pCWC cwc; public float damage; public Vector3_24b_Normalized direction; } } namespace EWC.CustomWeapon.Properties.Effects.Hit.Explosion.EEC_ExplosionFX { public static class ExplosionEffectPooling { private static readonly Queue _pool = new Queue(); [InvokeOnAssetLoad] private static void Initialize() { for (int i = 0; i < 30; i++) { _pool.Enqueue(CreatePoolObject()); } } private static ExplosionEffectHandler CreatePoolObject() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(); Object.DontDestroyOnLoad((Object)val); ExplosionEffectHandler result = val.AddComponent(); val.AddComponent(); val.SetActive(false); return result; } public static void TryDoEffect(ExplosionEffectData data) { if (_pool.TryDequeue(out ExplosionEffectHandler handler)) { handler.EffectDoneOnce = delegate { ((Component)handler).gameObject.SetActive(false); _pool.Enqueue(handler); }; ((Component)handler).gameObject.SetActive(true); handler.DoEffect(data); } } } public struct ExplosionEffectData { public Vector3 position; public Color flashColor; public float intensity; public float range; public float duration; public float fadeDuration; } } namespace EWC.CustomWeapon.Properties.Effects.Hit.Explosion.EEC_ExplosionFX.Handlers { internal sealed class ExplosionEffectHandler : MonoBehaviour { public Action? EffectDoneOnce; private EffectLight? _light; private Timer _timer; private bool _effectOnGoing; private float _initIntensity; private float _fadeDuration; [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } internal void DoEffect(ExplosionEffectData data) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.position = data.position; if ((Object)(object)_light == (Object)null) { _light = ((Component)this).gameObject.GetComponent(); ((LightBase)_light).Setup(); } ((LightBase)_light).UpdateVisibility(true); ((LightBase)_light).Color = data.flashColor; ((LightBase)_light).Range = data.range; ((LightBase)_light).Intensity = (_initIntensity = data.intensity); _timer.Reset(data.duration); _fadeDuration = data.fadeDuration; _effectOnGoing = true; } private void Update() { if (_effectOnGoing && _fadeDuration > 0f && (Object)(object)_light != (Object)null) { ((LightBase)_light).Intensity = _timer.PassedTime.Map(_timer.Duration - _fadeDuration, _timer.Duration, _initIntensity, 0f); } } private void FixedUpdate() { if (_effectOnGoing && _timer.TickAndCheckDone()) { OnDone(); } } private void OnDone() { if ((Object)(object)_light != (Object)null) { ((LightBase)_light).UpdateVisibility(false); } EffectDoneOnce?.Invoke(); EffectDoneOnce = null; _light = null; _effectOnGoing = false; } } public struct LazyTimer { private float _lastTickTime; private float _durationInv; public float PassedTime { get; private set; } public float Duration { get; private set; } public bool Done => Progress >= 1f; public float Progress => Math.Clamp(ProgressUnclamped, 0f, 1f); public float ProgressUnclamped { get { if (Duration != 0f) { return PassedTime * _durationInv; } return 1f; } } public LazyTimer(float duration) { PassedTime = 0f; Duration = duration; _durationInv = 1f / duration; _lastTickTime = GetTime(); } public void Reset(float newDuration = -1f) { PassedTime = 0f; if (newDuration >= 0f) { Duration = newDuration; _durationInv = 1f / newDuration; } _lastTickTime = GetTime(); } public void Tick() { float time = GetTime(); float num = time - _lastTickTime; _lastTickTime = time; PassedTime += num; } public bool TickAndCheckDone() { Tick(); return Done; } private static float GetTime() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)GameStateManager.CurrentStateName == 10) { return Clock.ExpeditionProgressionTime; } return Clock.Time; } } public struct Timer { private float _durationInv; public float PassedTime { get; private set; } public float Duration { get; private set; } public bool Done => Progress >= 1f; public float Progress => Math.Clamp(ProgressUnclamped, 0f, 1f); public float ProgressUnclamped { get { if (Duration != 0f) { return PassedTime * _durationInv; } return 1f; } } public Timer(float duration) { PassedTime = 0f; Duration = duration; _durationInv = 1f / duration; } public void Reset(float newDuration = -1f) { PassedTime = 0f; if (newDuration >= 0f) { Duration = newDuration; _durationInv = 1f / newDuration; } } public void Tick() { PassedTime += Time.deltaTime; } public void Tick(float deltaTime) { PassedTime += deltaTime; } public bool TickAndCheckDone() { Tick(); return Done; } public bool TickAndCheckDone(float deltaTime) { Tick(deltaTime); return Done; } } public struct DoubleTimer { private double _durationInv; public double PassedTime { get; private set; } public double Duration { get; private set; } public bool Done => Progress >= 1.0; public double Progress => Math.Clamp(0.0, 1.0, ProgressUnclamped); public double ProgressUnclamped { get { if (Duration != 0.0) { return PassedTime * _durationInv; } return 1.0; } } public DoubleTimer(double duration) { PassedTime = 0.0; Duration = duration; _durationInv = 1.0 / duration; } public void Reset(double newDuration = -1.0) { PassedTime = 0.0; if (newDuration >= 0.0) { Duration = newDuration; _durationInv = 1.0 / newDuration; } } public void Tick() { PassedTime += Time.deltaTime; } public bool TickAndCheckDone() { Tick(); return Done; } } } namespace EWC.CustomWeapon.Properties.Effects.Hit.DOT { public sealed class DOTController { private sealed class DOTDamageableWrapper : ObjectWrapper { private readonly IDamageable _baseDamageable; private readonly bool _hasTrans; private readonly Transform? _transform; public DOTInstance? LastInstance { get; set; } public bool Alive { get { if (_baseDamageable != null && _baseDamageable.GetHealthRel() > 0f) { return _hasTrans == ((Object)(object)_transform != (Object)null); } return false; } } public DOTDamageableWrapper(IDamageable damageable, IntPtr ptr) : base(damageable, ptr) { _baseDamageable = damageable.GetBaseDamagable(); _transform = ((Il2CppObjectBase)damageable).Cast().transform; _hasTrans = (Object)(object)_transform != (Object)null; } } private sealed class DOTComparer : IComparer { public int Compare(DOTInstance? x, DOTInstance? y) { if (x?.NextTickTime == y?.NextTickTime) { return 0; } if (x == null) { return 1; } if (y == null) { return -1; } if (!(x.NextTickTime < y.NextTickTime)) { return 1; } return -1; } } [CompilerGenerated] private sealed class d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DOTController <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Expected O, but got Unknown int num = <>1__state; DOTController dOTController = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; } dOTController._nextTickTime = float.MaxValue; dOTController.Cleanup(); int count = dOTController._activeDots.Count; foreach (KeyValuePair> item in dOTController._activeDots.ToList()) { PriorityQueue value = item.Value; IDamageable @object = item.Key.Object; while (value.Count > 0 && value.Peek().CanTick) { DOTInstance dOTInstance = value.Dequeue(); dOTInstance.DoDamage(@object); if (!dOTInstance.Expired) { value.Enqueue(dOTInstance, dOTInstance); } } if (value.Count > 0) { dOTController._nextTickTime = Math.Min(dOTController._nextTickTime, value.Peek().NextTickTime); } } if (dOTController._activeDots.Count > count) { foreach (PriorityQueue value2 in dOTController._activeDots.Values) { if (value2.Count > 0) { dOTController._nextTickTime = Math.Min(dOTController._nextTickTime, value2.Peek().NextTickTime); } } } if (dOTController._nextTickTime != float.MaxValue) { <>2__current = (object)new WaitForSeconds(dOTController._nextTickTime - Clock.Time); <>1__state = 1; return true; } dOTController._updateRoutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly Dictionary _ptrToWrapper = new Dictionary(); private readonly Dictionary> _activeDots = new Dictionary>(); private static readonly DOTComparer s_comparer = new DOTComparer(); private Coroutine? _updateRoutine; private float _nextTickTime = float.MaxValue; public void AddDOT(DOTInstance newDot, IDamageable damageable) { IntPtr pointer = ((Il2CppObjectBase)damageable).Pointer; if (!_ptrToWrapper.ContainsKey(pointer)) { DOTDamageableWrapper dOTDamageableWrapper = new DOTDamageableWrapper(damageable, pointer); _ptrToWrapper[pointer] = dOTDamageableWrapper; _activeDots[dOTDamageableWrapper] = new PriorityQueue(s_comparer); _activeDots[dOTDamageableWrapper].Enqueue(newDot, newDot); dOTDamageableWrapper.LastInstance = newDot; } else { DOTDamageableWrapper dOTDamageableWrapper2 = _ptrToWrapper[pointer]; DOTInstance? lastInstance = dOTDamageableWrapper2.LastInstance; if (lastInstance != null && lastInstance.CanAddInstance(newDot.DotBase)) { dOTDamageableWrapper2.LastInstance.AddInstance(newDot); } else { _activeDots[dOTDamageableWrapper2].Enqueue(newDot, newDot); dOTDamageableWrapper2.LastInstance = newDot; } } if (_updateRoutine == null) { _updateRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(Update()), (Action)null); } } [IteratorStateMachine(typeof(d__6))] private IEnumerator Update() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0) { <>4__this = this }; } private void Cleanup() { _activeDots.Keys.Where((DOTDamageableWrapper wrapper) => !wrapper.Alive).ToList().ForEach(delegate(DOTDamageableWrapper wrapper) { _activeDots.Remove(wrapper); _ptrToWrapper.Remove(wrapper.Pointer); }); } public void Clear() { _activeDots.Clear(); _ptrToWrapper.Clear(); CoroutineUtil.Stop(ref _updateRoutine); } } public static class DOTDamageManager { private static readonly DOTDamageEnemySync _sync = new DOTDamageEnemySync(); private static readonly DOTDamagePlayerSync _playerSync = new DOTDamagePlayerSync(); [InvokeOnAssetLoad] private static void Init() { _sync.Setup(); _playerSync.Setup(); } public static void DoDOTDamage(IDamageable damageable, float damage, float falloff, float precisionMulti, float staggerMulti, bool bypassTumor, float backstabMulti, float origBackstabMulti, int ticks, ShotInfo shotInfo, DamageOverTime dotBase) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Invalid comparison between Unknown and I4 //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Invalid comparison between Unknown and I4 //IL_03a0: Unknown result type (might be due to invalid IL or missing references) if (damage <= 0f) { return; } damage = damage * falloff + 0.001f; Agent baseAgent = damageable.GetBaseAgent(); if ((Object)(object)baseAgent != (Object)null && (int)baseAgent.Type == 0) { Dam_PlayerDamageBase val = ((Il2CppObjectBase)damageable.GetBaseDamagable()).Cast(); damage *= val.m_playerData.friendlyFireMulti * dotBase.FriendlyDamageMulti; WeaponPreHitDamageableContext weaponPreHitDamageableContext = dotBase.CWC.Invoke(new WeaponPreHitDamageableContext(damageable, damageable.DamageTargetPos, baseAgent.Position - damageable.DamageTargetPos, damageable.DamageTargetPos - baseAgent.Position, 1f, 1f, falloff, shotInfo, DamageType.DOT)); if (ApplyShotMod(ref damage, ref precisionMulti, ref staggerMulti, weaponPreHitDamageableContext, dotBase)) { dotBase.CWC.Invoke(new WeaponHitDamageableContext(damage, weaponPreHitDamageableContext)); shotInfo.AddHits(weaponPreHitDamageableContext.DamageType, ticks); DOTPlayerData dOTPlayerData = default(DOTPlayerData); dOTPlayerData.damage = damage; DOTPlayerData packetData = dOTPlayerData; ((pPlayerAgent)(ref packetData.target)).Set(val.Owner); _playerSync.Send(packetData, null, (SNet_ChannelType)4); } return; } if ((Object)(object)baseAgent == (Object)null) { WeaponPreHitDamageableContext weaponPreHitDamageableContext2 = dotBase.CWC.Invoke(new WeaponPreHitDamageableContext(damageable, damageable.DamageTargetPos, Vector3.up, Vector3.up, 1f, 1f, falloff, shotInfo, DamageType.DOT)); if (ApplyShotMod(ref damage, ref precisionMulti, ref staggerMulti, weaponPreHitDamageableContext2, dotBase)) { dotBase.CWC.Invoke(new WeaponHitDamageableContext(damage, weaponPreHitDamageableContext2)); damageable.BulletDamage(damage, (Agent)(object)dotBase.Owner, Vector3.zero, Vector3.zero, Vector3.zero, false, 1f, 1f, 0u); shotInfo.AddHits(weaponPreHitDamageableContext2.DamageType, ticks); } return; } Dam_EnemyDamageLimb val2 = ((Il2CppObjectBase)damageable).TryCast(); if ((Object)(object)val2 == (Object)null) { return; } WeaponPreHitDamageableContext context = dotBase.CWC.Invoke(new WeaponPreHitDamageableContext(damageable, val2.DamageTargetPos, baseAgent.Position - val2.DamageTargetPos, val2.DamageTargetPos - baseAgent.Position, backstabMulti, origBackstabMulti, falloff, shotInfo, DamageType.DOT)); if (ApplyShotMod(ref damage, ref precisionMulti, ref staggerMulti, context, dotBase)) { Dam_EnemyDamageBase @base = val2.m_base; DOTData packet = default(DOTData); ((pEnemyAgent)(ref packet.target)).Set(@base.Owner); packet.cwc.Set(dotBase.CWC); packet.limbID = (byte)val2.m_limbID; packet.damageLimb = dotBase.DamageLimb; packet.localPosition.Set(val2.DamageTargetPos - @base.Owner.Position, 10f); packet.staggerMult = staggerMulti; packet.setCooldowns = dotBase.ApplyAttackCooldown; bool num = (int)val2.m_type == 1; float armorMulti = (dotBase.IgnoreArmor ? 1f : val2.m_armorDamageMulti); DebuffManager.GetAndApplyArmorShredDebuff(ref armorMulti, damageable, dotBase.CWC.DebuffIDs); float num2 = (num ? Math.Max(val2.m_weakspotDamageMulti * precisionMulti, 1f) : 1f); float num3 = damage * num2 * armorMulti * backstabMulti; if (!bypassTumor && (int)val2.DestructionType == 1) { num3 = Math.Min(num3, val2.m_healthMax + 1f); } packet.damage = num3; WeaponHitDamageableContext weaponHitDamageableContext = dotBase.CWC.Invoke(new WeaponHitDamageableContext(num3, context)); bool flag = ((Dam_SyncedDamageBase)@base).WillDamageKill(num3); HitTrackerManager.RegisterHit(dotBase.CWC.Owner, dotBase.CWC, weaponHitDamageableContext); if (flag || dotBase.ShouldDoHitmarker(damageable)) { ShotManager.DoHitmarker(dotBase.CWC, dotBase.CWC.GetContextController(), val2, num3 > damage, flag, weaponHitDamageableContext.Position, armorMulti < 1f || @base.IsImortal); } shotInfo.AddHits(weaponHitDamageableContext.DamageType, ticks); _sync.Send(packet, (SNet_ChannelType)4); } } private static bool ApplyShotMod(ref float damage, ref float precisionMulti, ref float staggerMulti, WeaponPreHitDamageableContext context, DamageOverTime dotBase) { if (!dotBase.CalcShotModsPerTick || dotBase.IgnoreShotMods) { return true; } WeaponStatContext weaponStatContext = new WeaponStatContext(damage, precisionMulti, staggerMulti, context.DamageType, context.Damageable, context.ShotInfo.Orig, dotBase.CWC.DebuffIDs); dotBase.CWC.Invoke(weaponStatContext); damage = weaponStatContext.Damage; precisionMulti = weaponStatContext.Precision; staggerMulti = weaponStatContext.Stagger; return damage > 0f; } public static void Internal_ReceiveDOTDamagePlayer(PlayerAgent target, float damage) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ShotManager.ReceivePlayerDamage(target, damage, PlayerDamageType.DOT, Vector3.zero, cameraShake: false); } internal static void Internal_ReceiveDOTDamageEnemy(EnemyAgent target, PlayerAgent? source, OwnerType ownerType, int limbID, bool damageLimb, Vector3 localPos, float damage, float staggerMult, bool setCooldowns) { //IL_0057: 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_006b: 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_0080: 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_0091: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) Dam_EnemyDamageBase damage2 = target.Damage; Dam_EnemyDamageLimb val = ((Il2CppArrayBase)(object)damage2.DamageLimbs)[limbID]; if (!((Agent)target).Alive || damage2.IsImortal) { return; } DamageAPI.FirePreDOTCallbacks(damage, target, val, source, ownerType); ES_HitreactType hitreact = (ES_HitreactType)((!(damage * staggerMult + damage2.m_damBuildToHitreact >= target.EnemyBalancingData.Health.DamageUntilHitreact)) ? 1 : 3); bool tryForceHitreact = false; bool flag = ((Dam_SyncedDamageBase)damage2).WillDamageKill(damage); CD_DestructionSeverity val2; if (flag) { tryForceHitreact = true; hitreact = (ES_HitreactType)4; val2 = (CD_DestructionSeverity)3; } else { val2 = (CD_DestructionSeverity)2; } EXPAPIWrapper.RegisterDamage(target, source, damage, flag); Vector3 direction = ((Agent)target).TargetLookDir * -1f; Vector3 position = localPos + target.Position; if (damageLimb) { if (!flag && !val.DoDamage(damage)) { target.AI.m_behaviour.SignalEvent((Event)1, (Object)(object)val); } else { damage2.CheckDestruction(val, ref localPos, ref direction, limbID, ref val2, ref tryForceHitreact, ref hitreact); } } ProcessReceivedDOTDamage(damage2, damage, (Agent?)(object)source, position, direction, hitreact, tryForceHitreact, staggerMult, setCooldowns); DamageSyncWrapper.RunDamageSync(target, damageLimb ? limbID : (-1)); DamageAPI.FirePostDOTCallbacks(damage, target, val, source, ownerType); } private static void ProcessReceivedDOTDamage(Dam_EnemyDamageBase damBase, float damage, Agent? damageSource, Vector3 position, Vector3 direction, ES_HitreactType hitreact, bool tryForceHitreact = false, float staggerDamageMulti = 1f, bool setCooldowns = true) { //IL_001a: 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_0060: 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_0088: 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_009b: 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_00a0: Unknown result type (might be due to invalid IL or missing references) EnemyAgent owner = damBase.Owner; bool num = ((Dam_SyncedDamageBase)damBase).RegisterDamage(damage); ((Agent)owner).RegisterDamageInflictor(damageSource); bool flag = false; if (num) { hitreact = (ES_HitreactType)5; flag = true; } else { damBase.m_damBuildToHitreact += damage * staggerDamageMulti; if (tryForceHitreact || damBase.m_damBuildToHitreact >= owner.EnemyBalancingData.Health.DamageUntilHitreact) { flag = true; damBase.m_damBuildToHitreact = 0f; } } owner.OnTakeCustomDamage(damage, damageSource, position, direction, hitreact, setCooldowns); if (flag && owner.Locomotion.Hitreact.CanHitreact(hitreact, tryForceHitreact)) { ImpactDirection direction2 = ES_Hitreact.GetDirection(((Component)owner).transform, direction); owner.Locomotion.Hitreact.ActivateState(hitreact, direction2, true, damageSource, position, (DamageNoiseLevel)0); } } } public struct DOTData { public pEnemyAgent target; public pCWC cwc; public byte limbID; public bool damageLimb; public Vector3_32b localPosition; public float damage; public float staggerMult; public bool setCooldowns; } public struct DOTPlayerData { public pPlayerAgent target; public float damage; } internal sealed class DOTDamageEnemySync : SyncedEventMasterOnly { public override string GUID => "DOT"; protected override void Receive(DOTData packet) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) EnemyAgent target = default(EnemyAgent); if (((pEnemyAgent)(ref packet.target)).TryGet(ref target)) { packet.cwc.TryGetSource(out PlayerAgent comp); DOTDamageManager.Internal_ReceiveDOTDamageEnemy(target, comp, packet.cwc.ownerType, packet.limbID, packet.damageLimb, packet.localPosition.Get(10f), packet.damage, packet.staggerMult, packet.setCooldowns); } } } internal sealed class DOTDamagePlayerSync : SyncedEvent { public override string GUID => "DOTP"; protected override void Receive(DOTPlayerData packet) { PlayerAgent target = default(PlayerAgent); if (((pPlayerAgent)(ref packet.target)).TryGet(ref target)) { DOTDamageManager.Internal_ReceiveDOTDamagePlayer(target, packet.damage); } } protected override void ReceiveLocal(DOTPlayerData packet) { Receive(packet); } } public static class DOTGlowPooling { private static readonly Queue _pool = new Queue(); private static readonly Dictionary> _activeHandlers = new Dictionary>(); private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; [InvokeOnAssetLoad] private static void Initialize() { for (int i = 0; i < 30; i++) { _pool.Enqueue(CreatePoolObject()); } } [InvokeOnCleanup(true)] private static void Reset() { _activeHandlers.Clear(); } private static DOTGlowHandler CreatePoolObject() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(); Object.DontDestroyOnLoad((Object)val); DOTGlowHandler result = val.AddComponent(); val.AddComponent(); val.SetActive(false); return result; } public static void TryDoEffect(DamageOverTime data, IDamageable damBase, Transform target, float mod) { DamageOverTime data2 = data; TempWrapper.Set(damBase); if (_activeHandlers.TryGetValue(data2, out Dictionary value)) { if (value.TryGetValue(TempWrapper, out var value2)) { value2.AddInstance(mod); return; } } else { _activeHandlers.Add(data2, new Dictionary()); } if (!_pool.TryDequeue(out DOTGlowHandler handler)) { return; } BaseDamageableWrapper wrapper = new BaseDamageableWrapper(TempWrapper); _activeHandlers[data2].Add(wrapper, handler); handler.EffectDoneOnce = delegate { ((Component)handler).gameObject.SetActive(false); _pool.Enqueue(handler); if (_activeHandlers.TryGetValue(data2, out Dictionary value3)) { value3.Remove(wrapper); } }; ((Component)handler).gameObject.SetActive(true); handler.DoEffect(data2, damBase, target, mod); } public static void TryEndEffect(DamageOverTime data) { if (!_activeHandlers.TryGetValue(data, out Dictionary value)) { return; } foreach (DOTGlowHandler value2 in value.Values) { value2.ForceEnd(); } } } public sealed class DOTInstance { private int _tick; private float _damagePerTick; private float _lastTickTime; private readonly int _totalTicks; private readonly float _totalDamage; private readonly float _precisionMulti; private readonly float _staggerMulti; private readonly bool _bypassTumor; private readonly float _backstabMulti; private readonly float _origBackstabMulti; private readonly float _falloff; private readonly float _tickDelay; private readonly ShotInfo _shotInfo; private readonly float _expoPlusOne; private readonly double _expoModifier; private readonly double _expoDivisor; public DamageOverTime DotBase { get; } public bool Expired => _tick >= _totalTicks; public bool CanTick => Clock.Time - _lastTickTime >= _tickDelay; public float NextTickTime => _lastTickTime + _tickDelay; public bool Started => _tick != 0; public DOTInstance(float totalDamage, float falloff, float precision, float stagger, bool bypassTumor, float backstab, float origBackstab, ShotInfo info, DamageOverTime dotBase) { DotBase = dotBase; _totalDamage = totalDamage; _precisionMulti = precision; _staggerMulti = stagger; _bypassTumor = bypassTumor; _backstabMulti = backstab; _origBackstabMulti = origBackstab; _falloff = falloff; _tickDelay = 1f / dotBase.TickRate; _lastTickTime = Clock.Time; _totalTicks = (int)(dotBase.Duration * dotBase.TickRate); _shotInfo = info; _expoPlusOne = dotBase.Exponent + 1f; _expoModifier = _expoPlusOne / ((dotBase.EndDamageFrac * dotBase.Exponent + 1f) * (float)_totalTicks); _expoDivisor = (double)_expoPlusOne * Math.Pow(_totalTicks, dotBase.Exponent); AddInstance(this); } public bool CanAddInstance(DamageOverTime dotBase) { if (DotBase.BatchStacks && DotBase.StackLimit == 0 && DotBase == dotBase) { return !Started; } return false; } public void AddInstance(DOTInstance instance) { _damagePerTick += (float)((double)instance._totalDamage * _expoModifier); } public void StartWithTargetTime(float nextTickTime) { _lastTickTime = nextTickTime - _tickDelay; } public void Destroy() { _tick = _totalTicks; } private double ComputeDamageMod(int tick) { return (double)(DotBase.EndDamageFrac * (float)tick) + (double)(DotBase.EndDamageFrac - 1f) * Math.Pow(_totalTicks - tick, _expoPlusOne) / _expoDivisor; } public float GetRemainingDamage() { return (float)((double)_damagePerTick * (ComputeDamageMod(_totalTicks) - ComputeDamageMod(_tick))); } public void DoDamage(IDamageable damageable) { if (!CanTick || Expired) { return; } int num = Math.Min(_totalTicks - _tick, (int)((Clock.Time - _lastTickTime) * DotBase.TickRate)); float damage = ((DotBase.EndDamageFrac != 1f) ? ((float)((double)_damagePerTick * (ComputeDamageMod(_tick + num) - ComputeDamageMod(_tick)))) : (_damagePerTick * (float)num)); _lastTickTime += (float)num * _tickDelay; _tick += num; try { DOTDamageManager.DoDOTDamage(damageable, damage, _falloff, _precisionMulti, _staggerMulti, _bypassTumor, _backstabMulti, _origBackstabMulti, num, _shotInfo, DotBase); } catch (Exception value) { EWCLogger.Log($"DOT: Error when doing damage: {value}"); Destroy(); } } } } namespace EWC.CustomWeapon.Properties.Effects.Hit.DOT.DOTGlowFX { internal sealed class DOTGlowHandler : MonoBehaviour { public Action? EffectDoneOnce; private EffectLight? _light; private bool _effectOnGoing; private readonly Queue<(float intensity, float endTime)> _endTimes = new Queue<(float, float)>(); private DamageOverTime? _data; private IDamageable? _damBase; private Transform? _targetTransform; private Vector3 _targetPos; private Vector3 TargetPosition { get { //IL_001c: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_targetTransform != (Object)null)) { return _targetPos; } return _targetPos = _targetTransform.position; } } [InvokeOnLoad] private static void Init() { ClassInjector.RegisterTypeInIl2Cpp(); } [HideFromIl2Cpp] internal void DoEffect(DamageOverTime data, IDamageable damBase, Transform target, float mod) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) _data = data; _damBase = damBase; _targetTransform = target; ((Component)this).transform.position = TargetPosition; if ((Object)(object)_light == (Object)null) { _light = ((Component)this).gameObject.GetComponent(); ((LightBase)_light).Setup(); } ((LightBase)_light).UpdateVisibility(true); ((LightBase)_light).Color = data.GlowColor; ((LightBase)_light).Range = data.GlowRange; AddInstance(mod); _effectOnGoing = true; } internal void AddInstance(float mod) { float num = _data.GlowIntensity * mod; EffectLight? light = _light; ((LightBase)light).Intensity = ((LightBase)light).Intensity + num; _endTimes.Enqueue((num, _data.Duration + Clock.Time)); if (_data.StackLimit != 0 && _endTimes.Count > _data.StackLimit) { num = _endTimes.Dequeue().intensity; EffectLight? light2 = _light; ((LightBase)light2).Intensity = ((LightBase)light2).Intensity - num; } } internal void ForceEnd() { OnDone(); } private void Update() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (_damBase == null || _damBase.GetHealthRel() <= 0f) { OnDone(); } else { ((Component)this).transform.position = TargetPosition; } } private void FixedUpdate() { (float, float) result; while (_endTimes.TryPeek(out result) && Clock.Time >= result.Item2) { EffectLight? light = _light; ((LightBase)light).Intensity = ((LightBase)light).Intensity - result.Item1; _endTimes.Dequeue(); } if (_effectOnGoing && _endTimes.Count == 0) { OnDone(); } } private void OnDone() { if ((Object)(object)_light != (Object)null) { ((LightBase)_light).UpdateVisibility(false); } EffectDoneOnce?.Invoke(); _endTimes.Clear(); EffectDoneOnce = null; _light = null; _effectOnGoing = false; } } } namespace EWC.CustomWeapon.Properties.Effects.Hit.CustomFoam { public static class FoamActionManager { private static readonly FoamStaticSync _staticSync = new FoamStaticSync(); private static readonly FoamEnemySync _enemySync = new FoamEnemySync(); private static readonly FoamDoorSync _doorSync = new FoamDoorSync(); private static readonly FoamDirectSync _directSync = new FoamDirectSync(); private static readonly FoamSync _foamSync = new FoamSync(); private static readonly FoamActivateSync _activateSync = new FoamActivateSync(); private static readonly FoamBubbleSync _bubbleSync = new FoamBubbleSync(); public const float MaxVolumeMod = 256f; public const float MaxDirect = 100f; public const float MaxFoam = 32f; public const float MaxTime = 32f; [InvokeOnAssetLoad] private static void Init() { _staticSync.Setup(); _enemySync.Setup(); _doorSync.Setup(); _directSync.Setup(); _foamSync.Setup(); _activateSync.Setup(); _bubbleSync.Setup(); } public static void FoamEnemy(GameObject go, PlayerAgent? source, Vector3 pos, float volumeMod, Foam property) { //IL_00a3: 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) //IL_0065: 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) IGlueTarget component = go.GetComponent(); if (component != null && !((Object)(object)component.GlueTargetEnemyAgent == (Object)null)) { if ((Object)(object)component.GlueTargetEnemyAgent != (Object)null) { FoamEnemyData packet = default(FoamEnemyData); ((pEnemyAgent)(ref packet.target)).Set(component.GlueTargetEnemyAgent); packet.limbID = (byte)component.GlueTargetSubIndex; ((pPlayerAgent)(ref packet.source)).Set(source); packet.localPosition = component.GlueTargetTransform.InverseTransformPoint(pos); packet.volumeMod.Set(volumeMod + 0.001f, 256f); packet.propertyID = property.SyncPropertyID; _enemySync.Send(packet, (SNet_ChannelType)4); } else { FoamStatic(source, pos, volumeMod, property); } } } internal static void Internal_ReceiveFoamEnemy(FoamEnemyData packet) { //IL_0001: 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) //IL_0041: Unknown result type (might be due to invalid IL or missing references) EnemyAgent val = default(EnemyAgent); if (TrySpawnNewFoam(packet.source, packet.volumeMod, packet.propertyID, out GlueGunProjectile projectile) && ((pEnemyAgent)(ref packet.target)).TryGet(ref val)) { ProjectileManager.WantToSpawnGlueOnEnemyAgent(projectile.SyncID, val, (int)packet.limbID, packet.localPosition, projectile.m_volumeDesc, projectile.EffectMultiplier); } } public static void FoamDoor(GameObject go, PlayerAgent? source, Vector3 pos, float volumeMod, Foam property) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) IGlueTarget component = go.GetComponent(); if (component != null) { FoamDoorData packet = default(FoamDoorData); packet.door = component.GlueTargetDoorSyncStruct; packet.glueTarget = component.GlueTargetSubIndex; ((pPlayerAgent)(ref packet.source)).Set(source); packet.localPosition = component.GlueTargetTransform.InverseTransformPoint(pos); packet.volumeMod.Set(volumeMod + 0.001f, 256f); packet.propertyID = property.SyncPropertyID; _doorSync.Send(packet, (SNet_ChannelType)4); } } internal static void Internal_ReceiveFoamDoor(FoamDoorData packet) { //IL_0001: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (TrySpawnNewFoam(packet.source, packet.volumeMod, packet.propertyID, out GlueGunProjectile projectile)) { ProjectileManager.WantToSpawnGlueOnDoor(projectile.SyncID, packet.door, packet.glueTarget, packet.localPosition, projectile.m_volumeDesc); } } public static void FoamStatic(PlayerAgent? source, Vector3 pos, float volumeMod, Foam property) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) FoamStaticData packet = default(FoamStaticData); ((pPlayerAgent)(ref packet.source)).Set(source); packet.position = pos; packet.volumeMod.Set(volumeMod + 0.001f, 256f); packet.propertyID = property.SyncPropertyID; _staticSync.Send(packet, (SNet_ChannelType)4); } internal static void Internal_ReceiveFoamStatic(FoamStaticData packet) { //IL_0001: 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_002a: Unknown result type (might be due to invalid IL or missing references) if (TrySpawnNewFoam(packet.source, packet.volumeMod, packet.propertyID, out GlueGunProjectile projectile)) { ProjectileManager.WantToSpawnStaticGlue(projectile.SyncID, packet.position, projectile.m_volumeDesc); } } private static bool TrySpawnNewFoam(pPlayerAgent owner, UFloat16b volumeMod, ushort propertyID, [MaybeNullWhen(false)] out GlueGunProjectile projectile, uint syncID = 0u) { projectile = null; PlayerAgent owner2 = default(PlayerAgent); if (!((pPlayerAgent)(ref owner)).TryGet(ref owner2) || !CustomDataManager.TryGetSyncProperty(propertyID, out var property)) { return false; } projectile = SpawnNewFoam(owner2, volumeMod.Get(256f), property, syncID); return true; } private static GlueGunProjectile SpawnNewFoam(PlayerAgent? owner, float volumeMod, Foam property, uint syncID = 0u) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (syncID == 0) { syncID = ProjectileManager.GetNextSyncID(); } GlueGunProjectile obj = ProjectileManager.Current.SpawnGlueGunProjectileIfNeeded(syncID, default(Vector3), false); float bubbleStrength = property.BubbleStrength; bubbleStrength *= (property.IgnoreBooster ? 1f : AgentModifierManager.ApplyModifier((Agent)(object)owner, (AgentModifier)100, 1f)); obj.m_glueStrengthMultiplier = bubbleStrength; GlueVolumeDesc volumeDesc = obj.m_volumeDesc; volumeDesc.expandVolume = property.BubbleAmount * volumeMod; obj.m_volumeDesc = volumeDesc; obj.m_expandSpeed = property.BubbleExpandSpeed * volumeMod; obj.m_owner = owner ?? ((Il2CppObjectBase)SNet.Master.PlayerAgent).Cast(); obj.m_allowSplat = false; FoamManager.AddFoamBubble(obj, property); FoamBubbleSync(owner, syncID, volumeMod, property); return obj; } public static void FoamDirect(EnemyAgent enemy, float amount, Foam property) { FoamDirectData packet = default(FoamDirectData); ((pEnemyAgent)(ref packet.target)).Set(enemy); packet.amount.Set(amount + 0.001f, 100f); packet.propertyID = property.SyncPropertyID; _directSync.Send(packet, (SNet_ChannelType)4); } internal static void Internal_ReceiveFoamDirect(FoamDirectData packet) { EnemyAgent val = default(EnemyAgent); if (((pEnemyAgent)(ref packet.target)).TryGet(ref val) && CustomDataManager.TryGetSyncProperty(packet.propertyID, out var property)) { FoamManager.AddFoam(val.Damage, packet.amount.Get(100f), property); } } public static void FoamSync(EnemyAgent enemy, float amountRel, float timeRel) { if (SNet.IsMaster) { FoamSyncData packetData = default(FoamSyncData); ((pEnemyAgent)(ref packetData.target)).Set(enemy); packetData.amount.Set(amountRel, 32f); packetData.time.Set(timeRel, 32f); _foamSync.Send(packetData, null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveFoamSync(FoamSyncData packet) { EnemyAgent val = default(EnemyAgent); if (((pEnemyAgent)(ref packet.target)).TryGet(ref val)) { FoamManager.ReceiveSyncFoam(val.Damage, packet.amount.Get(32f), packet.time.Get(32f)); } } public static void FoamActivateSync(EnemyAgent enemy, float amountRel, float timeRel, byte animIndex, bool fromHibernate) { if (SNet.IsMaster) { FoamSyncData syncData = default(FoamSyncData); ((pEnemyAgent)(ref syncData.target)).Set(enemy); syncData.amount.Set(amountRel, 32f); syncData.time.Set(timeRel, 32f); FoamActivateSyncData packetData = default(FoamActivateSyncData); packetData.syncData = syncData; packetData.animIndex = animIndex; packetData.fromHibernate = fromHibernate; _activateSync.Send(packetData, null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveFoamActivateSync(FoamActivateSyncData packet) { EnemyAgent val = default(EnemyAgent); if (((pEnemyAgent)(ref packet.syncData.target)).TryGet(ref val)) { FoamManager.ReceiveActivateSyncFoam(val.Damage, packet.syncData.amount.Get(32f), packet.syncData.time.Get(32f), packet.animIndex, packet.fromHibernate); } } public static void FoamBubbleSync(PlayerAgent? owner, uint syncID, float volumeMod, Foam property) { if (SNet.IsMaster) { FoamBubbleSyncData foamBubbleSyncData = default(FoamBubbleSyncData); foamBubbleSyncData.syncID = syncID; foamBubbleSyncData.propertyID = property.SyncPropertyID; FoamBubbleSyncData packetData = foamBubbleSyncData; ((pPlayerAgent)(ref packetData.source)).Set(owner); packetData.volumeMod.Set(volumeMod, 256f); _bubbleSync.Send(packetData, null, (SNet_ChannelType)4); } } internal static void Internal_ReceiveBubbleSync(FoamBubbleSyncData packet) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) TrySpawnNewFoam(packet.source, packet.volumeMod, packet.propertyID, out GlueGunProjectile _, packet.syncID); } } public struct FoamEnemyData { public pEnemyAgent target; public byte limbID; public pPlayerAgent source; public Vector3 localPosition; public UFloat16b volumeMod; public ushort propertyID; } public struct FoamStaticData { public pPlayerAgent source; public Vector3 position; public UFloat16b volumeMod; public ushort propertyID; } public struct FoamDoorData { public pStateReplicatorProvider door; public int glueTarget; public pPlayerAgent source; public Vector3 localPosition; public UFloat16b volumeMod; public ushort propertyID; } public struct FoamDirectData { public pEnemyAgent target; public UFloat16b amount; public ushort propertyID; } public struct FoamSyncData { public pEnemyAgent target; public UFloat16b amount; public UFloat16b time; } public struct FoamActivateSyncData { public FoamSyncData syncData; public byte animIndex; public bool fromHibernate; } public struct FoamBubbleSyncData { public pPlayerAgent source; public uint syncID; public UFloat16b volumeMod; public ushort propertyID; } internal sealed class FoamEnemySync : SyncedEventMasterOnly { public override string GUID => "FMENMY"; protected override void Receive(FoamEnemyData packet) { FoamActionManager.Internal_ReceiveFoamEnemy(packet); } } internal sealed class FoamStaticSync : SyncedEventMasterOnly { public override string GUID => "FMSTAT"; protected override void Receive(FoamStaticData packet) { FoamActionManager.Internal_ReceiveFoamStatic(packet); } } internal sealed class FoamDoorSync : SyncedEventMasterOnly { public override string GUID => "FMDOOR"; protected override void Receive(FoamDoorData packet) { FoamActionManager.Internal_ReceiveFoamDoor(packet); } } internal sealed class FoamDirectSync : SyncedEventMasterOnly { public override string GUID => "FMDRCT"; protected override void Receive(FoamDirectData packet) { FoamActionManager.Internal_ReceiveFoamDirect(packet); } } internal sealed class FoamSync : SyncedEvent { public override string GUID => "FMSYNC"; protected override void Receive(FoamSyncData packet) { FoamActionManager.Internal_ReceiveFoamSync(packet); } } internal sealed class FoamActivateSync : SyncedEvent { public override string GUID => "FMASYN"; protected override void Receive(FoamActivateSyncData packet) { FoamActionManager.Internal_ReceiveFoamActivateSync(packet); } } internal sealed class FoamBubbleSync : SyncedEvent { public override string GUID => "FMBSYN"; protected override void Receive(FoamBubbleSyncData packet) { FoamActionManager.Internal_ReceiveBubbleSync(packet); } } public sealed class FoamManager { private class FoamTimeHandler { private float _totalAmount; private float _totalTime; private bool _unfoam; private float _lastUpdateTime; public readonly Dam_EnemyDamageBase DamBase; private readonly ES_StuckInGlue _stuckInGlue; private readonly float _tolerance; private readonly float _foamTime; private float UnfoamAmount => Math.Min((_totalTime / _foamTime + 0.1f) * _tolerance, _tolerance); public FoamTimeHandler(Dam_EnemyDamageBase damBase) { DamBase = damBase; _stuckInGlue = DamBase.Owner.Locomotion.StuckInGlue; EnemyBalancingDataBlock enemyBalancingData = damBase.Owner.EnemyBalancingData; _tolerance = enemyBalancingData.GlueTolerance; _foamTime = enemyBalancingData.GlueFadeOutTime * 0.9f; } public bool Update() { if (!_unfoam) { return false; } float num = Time.time - _lastUpdateTime; _totalTime = Math.Max(0f, _totalTime - num); if (_totalTime == 0f) { DamBase.m_attachedGlueVolume = 0f; _totalAmount = 0f; _unfoam = false; SendSyncFoam(); } else { _totalAmount = UnfoamAmount; DamBase.m_attachedGlueVolume = _totalAmount; } _lastUpdateTime = Time.time; return _unfoam; } public bool AddFoam(float amount, Foam? property = null) { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Invalid comparison between Unknown and I4 //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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 (DamBase.IsImortal) { return false; } float num = property?.GetMaxFoamTime(_foamTime) ?? _foamTime; if (_unfoam && Update()) { if (_totalTime < num) { _totalTime = Math.Min(num, _totalTime + amount / _tolerance * num); } _totalAmount = UnfoamAmount; FixFoamVisual(); SendSyncFoam(); return false; } if (_totalAmount + amount >= _tolerance) { _totalTime += (_tolerance - _totalAmount) / _tolerance * num; _totalAmount = _tolerance; _unfoam = true; if (SNet.IsMaster) { if (!DamBase.IsStuckInGlue) { pES_EnemyStuckInGlueData val = default(pES_EnemyStuckInGlueData); int lastAnimIndex = _stuckInGlue.m_lastAnimIndex; val.AnimIndex = (byte)((ES_Base)_stuckInGlue).m_locomotion.GetUniqueAnimIndex(EnemyLocomotion.s_hashScreams, ref lastAnimIndex); val.FromHibernate = (int)((ES_Base)_stuckInGlue).m_locomotion.CurrentStateEnum == 14; _stuckInGlue.m_lastAnimIndex = lastAnimIndex; _stuckInGlue.m_stuckInGlueData = val; _stuckInGlue.DoStartStuckInGlue((int)val.AnimIndex, val.FromHibernate); } FixFoamVisual(); SendActivateSyncFoam(); } _lastUpdateTime = Time.time; } else { _totalTime += amount / _tolerance * num; _totalAmount += amount; SendSyncFoam(); } DamBase.m_attachedGlueVolume = _totalAmount; return _unfoam; } internal void ReceiveSyncFoam(float amountRel, float timeRel) { _totalAmount = amountRel * _tolerance; _totalTime = timeRel * _foamTime; if (_unfoam) { DamBase.m_attachedGlueVolume = UnfoamAmount; FixFoamVisual(); _lastUpdateTime = Time.time; } else { DamBase.m_attachedGlueVolume = amountRel * _tolerance; } } internal bool ReceiveActivateSyncFoam(float amountRel, float timeRel, byte animIndex, bool fromHibernate) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 ReceiveSyncFoam(amountRel, timeRel); bool result = !_unfoam; _unfoam = true; DamBase.m_attachedGlueVolume = UnfoamAmount; if (!DamBase.IsStuckInGlue || (int)DamBase.Owner.Locomotion.CurrentStateEnum != 17) { _stuckInGlue.DoStartStuckInGlue((int)animIndex, fromHibernate); } FixFoamVisual(); _lastUpdateTime = Time.time; return result; } private void SendSyncFoam() { FoamActionManager.FoamSync(DamBase.Owner, _totalAmount / _tolerance, _totalTime / _foamTime); } private void SendActivateSyncFoam() { //IL_002b: 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) FoamActionManager.FoamActivateSync(DamBase.Owner, _totalAmount / _tolerance, _totalTime / _foamTime, _stuckInGlue.m_stuckInGlueData.AnimIndex, _stuckInGlue.m_stuckInGlueData.FromHibernate); } private void FixFoamVisual() { float num = (_totalTime - _stuckInGlue.m_fadeInDuration) * 1.6f; _stuckInGlue.m_fadeOutDuration = num; _stuckInGlue.m_fadeOutTimer = _stuckInGlue.m_fadeInTimer; if (Clock.Time > _stuckInGlue.m_fadeOutTimer) { _stuckInGlue.m_glueFadeOutTriggered = true; EnemyAppearance appearance = DamBase.Owner.Appearance; appearance.m_lastGlueEnd = 1f; appearance.SetGlueAmount(0f, num); } } } [CompilerGenerated] private sealed class d__20 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public FoamManager <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; FoamManager foamManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (foamManager._unfoamHandlers.Count > 0) { LinkedListNode first = foamManager._unfoamHandlers.First; for (LinkedListNode linkedListNode = first; linkedListNode != null; linkedListNode = first) { FoamTimeHandler value = linkedListNode.Value; first = linkedListNode.Next; if ((Object)(object)value.DamBase == (Object)null || ((Dam_SyncedDamageBase)value.DamBase).Health <= 0f || !value.Update()) { foamManager._unfoamHandlers.Remove(linkedListNode); } } <>2__current = null; <>1__state = 1; return true; } foamManager._updateRoutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__21 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public FoamManager <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; FoamManager foamManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (foamManager._bubbleExpireTimes.Count > 0) { float time = Clock.Time; ObjectWrapper element; float priority; while (foamManager._bubbleExpireTimes.TryPeek(out element, out priority) && priority < time) { if ((Object)(object)element.Object != (Object)null) { ProjectileManager.WantToDestroyGlue(element.Object.SyncID); } foamManager._bubbleExpireTimes.Dequeue(); } <>2__current = null; <>1__state = 1; return true; } foamManager._expireRoutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly FoamManager Current = new FoamManager(); private readonly Dictionary, FoamTimeHandler> _foamTimes = new Dictionary, FoamTimeHandler>(); private readonly Dictionary, Foam> _customFoams = new Dictionary, Foam>(); private readonly PriorityQueue, float> _bubbleExpireTimes = new PriorityQueue, float>(); private readonly LinkedList _unfoamHandlers = new LinkedList(); private Coroutine? _updateRoutine; private Coroutine? _expireRoutine; private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; private static ObjectWrapper ProjTempWrapper => ObjectWrapper.SharedInstance; public static void AddFoamBubble(GlueGunProjectile proj, Foam property) { Current.CleanupBubbles(); ObjectWrapper objectWrapper = new ObjectWrapper(proj); Current._customFoams[objectWrapper] = property; if (property.BubbleLifetime > 0f) { Current.AddExpiringBubble(objectWrapper, property.BubbleLifetime); } } public static Foam? GetProjProperty(GlueGunProjectile? proj) { if (!((Object)(object)proj != (Object)null)) { return null; } return Current._customFoams.GetValueOrDefault(ProjTempWrapper.Set(proj)); } public static void AddFoam(Dam_EnemyDamageBase damBase, float amount, Foam? property = null) { if (!Current._foamTimes.TryGetValue(TempWrapper.Set(damBase), out FoamTimeHandler value)) { Current.CleanupFoam(); FoamTimeHandler foamTimeHandler2 = (Current._foamTimes[new BaseDamageableWrapper(TempWrapper)] = new FoamTimeHandler(damBase)); value = foamTimeHandler2; } if (value.AddFoam(amount, property)) { Current.AddUnfoamHandler(value); } } internal static void ReceiveSyncFoam(Dam_EnemyDamageBase damBase, float amountRel, float timeRel) { if (!Current._foamTimes.TryGetValue(TempWrapper.Set(damBase), out FoamTimeHandler value)) { Current.CleanupFoam(); FoamTimeHandler foamTimeHandler2 = (Current._foamTimes[new BaseDamageableWrapper(TempWrapper)] = new FoamTimeHandler(damBase)); value = foamTimeHandler2; } value.ReceiveSyncFoam(amountRel, timeRel); } internal static void ReceiveActivateSyncFoam(Dam_EnemyDamageBase damBase, float amountRel, float timeRel, byte animIndex, bool fromHibernate) { if (!Current._foamTimes.TryGetValue(TempWrapper.Set(damBase), out FoamTimeHandler value)) { Current.CleanupFoam(); FoamTimeHandler foamTimeHandler2 = (Current._foamTimes[new BaseDamageableWrapper(TempWrapper)] = new FoamTimeHandler(damBase)); value = foamTimeHandler2; } if (value.ReceiveActivateSyncFoam(amountRel, timeRel, animIndex, fromHibernate)) { Current.AddUnfoamHandler(value); } } private void CleanupFoam() { _foamTimes.Keys.Where((BaseDamageableWrapper wrapper) => !wrapper.Alive).ToList().ForEach(delegate(BaseDamageableWrapper wrapper) { FoamTimeHandler value = _foamTimes[wrapper]; _foamTimes.Remove(wrapper); _unfoamHandlers.Remove(value); }); if ((float)_unfoamHandlers.Count == 0f) { CoroutineUtil.Stop(ref _updateRoutine); } } private void CleanupBubbles() { _customFoams.Keys.Where((ObjectWrapper wrapper) => (Object)(object)wrapper.Object == (Object)null).ToList().ForEach(delegate(ObjectWrapper wrapper) { _customFoams.Remove(wrapper); }); if ((float)_customFoams.Count == 0f && CoroutineUtil.Stop(ref _expireRoutine)) { _bubbleExpireTimes.Clear(); } } private void AddUnfoamHandler(FoamTimeHandler handler) { _unfoamHandlers.AddLast(handler); if (_updateRoutine == null) { _updateRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(Update()), (Action)null); } } private void AddExpiringBubble(ObjectWrapper wrapper, float lifetime) { if (SNet.IsMaster) { _bubbleExpireTimes.Enqueue(wrapper, Clock.Time + lifetime); if (_expireRoutine == null) { _expireRoutine = CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(UpdateExpiring()), (Action)null); } } } [IteratorStateMachine(typeof(d__20))] private IEnumerator Update() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__20(0) { <>4__this = this }; } [IteratorStateMachine(typeof(d__21))] private IEnumerator UpdateExpiring() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__21(0) { <>4__this = this }; } } } namespace EWC.CustomWeapon.ObjectWrappers { public class BaseDamageableWrapper : ObjectWrapper { public new static readonly BaseDamageableWrapper SharedInstance = new BaseDamageableWrapper(null, IntPtr.Zero); public bool Alive { get { if (base.Object != null) { return base.Object.GetHealthRel() > 0f; } return false; } } public BaseDamageableWrapper(BaseDamageableWrapper wrapper) : base((ObjectWrapper)wrapper) { } public BaseDamageableWrapper(IDamageable? obj, IntPtr ptr) : base((obj != null) ? obj.GetBaseDamagable() : null, ptr) { } public BaseDamageableWrapper(IDamageable obj) : base(obj.GetBaseDamagable()) { } public override BaseDamageableWrapper Set(IDamageable damageable) { damageable = damageable.GetBaseDamagable(); base.Set(damageable); return this; } } public class BaseDamageableWrapper : ObjectWrapper where T : Dam_SyncedDamageBase { public new static readonly BaseDamageableWrapper SharedInstance = new BaseDamageableWrapper(null, IntPtr.Zero); public bool Alive { get { if ((Object)(object)base.Object != (Object)null) { return ((Dam_SyncedDamageBase)base.Object).GetHealthRel() > 0f; } return false; } } public BaseDamageableWrapper(BaseDamageableWrapper wrapper) : base((ObjectWrapper)wrapper) { } public BaseDamageableWrapper(IDamageable? obj, IntPtr ptr) : base((obj != null) ? ((Il2CppObjectBase)obj.GetBaseDamagable()).Cast() : default(T), ptr) { } public BaseDamageableWrapper(IDamageable obj) : base(((Il2CppObjectBase)obj.GetBaseDamagable()).Cast()) { } public override BaseDamageableWrapper Set(T damageable) { base.Set(damageable); return this; } public BaseDamageableWrapper Set(IDamageable damageable) { base.Set(((Il2CppObjectBase)damageable.GetBaseDamagable()).Cast()); return this; } } public class ObjectWrapper where T : Il2CppObjectBase { public static readonly ObjectWrapper SharedInstance = new ObjectWrapper(default(T), IntPtr.Zero); public T? Object { get; private set; } public IntPtr Pointer { get; protected set; } public ObjectWrapper(ObjectWrapper wrapper) { Pointer = wrapper.Pointer; Object = wrapper.Object; } public ObjectWrapper(T? obj, IntPtr ptr) { if (ptr == IntPtr.Zero && obj != null) { Pointer = ((Il2CppObjectBase)obj).Pointer; } else { Pointer = ptr; } Object = obj; } public ObjectWrapper(T obj) { Pointer = ((Il2CppObjectBase)obj).Pointer; Object = obj; } public virtual ObjectWrapper Set(T obj) { Pointer = ((Il2CppObjectBase)obj).Pointer; Object = obj; return this; } public override int GetHashCode() { return Pointer.GetHashCode(); } public override bool Equals(object? obj) { if (obj is ObjectWrapper objectWrapper) { return objectWrapper.Pointer == Pointer; } return false; } } } namespace EWC.CustomWeapon.HitTracker { internal sealed class HitTracker { private readonly Dictionary, Dictionary, (WeaponHitDamageableContext context, float time)>> _lastHits = new Dictionary, Dictionary, (WeaponHitDamageableContext, float)>>(); private readonly Dictionary, bool> _shownHits = new Dictionary, bool>(); private readonly bool _onlyOnce; public HitTracker(bool onlyOnce) { _onlyOnce = onlyOnce; } public void RegisterHit(ObjectWrapper cwc, WeaponHitDamageableContext hitContext, ObjectWrapper enemy) { if (_lastHits.TryGetValue(enemy, out Dictionary, (WeaponHitDamageableContext, float)> value)) { if (value.ContainsKey(cwc)) { value[cwc] = (hitContext, Clock.Time); } else { value[new ObjectWrapper(cwc)] = (hitContext, Clock.Time); } if (!_onlyOnce) { _shownHits[enemy] = false; } } else { enemy = new ObjectWrapper(enemy); _lastHits[enemy] = new Dictionary, (WeaponHitDamageableContext, float)> { [new ObjectWrapper(cwc)] = (hitContext, Clock.Time) }; _shownHits[enemy] = false; } } public bool TryGetContexts(ObjectWrapper enemy, [MaybeNullWhen(false)] out Dictionary, (WeaponHitDamageableContext context, float time)> hitsDict, out IntPtr lastCWCPtr) { _lastHits.Keys.Where((ObjectWrapper wrapper) => (Object)(object)wrapper.Object == (Object)null).ToList().ForEach(delegate(ObjectWrapper wrapper) { _lastHits.Remove(wrapper); _shownHits.Remove(wrapper); }); if (!_shownHits.ContainsKey(enemy) || _shownHits[enemy]) { hitsDict = null; lastCWCPtr = IntPtr.Zero; return false; } _shownHits[enemy] = true; hitsDict = _lastHits[enemy]; if (hitsDict == null || hitsDict.Count == 0) { lastCWCPtr = IntPtr.Zero; return false; } float num = 0f; lastCWCPtr = IntPtr.Zero; foreach (KeyValuePair, (WeaponHitDamageableContext, float)> item2 in hitsDict) { item2.Deconstruct(out var key, out var value); (WeaponHitDamageableContext, float) tuple = value; ObjectWrapper objectWrapper = key; float item = tuple.Item2; if (item > num) { lastCWCPtr = objectWrapper.Pointer; num = item; } } return true; } } internal static class HitTrackerManager { private static readonly Dictionary _trackers = new Dictionary(); [InvokeOnCleanup(true)] private static void Cleanup() { _trackers.Clear(); } public static void RegisterHit(IOwnerComp owner, CustomWeaponComponent cwc, WeaponHitDamageableContext hitContext) { if (!_trackers.TryGetValue(owner, out PlayerHitTracker value)) { _trackers.Add(owner, value = new PlayerHitTracker()); } value.RegisterHit(cwc, hitContext); } public static void RunKillContexts(Agent? enemy) { foreach (PlayerHitTracker value in _trackers.Values) { value.RunKillContexts(enemy); } } public static void RunStaggerContexts(Agent? enemy, bool limbBreak) { foreach (PlayerHitTracker value in _trackers.Values) { value.RunStaggerContexts(enemy, limbBreak); } } } internal class PlayerHitTracker { private readonly HitTracker _killTracker = new HitTracker(onlyOnce: true); private readonly HitTracker _staggerTracker = new HitTracker(onlyOnce: false); private static ObjectWrapper TempWrapper => ObjectWrapper.SharedInstance; private static ObjectWrapper TempCWCWrapper => ObjectWrapper.SharedInstance; public void RegisterHit(CustomWeaponComponent cwc, WeaponHitDamageableContext hitContext) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) Agent baseAgent = hitContext.Damageable.GetBaseAgent(); EnemyAgent val = ((baseAgent != null) ? ((Il2CppObjectBase)baseAgent).TryCast() : null); if (!((Object)(object)val == (Object)null)) { PlayerAgent? player = cwc.Owner.Player; if (player != null && ((Agent)player).IsLocallyOwned) { KillAPIWrapper.TagEnemy(val, ((Il2CppObjectBase)cwc.Weapon.Component).Cast(), hitContext.LocalPosition); } TempCWCWrapper.Set(cwc); TempWrapper.Set((Agent)(object)val); _killTracker.RegisterHit(TempCWCWrapper, hitContext, TempWrapper); _staggerTracker.RegisterHit(TempCWCWrapper, hitContext, TempWrapper); } } public void RunKillContexts(Agent? enemy) { if ((Object)(object)enemy == (Object)null || !_killTracker.TryGetContexts(TempWrapper.Set(enemy), out Dictionary, (WeaponHitDamageableContext, float)> hitsDict, out IntPtr lastCWCPtr)) { return; } foreach (KeyValuePair, (WeaponHitDamageableContext, float)> item in hitsDict) { item.Deconstruct(out var key, out var value); (WeaponHitDamageableContext, float) tuple = value; ObjectWrapper objectWrapper = key; var (hitContext, lastTime) = tuple; objectWrapper.Object.Invoke(new WeaponPostKillContext(hitContext, lastTime, objectWrapper.Pointer == lastCWCPtr)); } } public void RunStaggerContexts(Agent? enemy, bool limbBreak) { if ((Object)(object)enemy == (Object)null || !_staggerTracker.TryGetContexts(TempWrapper.Set(enemy), out Dictionary, (WeaponHitDamageableContext, float)> hitsDict, out IntPtr lastCWCPtr)) { return; } foreach (KeyValuePair, (WeaponHitDamageableContext, float)> item in hitsDict) { item.Deconstruct(out var key, out var value); (WeaponHitDamageableContext, float) tuple = value; ObjectWrapper objectWrapper = key; var (hitContext, lastTime) = tuple; objectWrapper.Object.Invoke(new WeaponPostStaggerContext(hitContext, lastTime, objectWrapper.Pointer == lastCWCPtr, limbBreak)); } } } } namespace EWC.CustomWeapon.Enums { [Flags] public enum DamageType { Invalid = -1, Any = 0, Body = 1, Weakspot = 2, Bullet = 4, Explosive = 8, DOT = 0x10, Shrapnel = 0x20, Foam = 0x40, Armor = 0x80, Flesh = 0x100, Foamed = 0x200, Unfoamed = 0x400, Staggered = 0x800, Unstaggered = 0x1000, Enemy = 0x2000, Player = 0x4000, Object = 0x8000, Dead = 0x10000, Terrain = 0x30000 } public static class DamageTypeConst { public static readonly DamageType[] Any = new DamageType[1]; public static readonly DamageType[] Invalid = new DamageType[1] { DamageType.Invalid }; } public static class DamageTypeMethods { public static DamageType[] ToDamageTypes(this string? name) { if (name == null) { return new DamageType[1] { DamageType.Invalid }; } name = name.Replace(" ", null).ToLowerInvariant(); string[] array = name.Split('|'); DamageType[] array2 = new DamageType[array.Length]; for (int i = 0; i < array.Length; i++) { array2[i] = Internal_ToDamageType(array[i]); } return array2; } public static DamageType ToDamageType(this string? name) { if (name == null) { return DamageType.Invalid; } name = name.Replace(" ", null).ToLowerInvariant(); return Internal_ToDamageType(name); } private static DamageType Internal_ToDamageType(string name) { DamageType damageType = DamageType.Any; if (name.Contains("prec") || name.Contains("weakspot")) { damageType |= DamageType.Weakspot; } else if (name.Contains("body")) { damageType |= DamageType.Body; } if (name.Contains("unfoamed")) { damageType |= DamageType.Unfoamed; } else if (name.Contains("foamed")) { damageType |= DamageType.Foamed; } if (name.Contains("unstaggered")) { damageType |= DamageType.Unstaggered; } else if (name.Contains("staggered")) { damageType |= DamageType.Staggered; } if (name.Contains("armor")) { damageType |= DamageType.Armor; } else if (name.Contains("flesh")) { damageType |= DamageType.Flesh; } if (name.Contains("enemy")) { damageType |= DamageType.Enemy; } else if (name.Contains("player") || name.Contains("friendly")) { damageType |= DamageType.Player; } else if (name.Contains("object") || name.Contains("lock")) { damageType |= DamageType.Object; } else if (name.Contains("terrain")) { damageType |= DamageType.Terrain; } if (name.Contains("bullet") || name.Contains("melee")) { damageType |= DamageType.Bullet; } else if (name.Contains("explo")) { damageType |= DamageType.Explosive; } else if (name.Contains("dot")) { damageType |= DamageType.DOT; } else if (name.Contains("shrapnel")) { damageType |= DamageType.Shrapnel; } else if (name.Contains("glue")) { damageType |= DamageType.Foam; } return damageType; } public static bool HasAnyFlag(this DamageType type, DamageType flagSet) { return (type & flagSet) != 0; } public static bool HasFlagIn(this DamageType type, DamageType[] flagSet) { foreach (DamageType damageType in flagSet) { if (type.HasFlag(damageType)) { return true; } } return false; } public static DamageType GetBaseType(this DamageType type) { return type & (DamageType.Bullet | DamageType.Explosive | DamageType.DOT | DamageType.Shrapnel); } public static DamageType GetBaseType(this DamageType[] types) { DamageType damageType = DamageType.Invalid; foreach (DamageType type in types) { damageType &= type.GetBaseType(); } return damageType; } public static DamageType GetSubTypes(Dam_EnemyDamageLimb limb) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Invalid comparison between Unknown and I4 int num = 0x2000 | (((int)limb.m_type != 1) ? 1 : 2) | ((limb.m_armorDamageMulti < 1f) ? 128 : 256) | (limb.m_base.IsStuckInGlue ? 512 : 1024); ES_StateEnum currentStateEnum = limb.m_base.Owner.Locomotion.CurrentStateEnum; return (DamageType)(num | (int)(((int)currentStateEnum == 7 || (int)currentStateEnum == 29) ? DamageType.Staggered : DamageType.Unstaggered)); } public static DamageType GetSubTypes(IDamageable damageable) { //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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 Agent baseAgent = damageable.GetBaseAgent(); if ((Object)(object)baseAgent == (Object)null) { if ((Object)(object)((Il2CppObjectBase)damageable).TryCast() == (Object)null) { return DamageType.Body | DamageType.Flesh | DamageType.Unfoamed | DamageType.Object; } return DamageType.Terrain; } AgentType type = baseAgent.Type; if ((int)type != 0) { if ((int)type == 1) { return (damageable.GetBaseDamagable().GetHealthRel() > 0f) ? GetSubTypes(((Il2CppObjectBase)damageable).Cast()) : DamageType.Dead; } return DamageType.Any; } return DamageType.Body | DamageType.Flesh | DamageType.Unfoamed | DamageType.Unstaggered | DamageType.Player; } public static DamageType WithSubTypes(this DamageType damageType, Dam_EnemyDamageLimb limb) { return damageType | GetSubTypes(limb); } public static DamageType WithSubTypes(this DamageType damageType, IDamageable damageable) { return damageType | GetSubTypes(damageable); } } [Flags] public enum OwnerType : byte { Any = 0, Managed = 1, Local = 2, Player = 4, Sentry = 8, Unmanaged = 0x10 } [Flags] public enum PlayerDamageType { Invalid = -1, Any = 0, Enemy = 1, Tentacle = 3, Shooter = 5, Melee = 9, Bleed = 0x11, Player = 0x20, Bullet = 0x60, Explosive = 0x80, DOT = 0x120, Shrapnel = 0x220, Heal = 0x420, Syringe = 0x820, Fall = 0x1020 } public static class PlayerDamageTypeConst { public static readonly PlayerDamageType[] Any = new PlayerDamageType[1]; } public static class PlayerDamageTypeMethods { public static PlayerDamageType[] ToPlayerDamageTypes(this string? name) { if (name == null) { return new PlayerDamageType[1] { PlayerDamageType.Invalid }; } name = name.Replace(" ", null).ToLowerInvariant(); string[] array = name.Split('|'); PlayerDamageType[] array2 = new PlayerDamageType[array.Length]; for (int i = 0; i < array.Length; i++) { array2[i] = Internal_ToDamageType(array[i]); } return array2; } public static PlayerDamageType ToPlayerDamageType(this string? name) { if (name == null) { return PlayerDamageType.Invalid; } name = name.Replace(" ", null).ToLowerInvariant(); return Internal_ToDamageType(name); } private static PlayerDamageType Internal_ToDamageType(string name) { PlayerDamageType playerDamageType = PlayerDamageType.Any; if (name.Contains("enemy")) { playerDamageType |= PlayerDamageType.Enemy; } else if (name.Contains("player") | name.Contains("friendly")) { playerDamageType |= PlayerDamageType.Player; } if (name.Contains("tentacle") | name.Contains("tongue")) { playerDamageType |= PlayerDamageType.Tentacle; } else if (name.Contains("shooter")) { playerDamageType |= PlayerDamageType.Shooter; } else if (name.Contains("melee")) { playerDamageType |= PlayerDamageType.Melee; } else if (name.Contains("bleed")) { playerDamageType |= PlayerDamageType.Bleed; } if (name.Contains("bullet")) { playerDamageType |= PlayerDamageType.Bullet; } else if (name.Contains("explo")) { playerDamageType |= PlayerDamageType.Explosive; } else if (name.Contains("dot")) { playerDamageType |= PlayerDamageType.DOT; } else if (name.Contains("shrapnel")) { playerDamageType |= PlayerDamageType.Shrapnel; } else if (name.Contains("heal")) { playerDamageType |= PlayerDamageType.Heal; } else if (name.Contains("syringe")) { playerDamageType |= PlayerDamageType.Syringe; } else if (name.Contains("fall")) { playerDamageType |= PlayerDamageType.Fall; } return playerDamageType; } public static bool HasAnyFlag(this PlayerDamageType type, PlayerDamageType flagSet) { return (type & flagSet) != 0; } public static bool HasFlagIn(this PlayerDamageType type, PlayerDamageType[] flagSet) { foreach (PlayerDamageType playerDamageType in flagSet) { if (type.HasFlag(playerDamageType)) { return true; } } return false; } } public enum StackType { Invalid = -1, Override = 0, None = 0, Add = 1, Multiply = 2, Mult = 2, Max = 3, Min = 4 } public static class StackTypeConst { public static readonly int Count = (int)(Enum.GetValues().Max() + 1); } public enum StatType { Damage = 0, Precision = 1, Prec = 1, Stagger = 2 } public static class StatTypeConst { public static readonly int Count = (int)(Enum.GetValues().Max() + 1); } public enum TriggerPosMode { Relative, Absolute, User } [Flags] public enum WeaponType : byte { Any = 0, SentryHolder = 1, Melee = 2, Gun = 4, BulletWeapon = 8, Sentry = 0x10 } } namespace EWC.CustomWeapon.CustomShot { public sealed class CustomShotComponent { private struct ShotHitbox { private readonly CustomShotComponent _parent; private readonly IWeaponComp _weapon; private readonly IOwnerComp _owner; private readonly PlayerAgent? _ownerPlayer; private readonly HashSet? _hitEnts; private readonly HitData _hitData; private readonly ShotInfo.Const _origInfo; private readonly Ray _ray; private readonly Vector3 _fxPos; private readonly WallPierce? _wallPierce; private readonly float _hitSize; private readonly float _hitSizeFriendly; private readonly SearchSetting _friendlySetting; private readonly int _friendlyMask; private readonly Func _hitFunc; private int _pierceCount; private static RaycastHit s_rayHit; private const float SightCheckMinSize = 0.5f; public ShotHitbox(CustomShotComponent parent, HitData hitData, Ray fireRay, Vector3 fxPos, int friendlyMask, IntPtr ignoreEnt) : this(parent, hitData, fireRay, fxPos, friendlyMask, ignoreEnt, new CustomShotSettings(parent.ThickBullet, parent.WallPierce)) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) public ShotHitbox(CustomShotComponent parent, HitData hitData, Ray fireRay, Vector3 fxPos, int friendlyMask, IntPtr ignoreEnt, CustomShotSettings shotSettings) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) _parent = parent; _weapon = _parent._weapon; _owner = _parent._owner; _ownerPlayer = (_owner.IsType(OwnerType.Player) ? _owner.Player : null); _ray = fireRay; _fxPos = fxPos; _hitData = hitData; _origInfo = _hitData.shotInfo.State; _pierceCount = hitData.GetPierceOrFallback(_weapon); if (_pierceCount > 1 || ignoreEnt != IntPtr.Zero) { _hitEnts = new HashSet(_pierceCount); if (ignoreEnt != IntPtr.Zero) { _hitEnts.Add(ignoreEnt); } } else { _hitEnts = null; } _wallPierce = shotSettings.wallPierce; _hitSize = 0f; _hitSizeFriendly = 0f; _friendlySetting = SearchSetting.None; if (friendlyMask == -1) { _friendlyMask = LayerUtil.MaskFriendly; _friendlySetting |= SearchSetting.CheckFriendly; if (!_owner.IsType(OwnerType.Local)) { _friendlyMask |= LayerUtil.MaskLocal; } } else { _friendlyMask = friendlyMask & (LayerUtil.MaskFriendly | LayerUtil.MaskLocal); bool flag = (_friendlyMask & LayerUtil.MaskFriendly) != 0; bool flag2 = (_friendlyMask & LayerUtil.MaskLocal) != 0; if (flag2) { _friendlySetting |= SearchSetting.CheckOwner; } if (flag) { _friendlySetting |= SearchSetting.CheckFriendly; } if (!_owner.IsType(OwnerType.Local)) { _friendlyMask &= LayerUtil.MaskFriendly; if (flag2) { _friendlyMask |= LayerUtil.MaskFriendly; } if (flag) { _friendlyMask |= LayerUtil.MaskLocal; } } } if (shotSettings.thickBullet != null) { _hitSize = shotSettings.thickBullet.HitSize; _hitSizeFriendly = shotSettings.thickBullet.HitSizeFriendly; } _hitFunc = shotSettings.hitFunc; } public int Fire() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0048: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00f7: Unknown result type (might be due to invalid IL or missing references) bool hitWall; RaycastHit wallRayHit = default(RaycastHit); Vector3 val; Ray ray; if ((hitWall = Physics.Raycast(_ray, ref wallRayHit, _hitData.maxRayDist, LayerUtil.MaskWorld)) && _wallPierce == null) { val = ((RaycastHit)(ref wallRayHit)).point; } else { ray = _ray; Vector3 origin = ((Ray)(ref ray)).origin; ray = _ray; val = origin + ((Ray)(ref ray)).direction * _hitData.maxRayDist; } FireShotAPI.FirePreShotFiredCallback(_hitData, _ray, _weapon.Type); if (!Fire_Internal(val, hitWall, wallRayHit, out var fxTarget)) { val = fxTarget; } HitData hitData = _hitData; ray = _ray; FireShotAPI.FireShotFiredCallback(hitData, ((Ray)(ref ray)).origin, val, _weapon.Type); if (!_parent.CancelAllFX) { FX_Manager.EffectTargetPosition = val; FX_Manager.PlayLocalVersion = false; FX_EffectBase_Poolable obj = _weapon.TracerPool.AquireEffect(); Vector3 fxPos = _fxPos; ray = _ray; ((FX_EffectBase)obj).Play((FX_Trigger)null, fxPos, Quaternion.LookRotation(((Ray)(ref ray)).direction)); } _parent._cwc.Invoke(new WeaponShotEndContext(_hitData.damageType.GetBaseType(), _hitData.shotInfo, _origInfo)); return _pierceCount; } private bool Fire_Internal(Vector3 endRayPos, bool hitWall, RaycastHit wallRayHit, out Vector3 fxTarget) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_016e: 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) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) if (!CheckCollisionInitial(endRayPos, out fxTarget)) { return false; } Ray ray = _ray; Vector3 val = ((Ray)(ref ray)).origin - endRayPos; float magnitude = ((Vector3)(ref val)).magnitude; List<(IDamageable, RaycastHit)> list = new List<(IDamageable, RaycastHit)>(); if (_hitSize == 0f) { RaycastHit[] array = RaycastOneOrAll(_ray, magnitude, LayerUtil.MaskEnemyDynamic); for (int i = 0; i < array.Length; i++) { IDamageable damageableFromRayHit = DamageableUtil.GetDamageableFromRayHit(array[i]); if (damageableFromRayHit != null && !AlreadyHit(damageableFromRayHit)) { list.Add((damageableFromRayHit, array[i])); } } } else { RaycastHit[] array = SpherecastOneOrAll(_ray, _hitSize, magnitude, LayerUtil.MaskEnemyDynamic); for (int j = 0; j < array.Length; j++) { IDamageable damageableFromRayHit2 = DamageableUtil.GetDamageableFromRayHit(array[j]); if (damageableFromRayHit2 != null && !AlreadyHit(damageableFromRayHit2) && ((RaycastHit)(ref array[j])).distance > 0f) { ref RaycastHit reference = ref array[j]; ((RaycastHit)(ref reference)).distance = ((RaycastHit)(ref reference)).distance + _hitSize; list.Add((damageableFromRayHit2, array[j])); } } } if (_hitSizeFriendly == 0f) { RaycastHit[] array = RaycastOneOrAll(_ray, magnitude, _friendlyMask); for (int k = 0; k < array.Length; k++) { IDamageable damageableFromRayHit3 = DamageableUtil.GetDamageableFromRayHit(array[k]); if (damageableFromRayHit3 != null && !AlreadyHit(damageableFromRayHit3)) { list.Add((damageableFromRayHit3, array[k])); } } } else { RaycastHit[] array = SpherecastOneOrAll(_ray, _hitSizeFriendly, magnitude, _friendlyMask); for (int l = 0; l < array.Length; l++) { IDamageable damageableFromRayHit4 = DamageableUtil.GetDamageableFromRayHit(array[l]); if (damageableFromRayHit4 != null && !AlreadyHit(damageableFromRayHit4) && ((RaycastHit)(ref array[l])).distance > 0f) { ref RaycastHit reference2 = ref array[l]; ((RaycastHit)(ref reference2)).distance = ((RaycastHit)(ref reference2)).distance + _hitSizeFriendly; list.Add((damageableFromRayHit4, array[l])); } } } if (_hitSize > 0f) { SortUtil.SortWithWeakspotBuffer(list); } else { list.Sort(SortUtil.RayhitTuple); } foreach (var item3 in list) { IDamageable item = item3.Item1; RaycastHit item2 = item3.Item2; Agent baseAgent = item.GetBaseAgent(); if ((Object)(object)baseAgent != (Object)null && (Object)(object)baseAgent == (Object)(object)_ownerPlayer) { continue; } if ((Object)(object)baseAgent != (Object)null) { WallPierce? wallPierce = _wallPierce; if (wallPierce != null && !wallPierce.IsTargetReachable(_owner.CourseNode, baseAgent.CourseNode)) { continue; } } float num = ((baseAgent != null && (int)baseAgent.Type == 0) ? _hitSizeFriendly : _hitSize); if (_wallPierce == null && !CheckLineOfSight(((RaycastHit)(ref item2)).collider, ((RaycastHit)(ref item2)).point + ((RaycastHit)(ref item2)).normal * num, endRayPos, num, checkLock: true)) { continue; } if (num != 0f) { if (CheckDirectHit(baseAgent, ref s_rayHit)) { _hitData.RayHit = s_rayHit; fxTarget = ((RaycastHit)(ref s_rayHit)).point; } else { _hitData.RayHit = item2; ray = _ray; Vector3 origin = ((Ray)(ref ray)).origin; ray = _ray; fxTarget = origin + ((Ray)(ref ray)).direction * ((RaycastHit)(ref item2)).distance; } } else { _hitData.RayHit = item2; fxTarget = ((RaycastHit)(ref item2)).point; } if (_hitFunc(_weapon, _hitData)) { _pierceCount--; } if (_pierceCount <= 0) { return false; } } if (_pierceCount > 0 && hitWall && !AlreadyHit(DamageableUtil.GetDamageableFromRayHit(wallRayHit)) && _wallPierce == null) { _hitData.RayHit = wallRayHit; _hitFunc(_weapon, _hitData); } return true; } private bool CheckCollisionInitial(Vector3 endRayPos, out Vector3 fxTarget) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0030: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: 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_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0244: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) fxTarget = Vector3.zero; if (_hitSize == 0f && _hitSizeFriendly == 0f) { return true; } Ray ray = _ray; Vector3 origin = ((Ray)(ref ray)).origin; List<(Agent, RaycastHit)> list = new List<(Agent, RaycastHit)>(); if (_hitSize > 0f) { List<(EnemyAgent, RaycastHit)> enemyHitsInRange = SearchUtil.GetEnemyHitsInRange(_ray, _hitSize, 180f, _owner.CourseNode); list.EnsureCapacity(enemyHitsInRange.Count); foreach (var (val, item) in enemyHitsInRange) { list.Add((((Il2CppObjectBase)val).Cast(), item)); } foreach (RaycastHit item3 in SearchUtil.GetLockHitsInRange(_ray, _hitSize, 180f)) { list.Add((null, item3)); } } if (_hitSizeFriendly > 0f) { List<(PlayerAgent, RaycastHit)> playerHitsInRange = SearchUtil.GetPlayerHitsInRange(_ray, _hitSizeFriendly, 180f, _ownerPlayer, _friendlySetting); list.EnsureCapacity(playerHitsInRange.Count + list.Count); foreach (var (val2, item2) in playerHitsInRange) { list.Add((((Il2CppObjectBase)val2).Cast(), item2)); } } list.Sort(SortUtil.RayhitTuple); foreach (var item4 in list) { var (val3, rayHit) = item4; _hitData.RayHit = rayHit; if (AlreadyHit(_hitData.damageable)) { continue; } if ((Object)(object)val3 != (Object)null) { WallPierce? wallPierce = _wallPierce; if (wallPierce != null && !wallPierce.IsTargetReachable(_owner.CourseNode, val3.CourseNode)) { continue; } } float num = ((val3 != null && (int)val3.Type == 0) ? _hitSizeFriendly : _hitSize); if (_wallPierce == null && !CheckLineOfSight(((RaycastHit)(ref rayHit)).collider, origin, endRayPos, num)) { continue; } if (num != 0f) { if (CheckDirectHit(val3, ref s_rayHit)) { _hitData.RayHit = s_rayHit; fxTarget = ((RaycastHit)(ref s_rayHit)).point; } else { _hitData.RayHit = rayHit; ray = _ray; Vector3 origin2 = ((Ray)(ref ray)).origin; ray = _ray; fxTarget = origin2 + ((Ray)(ref ray)).direction * ((RaycastHit)(ref rayHit)).distance; } } else { _hitData.RayHit = rayHit; fxTarget = ((RaycastHit)(ref rayHit)).point; } if (_hitFunc(_weapon, _hitData)) { _pierceCount--; } if (_pierceCount <= 0) { return false; } } return true; } private bool CheckLineOfSight(Collider collider, Vector3 startPos, Vector3 endPos, float hitSize, bool checkLock = false) { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_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) //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00c7: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) if (hitSize < 0.5f) { return true; } Vector3 val = endPos - startPos; float num = ((Vector3)(ref val)).magnitude; float num2 = Math.Max(0.1f, Math.Min(hitSize, num) / 10f); Vector3 position = ((Component)collider).transform.position; Vector3 val2 = startPos; val = val2 - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; float num3 = sqrMagnitude; int num4 = 0; while (num >= 0.1f && sqrMagnitude <= num3) { if (!Physics.Linecast(val2, ((Component)collider).transform.position, ref s_rayHit, LayerUtil.MaskWorld)) { return true; } if (checkLock && ((Il2CppObjectBase)((Component)collider).gameObject).Pointer == ((Il2CppObjectBase)((Component)((RaycastHit)(ref s_rayHit)).collider).gameObject).Pointer) { return true; } Vector3 val3 = val2; Ray ray = _ray; val2 = val3 + ((Ray)(ref ray)).direction * num2; val = val2 - position; sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; num -= num2; num4++; } return false; } private bool CheckDirectHit(Agent? agent, ref RaycastHit hit) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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) if ((Object)(object)agent == (Object)null || (int)agent.Type != 1) { return false; } RaycastHit val = default(RaycastHit); ((RaycastHit)(ref val)).distance = float.MaxValue; RaycastHit val2 = val; RaycastHit val4 = default(RaycastHit); foreach (Collider componentsInChild in ((Component)agent).GetComponentsInChildren()) { if (((Component)componentsInChild).GetComponent() != null) { Ray ray = _ray; Vector3 position = ((Component)componentsInChild).transform.position; Ray ray2 = _ray; Vector3 val3 = position - ((Ray)(ref ray2)).origin; if (componentsInChild.Raycast(ray, ref val4, ((Vector3)(ref val3)).magnitude + 1f) && ((RaycastHit)(ref val4)).distance < ((RaycastHit)(ref val2)).distance) { val2 = val4; } } } if (((RaycastHit)(ref val2)).distance != float.MaxValue) { hit = val2; return true; } return false; } private bool AlreadyHit(IDamageable? damageable) { if (damageable == null || _hitEnts == null) { return false; } return !_hitEnts.Add(((Il2CppObjectBase)damageable.GetBaseDamagable()).Pointer); } private RaycastHit[] RaycastOneOrAll(Ray ray, float maxDist, int layerMask) { //IL_0030: 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_001f: 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) if (_hitEnts == null) { if (Physics.Raycast(ray, ref s_rayHit, maxDist, layerMask)) { return (RaycastHit[])(object)new RaycastHit[1] { s_rayHit }; } return Array.Empty(); } return SearchUtil.RaycastAll(ray, maxDist, layerMask).ToArray(); } private RaycastHit[] SpherecastOneOrAll(Ray ray, float hitSize, float maxDist, int layerMask) { //IL_0032: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (_hitEnts == null) { if (Physics.SphereCast(ray, hitSize, ref s_rayHit, maxDist, layerMask)) { return (RaycastHit[])(object)new RaycastHit[1] { s_rayHit }; } return Array.Empty(); } return Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)Physics.SphereCastAll(ray, hitSize, maxDist, layerMask)); } } private readonly IWeaponComp _weapon; private IOwnerComp _owner; private readonly CustomWeaponComponent _cwc; private int _normalCancel; private int _fxCancel; private static RaycastHit s_rayHit; public bool CancelNormalShot { get { return _normalCancel > 0; } set { _normalCancel += (value ? 1 : (-1)); } } public bool CancelAllFX { get { return _fxCancel > 0; } set { _fxCancel += (value ? 1 : (-1)); } } public Projectile? Projectile { get; set; } public WallPierce? WallPierce { get; set; } public ThickBullet? ThickBullet { get; set; } public CustomShotComponent(CustomWeaponComponent cwc) { _cwc = cwc; _owner = cwc.Owner; _weapon = cwc.Weapon; } public void RefreshOwner() { _owner = _cwc.Owner; } public void FireVanilla(HitData hitData, Vector3 origin) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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) Ray fireRay = default(Ray); ((Ray)(ref fireRay))..ctor(origin, CalcRayDir(hitData.fireDir, hitData.angOffsetX, hitData.angOffsetY, hitData.randomSpread)); hitData.fireDir = ((Ray)(ref fireRay)).direction; ShotManager.VanillaFireDir = ((Ray)(ref fireRay)).direction; if (!CancelNormalShot) { Fire(fireRay, _owner.MuzzleAlign.position, hitData, -1, (IntPtr)0); } } public void FireSpread(Ray fireRay, Vector3 fxPos, HitData hitData, int friendlyMask = -1, IntPtr ignoreEnt = default(IntPtr)) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) CalcRayDir(ref fireRay, hitData.angOffsetX, hitData.angOffsetY, hitData.randomSpread); Fire(fireRay, fxPos, hitData, friendlyMask, ignoreEnt); } public int Fire(Ray fireRay, Vector3 fxPos, HitData hitData, int friendlyMask = -1, IntPtr ignoreEnt = default(IntPtr)) { //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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0025: Unknown result type (might be due to invalid IL or missing references) hitData.fireDir = ((Ray)(ref fireRay)).direction; if (!_owner.IsType(OwnerType.Managed)) { if (Projectile == null) { FireVisual(fireRay, fxPos, hitData); } return 0; } if (Projectile != null) { Projectile.Fire(fireRay, fxPos, hitData, ignoreEnt); return 0; } return new ShotHitbox(this, hitData, fireRay, fxPos, friendlyMask, ignoreEnt).Fire(); } public int FireCustom(Ray fireRay, Vector3 fxPos, HitData hitData, int friendlyMask = -1, IntPtr ignoreEnt = default(IntPtr), CustomShotSettings shotSettings = default(CustomShotSettings)) { //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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) hitData.fireDir = ((Ray)(ref fireRay)).direction; if (!_owner.IsType(OwnerType.Managed)) { if (shotSettings.projectile == null) { FireVisual(fireRay, fxPos, hitData); } return 0; } if (shotSettings.projectile != null) { shotSettings.projectile.Fire(fireRay, fxPos, hitData, ignoreEnt); return 0; } return new ShotHitbox(this, hitData, fireRay, fxPos, friendlyMask, ignoreEnt, shotSettings).Fire(); } private void FireVisual(Ray fireRay, Vector3 fxPos, HitData hitData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_006f: 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_007a: 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) //IL_0046: 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_008c: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) FireShotAPI.FirePreShotFiredCallback(hitData, fireRay, _weapon.Type); float num = Math.Min(hitData.maxRayDist, 20f); if (Physics.Raycast(fireRay, ref s_rayHit, num, LayerUtil.MaskEntityAndWorld)) { FX_Manager.EffectTargetPosition = ((RaycastHit)(ref s_rayHit)).point; hitData.RayHit = s_rayHit; BulletWeapon.BulletHit(hitData.ToWeaponHitData(), false, 0f, 0u, true); } else { FX_Manager.EffectTargetPosition = ((Ray)(ref fireRay)).origin + ((Ray)(ref fireRay)).direction * num; } FireShotAPI.FireShotFiredCallback(hitData, ((Ray)(ref fireRay)).origin, FX_Manager.EffectTargetPosition, _weapon.Type); FX_Manager.PlayLocalVersion = false; ((FX_EffectBase)_weapon.TracerPool.AquireEffect()).Play((FX_Trigger)null, fxPos, Quaternion.LookRotation(((Ray)(ref fireRay)).direction)); } public static Vector3 CalcRayDir(Vector3 fireDir, float x, float y, float spread) { //IL_0028: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references) if (spread != 0f) { Vector2 val = Random.insideUnitCircle * spread; x += val.x; y += val.y; } return fireDir.RotateBy(x, y); } public static void CalcRayDir(ref Ray ray, float x, float y, float spread) { //IL_0002: 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) ((Ray)(ref ray)).direction = CalcRayDir(((Ray)(ref ray)).direction, x, y, spread); } } public struct CustomShotSettings { public ThickBullet? thickBullet; public Projectile? projectile; public WallPierce? wallPierce; public Func hitFunc; public CustomShotSettings(ThickBullet? thickBullet = null, WallPierce? wallPierce = null, Projectile? projectile = null, Func? hitFunc = null) { this.thickBullet = thickBullet; this.projectile = projectile; this.wallPierce = wallPierce; this.hitFunc = hitFunc ?? new Func(ShotManager.BulletHit); } public readonly CustomShotSettings Clone(Func? hitFunc = null) { return new CustomShotSettings((ThickBullet)(thickBullet?.Clone()), (WallPierce)(wallPierce?.Clone()), (Projectile)(projectile?.Clone()), hitFunc); } } public sealed class ShotInfo { public class Const { public readonly ShotInfo Orig; public readonly float ExternalDamageMod; public readonly float InnateDamageMod; public readonly float InnateStaggerMod; public readonly uint ID; private readonly DamageType[] _hits; public readonly uint Hits; public uint TypeHits(DamageType type) { return (uint)_hits.Count((DamageType hitType) => hitType.HasFlag(type)); } public uint TypeHits(DamageType[] types) { DamageType[] types2 = types; return (uint)_hits.Count((DamageType hitType) => hitType.HasFlagIn(types2)); } public uint TypeHits(DamageType[] types, DamageType blacklist) { DamageType[] types2 = types; return (uint)_hits.Count((DamageType hitType) => hitType.HasFlagIn(types2) && !hitType.HasAnyFlag(blacklist)); } public Const(ShotInfo info) { Orig = info; ExternalDamageMod = info.ExternalDamageMod; InnateDamageMod = info.InnateDamageMod; InnateStaggerMod = info.InnateStaggerMod; ID = info.ID; _hits = info._hits.ToArray(); Hits = (uint)_hits.Length; } } private readonly List _hits; private Const _state; public uint ID { get; private set; } public uint Hits => (uint)_hits.Count; public float OrigDamage { get; private set; } public float OrigPrecision { get; private set; } public float OrigStagger { get; private set; } public float ExternalDamageMod { get; private set; } public float InnateDamageMod { get; private set; } public float InnateStaggerMod { get; private set; } public ShotInfoMod Mod { get; set; } public ShotInfoMod GroupMod { get; set; } public Const State { get { if (!Equals(_state)) { _state = new Const(this); } return _state; } } public uint TypeHits(DamageType type) { return (uint)_hits.Count((DamageType hitType) => hitType.HasFlag(type)); } public uint TypeHits(DamageType[] types) { DamageType[] types2 = types; return (uint)_hits.Count((DamageType hitType) => hitType.HasFlagIn(types2)); } public uint TypeHits(DamageType[] types, DamageType blacklist) { DamageType[] types2 = types; return (uint)_hits.Count((DamageType hitType) => hitType.HasFlagIn(types2) && !hitType.HasAnyFlag(blacklist)); } public ShotInfo() : this(0f, 0f, 0f) { } public ShotInfo(float origDamage, float origPrecision, float origStagger) { ID = ShotManager.NextID; _hits = new List(5); Mod = new ShotInfoMod(); InnateDamageMod = ShotManager.CurrentDamageMod; InnateStaggerMod = ShotManager.CurrentStaggerMod; ExternalDamageMod = ShotManager.CurrentExternalDamageMod; GroupMod = ShotManager.CurrentGroupMod; OrigDamage = origDamage * InnateDamageMod; OrigPrecision = origPrecision; OrigStagger = origStagger * InnateStaggerMod; _state = new Const(this); } public ShotInfo(CustomWeaponComponent cwc, bool modOnly = false, bool isTagged = false) { ID = ShotManager.NextID; _hits = new List(5); RefreshMods(cwc, isTagged); if (!modOnly && !cwc.Weapon.Type.HasFlag(WeaponType.Melee)) { ArchetypeDataBlock archetypeData = ((IAmmoComp)cwc.Weapon).ArchetypeData; OrigDamage = archetypeData.Damage * InnateDamageMod; OrigPrecision = archetypeData.PrecisionDamageMulti; OrigStagger = archetypeData.StaggerDamageMulti * InnateStaggerMod; } else { OrigDamage = 0f; OrigPrecision = 0f; OrigStagger = 0f; } _state = new Const(this); } public ShotInfo(ShotInfo copy, bool modOnly = false, bool useParentMod = true) { PullMods(copy, useParentMod); if (modOnly) { ID = ShotManager.NextID; _hits = new List(5); OrigDamage = 0f; OrigPrecision = 0f; OrigStagger = 0f; _state = new Const(this); } else { ID = copy.ID; _hits = new List(copy._hits); OrigDamage = copy.OrigDamage; OrigPrecision = copy.OrigPrecision; OrigStagger = copy.OrigStagger; _state = new Const(this); } } public void Reset(float origDamage, float origPrecision, float origStagger, CustomWeaponComponent cwc, ShotInfo? parent = null, bool useParent = true) { if (parent != null) { PullMods(parent, useParent); } else { RefreshMods(cwc); } OrigDamage = origDamage * InnateDamageMod; OrigPrecision = origPrecision * InnateStaggerMod; OrigStagger = origStagger; ID = ShotManager.NextID; _hits.Clear(); } public void SetToPush() { InnateDamageMod = 1f; InnateStaggerMod = 1f; ExternalDamageMod = 1f; OrigDamage = 1f; OrigPrecision = 1f; OrigStagger = 1f; ID = ShotManager.NextID; _hits.Clear(); } public void AddHit(DamageType type) { _hits.Add(type); } public void AddHits(DamageType type, int hits) { for (int i = 0; i < hits; i++) { _hits.Add(type); } } [MemberNotNull("Mod")] [MemberNotNull("GroupMod")] private void PullMods(ShotInfo info, bool useOriginal = true) { Mod = (useOriginal ? info.Mod : new ShotInfoMod(info.Mod)); GroupMod = (useOriginal ? info.GroupMod : new ShotInfoMod(info.GroupMod)); ExternalDamageMod = info.ExternalDamageMod; InnateDamageMod = info.InnateDamageMod; InnateStaggerMod = info.InnateStaggerMod; } [MemberNotNull("Mod")] [MemberNotNull("GroupMod")] private void RefreshMods(CustomWeaponComponent cwc, bool isTagged = false) { ShotManager.AdvanceGroupModIfOld(cwc, isTagged); Mod = new ShotInfoMod(); GroupMod = ShotManager.CurrentGroupMod; InnateDamageMod = ShotManager.CurrentDamageMod; InnateStaggerMod = ShotManager.CurrentStaggerMod; ExternalDamageMod = ShotManager.CurrentExternalDamageMod; cwc.Invoke(new WeaponShotInitContext(Mod)); } public static implicit operator Const(ShotInfo info) { return info.State; } public bool Equals(Const state) { if (ID == state.ID) { return Hits == state.Hits; } return false; } } public sealed class ShotInfoMod { public readonly ShotStackMod Damage; public readonly ShotStackMod Precision; public readonly ShotStackMod Stagger; public ShotInfoMod() { Damage = new ShotStackMod(); Precision = new ShotStackMod(); Stagger = new ShotStackMod(); } public ShotInfoMod(ShotInfoMod mod) { Damage = new ShotStackMod(mod.Damage); Precision = new ShotStackMod(mod.Precision); Stagger = new ShotStackMod(mod.Stagger); } public void Add(TriggerMod triggerMod, StatType type, float mod, IDamageable? damageable = null, params DamageType[] types) { Add(triggerMod, type, mod, triggerMod.Cap, triggerMod.StackType, triggerMod.StackLayer, damageable, types); } public void Add(WeaponPropertyBase property, StatType type, float mod, float cap, StackType stack, StackType layer, IDamageable? damageable = null, params DamageType[] types) { switch (type) { case StatType.Damage: Damage.AddMod(property, mod, cap, stack, layer, damageable, types); break; case StatType.Precision: Precision.AddMod(property, mod, cap, stack, layer, damageable, types); break; case StatType.Stagger: Stagger.AddMod(property, mod, cap, stack, layer, damageable, types); break; } } public void Reset() { Damage.Reset(); Precision.Reset(); Stagger.Reset(); } } public static class ShotManager { public struct FiringInfo { public PlayerAgent? owner; public InventorySlot slot; public bool isTagged; public ArchetypeDataBlock? archBlock; public CustomWeaponComponent? cwc; public bool valid; public FiringInfo() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) owner = null; slot = (InventorySlot)0; isTagged = false; archBlock = null; cwc = null; valid = false; } } private static float s_lastShotTime = 0f; private static IntPtr s_lastGroupCWC = IntPtr.Zero; private static (IntPtr ptr, ShotInfo info) s_vanillaShotInfo = (IntPtr.Zero, new ShotInfo()); public static uint CurrentID { get; private set; } = 0u; public static uint NextID => ++CurrentID; public static ShotInfoMod CurrentGroupMod { get; private set; } = new ShotInfoMod(); public static float CurrentExternalDamageMod { get; private set; } = 1f; public static float CurrentDamageMod { get; private set; } = 1f; public static float CurrentStaggerMod { get; private set; } = 1f; public static FiringInfo ActiveFiringInfo { get; private set; } public static Vector3 VanillaFireDir { get; set; } public static ShotInfo GetVanillaShotInfo(WeaponHitData vanillaData) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (((Il2CppObjectBase)vanillaData).Pointer != s_vanillaShotInfo.ptr) { if ((Object)(object)ActiveFiringInfo.cwc != (Object)null) { s_vanillaShotInfo = (((Il2CppObjectBase)vanillaData).Pointer, new ShotInfo(ActiveFiringInfo.cwc, modOnly: false, ActiveFiringInfo.isTagged)); if ((Object)(object)vanillaData.owner == (Object)null) { ArchetypeDataBlock archBlock = ActiveFiringInfo.archBlock; vanillaData.owner = ActiveFiringInfo.owner; vanillaData.damage = s_vanillaShotInfo.info.OrigDamage; vanillaData.staggerMulti = s_vanillaShotInfo.info.OrigStagger; vanillaData.precisionMulti = archBlock.PrecisionDamageMulti; vanillaData.damageFalloff = archBlock.DamageFalloff; } } else if (ActiveFiringInfo.valid) { s_vanillaShotInfo = (((Il2CppObjectBase)vanillaData).Pointer, new ShotInfo(vanillaData.damage, vanillaData.precisionMulti, vanillaData.staggerMulti)); } } return s_vanillaShotInfo.info; } public static void CacheFiringGun(BulletWeapon weapon) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) FiringInfo activeFiringInfo = new FiringInfo(); activeFiringInfo.owner = ((Item)weapon).Owner; activeFiringInfo.slot = ((ItemEquippable)weapon).AmmoType.ToInventorySlot(); activeFiringInfo.archBlock = ((ItemEquippable)weapon).ArchetypeData; activeFiringInfo.isTagged = false; activeFiringInfo.cwc = ((Component)weapon).GetComponent(); activeFiringInfo.valid = ((ItemEquippable)weapon).ArchetypeData != null; ActiveFiringInfo = activeFiringInfo; } public static void CacheFiringMelee(MeleeWeaponFirstPerson weapon) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) FiringInfo activeFiringInfo = new FiringInfo(); activeFiringInfo.owner = ((Item)weapon).Owner; activeFiringInfo.slot = (InventorySlot)10; activeFiringInfo.isTagged = false; activeFiringInfo.cwc = ((Component)weapon).GetComponent(); activeFiringInfo.valid = true; ActiveFiringInfo = activeFiringInfo; } public static void CacheFiringSentry(SentryGunInstance sentry, bool isTagged) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) FiringInfo activeFiringInfo = new FiringInfo(); activeFiringInfo.owner = ((Item)sentry).Owner; activeFiringInfo.slot = (InventorySlot)3; activeFiringInfo.archBlock = ((ItemEquippable)sentry).ArchetypeData; activeFiringInfo.isTagged = isTagged; activeFiringInfo.cwc = ((Component)sentry).GetComponent(); activeFiringInfo.valid = ((ItemEquippable)sentry).ArchetypeData != null; ActiveFiringInfo = activeFiringInfo; } public static void ClearFiringInfo() { ActiveFiringInfo = default(FiringInfo); } public static bool BulletHit(IWeaponComp weapon, HitData data) { WeaponHitData obj = data.Apply(weapon.VanillaHitData); s_vanillaShotInfo = (((Il2CppObjectBase)obj).Pointer, data.shotInfo); FiringInfo activeFiringInfo = ActiveFiringInfo; if (weapon.IsType(WeaponType.BulletWeapon)) { CacheFiringGun(((IBulletWeaponComp)weapon).BulletWeapon); } else if (weapon.IsType(WeaponType.Melee)) { CacheFiringMelee(((MeleeComp)weapon).Value); } else { CacheFiringSentry(((SentryGunComp)weapon).Value, isTagged: false); } bool result = BulletWeapon.BulletHit(obj, true, 0f, 0u, true); ActiveFiringInfo = activeFiringInfo; return result; } public static void CancelTracerFX(CustomGunComponent cgc) { int val = 1; if (cgc.Gun.IsShotgun) { val = cgc.Gun.ArchetypeData.ShotgunBulletCount; } FX_Pool tracerPool = cgc.Gun.TracerPool; for (int num = Math.Min(val, tracerPool.m_inUse.Count); num > 0; num--) { List inUse = tracerPool.m_inUse; if (!((Object)(object)inUse[inUse.Count - 1]).TryCastOut(out FX_Effect result)) { break; } foreach (FX_EffectLinkBase item in (Il2CppArrayBase)(object)result.m_links) { FX_EffectBase_Poolable playingEffect = ((Il2CppObjectBase)item).Cast().m_playingEffect; if (playingEffect != null) { playingEffect.ReturnToPool(); } } ((FX_EffectBase_Poolable)result).ReturnToPool(); } } public static void ReceivePlayerDamage(PlayerAgent target, float damage, PlayerDamageType damageType, Vector3 dir, bool cameraShake = true) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) PlayerDamagePatches.SetPlayerDamageType(damageType); Dam_PlayerDamageBase damage2 = target.Damage; damage2.OnIncomingDamage(damage, damage, (Agent)null); if (((Agent)target).IsLocallyOwned) { ((Il2CppObjectBase)damage2).Cast().Hitreact(damage, dir, cameraShake, true, false); } } public static void DoHitmarker(CustomWeaponComponent cwc, ContextController cc, Dam_EnemyDamageLimb limb, bool crit, bool willKill, Vector3 hitPos, bool armor) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) PlayerAgent? player = cwc.Owner.Player; if (player != null && ((Agent)player).IsLocallyOwned) { EnemyLimbPatches.ShowHitmarker(cc, limb, crit, willKill, hitPos, armor); } } public static void AdvanceGroupMod(CustomWeaponComponent cwc, bool isTagged = false) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Invalid comparison between Unknown and I4 //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) s_lastShotTime = Clock.Time; s_lastGroupCWC = ((Il2CppObjectBase)cwc).Pointer; WeaponType type = cwc.Weapon.Type; PlayerAgent player = cwc.Owner.Player; CurrentGroupMod = new ShotInfoMod(); if (type.HasFlag(WeaponType.Sentry)) { CurrentExternalDamageMod = 1f; CurrentDamageMod = AgentModifierManager.ApplyModifier((Agent)(object)player, (AgentModifier)103, 1f); if (isTagged) { ArchetypeDataBlock archetypeData = cwc.Weapon.ArchetypeData; CurrentDamageMod *= archetypeData.Sentry_DamageTagMulti; CurrentStaggerMod *= archetypeData.Sentry_StaggerDamageTagMulti; } } else { if (type.HasFlag(WeaponType.BulletWeapon)) { AgentModifier val = (AgentModifier)(((int)cwc.Weapon.InventorySlot == 1) ? 70 : 71); CurrentExternalDamageMod = EXPAPIWrapper.GetDamageMod(cwc.Owner.IsType(OwnerType.Local), type); CurrentDamageMod = AgentModifierManager.ApplyModifier((Agent)(object)player, val, 1f); } else if (type.HasFlag(WeaponType.Melee)) { float num = ((((player != null) ? new float?(player.MeleeBuffTimer) : null) > Clock.Time) ? 3f : 1f); CurrentExternalDamageMod = EXPAPIWrapper.GetDamageMod(local: true, type) * num; CurrentDamageMod = AgentModifierManager.ApplyModifier((Agent)(object)player, (AgentModifier)200, 1f); } else { CurrentExternalDamageMod = 1f; CurrentDamageMod = 1f; } CurrentStaggerMod = 1f; } cwc.Invoke(new WeaponShotGroupInitContext(CurrentGroupMod)); } public static void AdvanceGroupModIfOld(CustomWeaponComponent cwc, bool isTagged) { float time = Clock.Time; if (!(((Il2CppObjectBase)cwc).Pointer == s_lastGroupCWC) || time != s_lastShotTime) { AdvanceGroupMod(cwc, isTagged); } } } public sealed class ShotStackMod : StackMod { private Dictionary>? _modsPerTarget; private Dictionary? _mods; private DamageType _lastType = DamageType.Invalid; private IntPtr _lastDamPtr = IntPtr.Zero; private bool _needType; private bool _needRecompute; private Dictionary> ModsPerTarget => _modsPerTarget ?? (_modsPerTarget = new Dictionary>(3)); private Dictionary Mods => _mods ?? (_mods = new Dictionary(3)); private static BaseDamageableWrapper TempWrapper => BaseDamageableWrapper.SharedInstance; public ShotStackMod(float min = 0f) : base(1f, min) { _mods = null; _modsPerTarget = null; } public ShotStackMod(ShotStackMod mod) : base(mod) { _mods = ((mod._mods != null) ? new Dictionary(mod._mods) : null); if (mod._modsPerTarget != null) { _modsPerTarget = new Dictionary>(mod._modsPerTarget); foreach (var (key, dictionary2) in mod._modsPerTarget) { _modsPerTarget[key] = new Dictionary(dictionary2); } } else { _modsPerTarget = null; } _needRecompute = mod._needRecompute; _needType = mod._needType; _lastDamPtr = mod._lastDamPtr; _lastType = mod._lastType; } public void AddMod(TriggerMod triggerMod, float mod, IDamageable? damageable = null, params DamageType[] types) { AddMod(triggerMod, mod, triggerMod.Cap, triggerMod.StackType, triggerMod.StackLayer, damageable, types); } public void AddMod(WeaponPropertyBase property, float mod, float cap, StackType stack, StackType layer, IDamageable? damageable = null, params DamageType[] types) { if (types.Length == 0) { types = DamageTypeConst.Any; } Dictionary dictionary; if (damageable != null) { if (!ModsPerTarget.TryGetValue(TempWrapper.Set(damageable), out Dictionary value)) { ModsPerTarget.Add(new BaseDamageableWrapper(TempWrapper), dictionary = new Dictionary(3)); } else { dictionary = value; } } else { dictionary = Mods; } if (dictionary.TryGetValue(property, out var value2)) { var (num, _, _) = value2; switch (stack) { case StackType.Override: value2.Item1 = mod; break; case StackType.Add: value2.Item1 += mod - 1f; break; case StackType.Multiply: value2.Item1 *= mod; break; case StackType.Max: value2.Item1 = Math.Max(value2.Item1, mod); break; case StackType.Min: value2.Item1 = Math.Min(value2.Item1, mod); break; } value2.Item1 = ((cap > 1f) ? Math.Min(value2.Item1, cap) : Math.Max(value2.Item1, cap)); if (num == value2.Item1) { return; } dictionary[property] = value2; } else { dictionary[property] = (mod, layer, types); } _needType = _needType || types.Length > 1 || (types.Length == 1 && types[0] != DamageType.Any); _needRecompute = true; } public void Reset(float min = 0f) { Reset(1f, min); } public bool HasMod(DamageType damageType = DamageType.Any, IDamageable? damageable = null) { if (_mods == null && _modsPerTarget == null) { return false; } IntPtr intPtr = ((damageable != null) ? ((Il2CppObjectBase)damageable).Pointer : IntPtr.Zero); if (!_needRecompute && (!_needType || _lastType == damageType) && (_modsPerTarget == null || _lastDamPtr == intPtr)) { return true; } _stackValue.Reset(); _lastDamPtr = intPtr; _lastType = damageType; _needRecompute = false; if (_mods != null) { foreach (var (mod, type, flagSet) in Mods.Values) { if (damageType.HasFlagIn(flagSet)) { AddMod(mod, type); } } } if (_modsPerTarget != null && intPtr != IntPtr.Zero) { TempWrapper.Set(damageable); if (ModsPerTarget.TryGetValue(TempWrapper, out Dictionary value)) { foreach (var (mod2, type2, flagSet2) in value.Values) { if (damageType.HasFlagIn(flagSet2)) { AddMod(mod2, type2); } } } } return true; } } public sealed class SpreadController { private Dictionary? _mods; private readonly bool _modifyCrosshair; private bool _active; private readonly StackMod _stackMod; private Dictionary Mods => _mods ?? (_mods = new Dictionary(3)); public bool Active { get { return _active; } set { if (_active != value && _modifyCrosshair) { _active = value; if (value) { ACAPIWrapper.UpdateCrosshairSpread(Value); } else { ACAPIWrapper.ResetCrosshairSpread(); } } } } public float Value => _stackMod.Value; public SpreadController(OwnerType owner, WeaponType weapon) { _stackMod = new StackMod(1f); _mods = null; _modifyCrosshair = owner.HasFlag(OwnerType.Local) && weapon.HasFlag(WeaponType.Gun); } public void Reset() { _stackMod.Reset(1f); _mods = null; if (Active) { ACAPIWrapper.ResetCrosshairSpread(); } } public void ClearMod(SpreadMod spreadMod, bool updateCrosshair = true) { Mods.Remove(spreadMod); Recompute(); if (updateCrosshair && Active) { ACAPIWrapper.UpdateCrosshairSpread(Value); } } public void SetMod(SpreadMod spreadMod, float newMod, bool updateCrosshair = true) { if (!Mods.TryGetValue(spreadMod, out var value) || value != newMod) { Mods[spreadMod] = newMod; Recompute(); if (updateCrosshair && Active) { ACAPIWrapper.UpdateCrosshairSpread(Value); } } } private void Recompute() { _stackMod.Reset(1f); foreach (var (spreadMod2, mod) in Mods) { _stackMod.AddMod(mod, spreadMod2.StackLayer); } } } } namespace EWC.CustomWeapon.ComponentWrapper { public abstract class OwnerComp : IOwnerComp where T : Object { public readonly T Value; public Transform MuzzleAlign { get; } public abstract eDimensionIndex DimensionIndex { get; } public abstract PlayerAgent? Player { get; } public abstract OwnerType Type { get; } public abstract AIG_CourseNode CourseNode { get; } public abstract Vector3 FirePos { get; } public abstract Vector3 FireDir { get; } public OwnerComp(T value, Transform muzzleAlign) { Value = value; MuzzleAlign = muzzleAlign; } } public interface IOwnerComp { Transform MuzzleAlign { get; } PlayerAgent? Player { get; } OwnerType Type { get; } AIG_CourseNode CourseNode { get; } Vector3 FirePos { get; } Vector3 FireDir { get; } eDimensionIndex DimensionIndex { get; } bool IsType(OwnerType type) { return Type.HasFlag(type); } bool IsAnyType(OwnerType type) { return Type.HasAnyFlag(type); } } public abstract class WeaponComp : IWeaponComp where T : ItemEquippable { public readonly T Value; public ItemEquippable Component => (ItemEquippable)(object)Value; public abstract WeaponType Type { get; } public abstract AmmoType AmmoType { get; } public virtual InventorySlot InventorySlot => AmmoType.ToInventorySlot(); public abstract CellSoundPlayer Sound { get; } public abstract bool AllowBackstab { get; } public virtual ArchetypeDataBlock ArchetypeData { get { throw new NotImplementedException("WeaponComp does not support ArchetypeData - is this called on an invalid weapon?"); } set { throw new NotImplementedException("WeaponComp does not support ArchetypeData - is this called on an invalid weapon?"); } } public virtual bool IsShotgun => false; public virtual bool IsAiming => false; public virtual WeaponHitData VanillaHitData { get { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown object obj = Weapon.s_weaponRayData; if (obj == null) { WeaponHitData val = new WeaponHitData(); Weapon.s_weaponRayData = val; obj = (object)val; } return (WeaponHitData)obj; } } public virtual FX_Pool TracerPool => BulletWeapon.s_tracerPool; public virtual float MaxRayDist { get; set; } = 100f; public WeaponComp(T value) { Value = value; } } public interface IWeaponComp { ItemEquippable Component { get; } WeaponType Type { get; } AmmoType AmmoType { get; } InventorySlot InventorySlot { get; } CellSoundPlayer Sound { get; } bool AllowBackstab { get; } ArchetypeDataBlock ArchetypeData { get; set; } bool IsShotgun { get; } bool IsAiming { get; } WeaponHitData VanillaHitData { get; } FX_Pool TracerPool { get; } float MaxRayDist { get; set; } bool IsType(WeaponType type) { return Type.HasFlag(type); } bool IsAnyType(WeaponType type) { return Type.HasAnyFlag(type); } } } namespace EWC.CustomWeapon.ComponentWrapper.WeaponComps { public abstract class BulletWeaponComp : GunComp, IBulletWeaponComp, IGunComp, IAmmoComp, IWeaponComp where T : BulletWeapon { private WeaponAudioDataBlock _audioData; private ArchetypeDataBlock _archetypeData; public override ArchetypeDataBlock ArchetypeData { get { return _archetypeData; } set { //IL_001a: Unknown result type (might be due to invalid IL or missing references) _archetypeData = value; ((ItemEquippable)(object)Value).ArchetypeData = value; base.FireMode = value.FireMode; } } public override WeaponAudioDataBlock AudioData { get { return _audioData; } set { _audioData = value; ((ItemEquippable)(object)Value).AudioData = value; ((Weapon)(object)Value).SetupAudioEvents(); } } public override WeaponHitData VanillaHitData => Weapon.s_weaponRayData; public override FX_Pool TracerPool => BulletWeapon.s_tracerPool; public override float MaxRayDist { get { return ((Weapon)(object)Value).MaxRayDist; } set { ((Weapon)(object)Value).MaxRayDist = value; } } public BulletWeapon BulletWeapon => (BulletWeapon)(object)Value; public override WeaponType Type => WeaponType.Gun | WeaponType.BulletWeapon; public override AmmoType AmmoType => ((ItemEquippable)(object)Value).AmmoType; public override CellSoundPlayer Sound => ((ItemEquippable)(object)Value).Sound; public override bool AllowBackstab => true; public BulletWeaponComp(T value, bool isShotgun) : base(value, isShotgun, ((ItemEquippable)(object)value).ArchetypeData.FireMode) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) _archetypeData = ((ItemEquippable)(object)Value).ArchetypeData; _audioData = ((ItemEquippable)(object)Value).AudioData; } public override int GetCurrentClip() { return ((ItemEquippable)(object)Value).GetCurrentClip(); } public override int GetMaxClip() { return ((ItemEquippable)(object)Value).GetMaxClip(); } public override void SetCurrentClip(int clip) { ((ItemEquippable)(object)Value).SetCurrentClip(clip); } } public interface IBulletWeaponComp : IGunComp, IAmmoComp, IWeaponComp { BulletWeapon BulletWeapon { get; } } public abstract class GunComp : WeaponComp, IGunComp, IAmmoComp, IWeaponComp where T : ItemEquippable { private readonly bool _isShotgun; public eWeaponFireMode FireMode { get; protected set; } public override bool IsShotgun => _isShotgun; public abstract WeaponAudioDataBlock AudioData { get; set; } public GunComp(T value, bool isShotgun, eWeaponFireMode fireMode) : base(value) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) _isShotgun = isShotgun; FireMode = fireMode; } public abstract int GetCurrentClip(); public abstract int GetMaxClip(); public abstract void SetCurrentClip(int clip); public abstract float ModifyFireRate(float lastFireTime, float shotDelay, float burstDelay, float cooldownDelay); } public interface IGunComp : IAmmoComp, IWeaponComp { WeaponAudioDataBlock AudioData { get; set; } eWeaponFireMode FireMode { get; } float ModifyFireRate(float lastFireTime, float shotDelay, float burstDelay, float cooldownDelay); } public interface IAmmoComp : IWeaponComp { int GetCurrentClip(); int GetMaxClip(); int GetMaxClip(out bool overflow) { overflow = false; return GetMaxClip(); } void SetCurrentClip(int clip); } public class LocalGunComp : BulletWeaponComp { private BulletWeaponArchetype _gunArchetype; private BWA_Burst? _burstArchetype; public BulletWeaponArchetype GunArchetype { get { return _gunArchetype; } set { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 Value.m_archeType = value; _gunArchetype = value; base.FireMode = ArchetypeData.FireMode; _burstArchetype = (((int)base.FireMode == 1) ? ((Il2CppObjectBase)value).Cast() : null); } } public override bool IsAiming => ((ItemEquippable)Value).FPItemHolder.ItemAimTrigger; public LocalGunComp(BulletWeapon value) : base(value, (Object)(object)((Il2CppObjectBase)value).TryCast() != (Object)null) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 _gunArchetype = value.m_archeType; _burstArchetype = (((int)base.FireMode == 1) ? ((Il2CppObjectBase)_gunArchetype).Cast() : null); } public bool TryGetBurstArchetype([MaybeNullWhen(false)] out BWA_Burst burstArchetype) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 burstArchetype = _burstArchetype; return (int)base.FireMode == 1; } public override float ModifyFireRate(float lastFireTime, float shotDelay, float burstDelay, float cooldownDelay) { burstDelay = Math.Max(shotDelay, burstDelay); GunArchetype.m_nextShotTimer = lastFireTime + shotDelay; if (GunArchetype.BurstIsDone()) { GunArchetype.m_nextBurstTimer = (GunArchetype.HasCooldown ? (lastFireTime + cooldownDelay) : Math.Max(lastFireTime + burstDelay, GunArchetype.m_nextShotTimer)); } FireRateAPI.FireCooldownSetCallback(Value, shotDelay, burstDelay, cooldownDelay); return Math.Max(GunArchetype.m_nextShotTimer, GunArchetype.m_nextBurstTimer); } } public class MeleeComp : WeaponComp { public override WeaponType Type => WeaponType.Melee; public override AmmoType AmmoType => (AmmoType)4; public override InventorySlot InventorySlot => (InventorySlot)10; public override CellSoundPlayer Sound => ((ItemEquippable)Value).Sound; public override bool AllowBackstab => true; public MeleeComp(MeleeWeaponFirstPerson value) : base(value) { } } public class SentryGunComp : GunComp { private WeaponAudioDataBlock _audioData; private ArchetypeDataBlock _archetypeData; private readonly CellSoundPlayer _sound; private bool _allowBackstab; public readonly SentryGunInstance_Firing_Bullets Firing; public readonly SentryGunInstance_Detection Detection; public bool IsFirstShot { get; set; } = true; public float CostOfBullet { get; private set; } public bool IsTargetTagged => Value.m_detection.TargetIsTagged; public override ArchetypeDataBlock ArchetypeData { get { return _archetypeData; } set { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (value != null) { if (value.FireMode != _archetypeData.FireMode) { ChangeFireMode(value); } _archetypeData = value; ((ItemEquippable)Value).ArchetypeData = value; Firing.m_archetypeData = value; Detection.m_archetypeData = value; base.FireMode = value.FireMode; CostOfBullet = _archetypeData.CostOfBullet * (float)Math.Max(1, _archetypeData.ShotgunBulletCount) * ((Item)Value).ItemDataBlock.ClassAmmoCostFactor; _allowBackstab = ETCWrapper.CanDoBackDamage(((GameDataBlockBase)(object)value).persistentID); if (IsShotgun) { Firing.m_segmentSize = MathUtil.DegreeToRadian(360f / ((float)value.ShotgunBulletCount - 1f)); } } } } public override WeaponAudioDataBlock AudioData { get { return _audioData; } set { if (value != null) { _audioData = value; Firing.m_audioData = value; Firing.m_audioFireSemi = BulletWeapon.GetRandomAudioEvents(value.eventOnSemiFire3D); Firing.m_audioFireBurst = BulletWeapon.GetRandomAudioEvents(value.eventOnBurstFire3D); Firing.m_audioFireAutoStart = BulletWeapon.GetRandomAudioEvents(value.eventOnAutoFireStart3D); Firing.m_audioFireAutoEnd = BulletWeapon.GetRandomAudioEvents(value.eventOnAutoFireEnd3D); Firing.m_audioChargeup = BulletWeapon.GetRandomAudioEvents(value.eventOnChargeup3D); Firing.m_audioCooldown = BulletWeapon.GetRandomAudioEvents(value.eventOnCooldown3D); } } } public override WeaponHitData VanillaHitData => SentryGunInstance_Firing_Bullets.s_weaponRayData; public override FX_Pool TracerPool => SentryGunInstance_Firing_Bullets.s_tracerPool; public override float MaxRayDist { get { return Firing.MaxRayDist; } set { Firing.MaxRayDist = value; } } public override bool IsAiming => false; public override AmmoType AmmoType => (AmmoType)2; public override WeaponType Type => WeaponType.Gun | WeaponType.Sentry; public override CellSoundPlayer Sound => _sound; public override bool AllowBackstab { get { if (!_allowBackstab) { return AllowBackstabOverride; } return true; } } public bool AllowBackstabOverride { get; set; } public SentryGunComp(SentryGunInstance value) : base(value, ((ItemEquippable)value).ArchetypeData.ShotgunBulletCount > 0, ((ItemEquippable)value).ArchetypeData.FireMode) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) _archetypeData = ((ItemEquippable)Value).ArchetypeData; _audioData = ((ItemEquippable)Value).AudioData; Firing = ((Il2CppObjectBase)Value.m_firing).Cast(); Detection = ((Il2CppObjectBase)Value.m_detection).Cast(); _sound = ((ItemEquippable)Value).Sound; CostOfBullet = _archetypeData.CostOfBullet * (float)Math.Max(1, _archetypeData.ShotgunBulletCount) * ((Item)Value).ItemDataBlock.ClassAmmoCostFactor; _allowBackstab = ETCWrapper.CanDoBackDamage(((GameDataBlockBase)(object)_archetypeData).persistentID); } private void ChangeFireMode(ArchetypeDataBlock newBlock) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected I4, but got Unknown Firing.m_playerAutoSoundLoop = false; eWeaponFireMode fireMode = newBlock.FireMode; switch ((int)fireMode) { case 0: if (IsShotgun && newBlock.ShotgunBulletCount > 0) { Firing.m_fireUpdateFunc = Action.op_Implicit((Action)Firing.UpdateFireShotgunSemi); } else { Firing.m_fireUpdateFunc = Action.op_Implicit((Action)Firing.UpdateFireSemi); } break; case 2: Firing.m_fireUpdateFunc = Action.op_Implicit((Action)Firing.UpdateFireAuto); Firing.m_playerAutoSoundLoop = true; break; case 1: Firing.m_fireUpdateFunc = Action.op_Implicit((Action)Firing.UpdateFireBurst); break; default: Firing.m_fireUpdateFunc = Action.op_Implicit((Action)Firing.UpdateFireAuto); Firing.m_playerAutoSoundLoop = true; break; } } public override int GetCurrentClip() { return (int)(Value.Ammo / CostOfBullet); } public override int GetMaxClip() { return (int)(Math.Max(Value.Ammo, Value.AmmoMaxCap) / CostOfBullet); } public int GetMaxClip(out bool overflow) { overflow = Value.Ammo > Value.AmmoMaxCap; return GetMaxClip(); } public override void SetCurrentClip(int clip) { int num = (int)(Value.Ammo / CostOfBullet); if (clip != num) { float num2 = Value.Ammo - (float)num * CostOfBullet; Value.Ammo = (float)clip * CostOfBullet + num2; Value.m_sync.ForceReliableAmmoUpdate(Value.Ammo); Firing.UpdateAmmo(0); } } public override float ModifyFireRate(float lastFireTime, float shotDelay, float burstDelay, float cooldownDelay) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 Firing.m_fireBulletTimer = lastFireTime + shotDelay; if ((int)base.FireMode == 1 && Firing.m_burstTimer > Clock.Time) { Firing.m_burstTimer = Clock.Time + burstDelay; } return Math.Max(Firing.m_fireBulletTimer, Firing.m_burstTimer); } } public class SentryHolderComp : WeaponComp, IAmmoComp, IWeaponComp { private ArchetypeDataBlock _archetypeData; public override WeaponType Type => WeaponType.SentryHolder; public override AmmoType AmmoType => ((ItemEquippable)Value).AmmoType; public override CellSoundPlayer Sound => ((ItemEquippable)Value).Sound; public override ArchetypeDataBlock ArchetypeData { get { return _archetypeData; } set { _archetypeData = value; ((ItemEquippable)Value).ArchetypeData = value; CostOfBullet = _archetypeData.CostOfBullet * (float)Math.Max(1, _archetypeData.ShotgunBulletCount) * ((Item)Value).ItemDataBlock.ClassAmmoCostFactor; } } public float CostOfBullet { get; private set; } public override bool AllowBackstab => true; public SentryHolderComp(SentryGunFirstPerson value) : base(value) { _archetypeData = ((ItemEquippable)value).ArchetypeData; CostOfBullet = _archetypeData.CostOfBullet * (float)Math.Max(1, _archetypeData.ShotgunBulletCount) * ((Item)Value).ItemDataBlock.ClassAmmoCostFactor; } public int GetCurrentClip() { return 0; } public int GetMaxClip() { return 0; } public void SetCurrentClip(int clip) { } } public class SyncedGunComp : BulletWeaponComp { public override bool IsAiming => true; public SyncedGunComp(BulletWeaponSynced value) : base(value, (Object)(object)((Il2CppObjectBase)value).TryCast() != (Object)null) { } public override float ModifyFireRate(float lastFireTime, float shotDelay, float burstDelay, float cooldownDelay) { return ((BulletWeapon)Value).m_lastFireTime = lastFireTime + shotDelay - ArchetypeData.ShotDelay; } } } namespace EWC.CustomWeapon.ComponentWrapper.OwnerComps { public class EmptyOwnerComp : OwnerComp { public override eDimensionIndex DimensionIndex => ((Agent)Value).DimensionIndex; public override PlayerAgent Player => Value; public override OwnerType Type => OwnerType.Any; public override AIG_CourseNode CourseNode => AIG_CourseNode.s_allNodes[0]; public override Vector3 FirePos => Vector3.zero; public override Vector3 FireDir => Vector3.zero; public EmptyOwnerComp() : base(PlayerManager.GetLocalPlayerAgent(), ((Component)Global.Current).transform) { } } public sealed class LocalOwnerComp : OwnerComp { public override eDimensionIndex DimensionIndex => ((Agent)Value).DimensionIndex; public override PlayerAgent Player => Value; public override OwnerType Type => OwnerType.Managed | OwnerType.Local | OwnerType.Player; public override AIG_CourseNode CourseNode => ((Agent)Value).CourseNode; public override Vector3 FirePos => Value.FPSCamera.Position; public override Vector3 FireDir => Value.FPSCamera.CameraRayDir; public LocalOwnerComp(PlayerAgent agent, Transform muzzleAlign) : base(agent, muzzleAlign) { } } public sealed class SentryOwnerComp : OwnerComp { private readonly OwnerType _type; public override eDimensionIndex DimensionIndex => CourseNode.m_dimension.DimensionIndex; public override PlayerAgent Player => ((Item)Value).Owner; public override OwnerType Type => _type; public override AIG_CourseNode CourseNode => Value.CourseNode; public override Vector3 FirePos => base.MuzzleAlign.position; public override Vector3 FireDir => base.MuzzleAlign.forward; public SentryOwnerComp(SentryGunInstance sentry) : base(sentry, ((ItemEquippable)sentry).MuzzleAlign) { _type = OwnerType.Sentry; if (SNet.IsMaster) { _type |= OwnerType.Managed; } else { _type |= OwnerType.Unmanaged; } } } public sealed class SyncedOwnerComp : OwnerComp { private readonly OwnerType _type; public override eDimensionIndex DimensionIndex => ((Agent)Value).DimensionIndex; public override PlayerAgent Player => Value; public override OwnerType Type => _type; public override AIG_CourseNode CourseNode => ((Agent)Value).CourseNode; public override Vector3 FirePos => base.MuzzleAlign.position; public override Vector3 FireDir => base.MuzzleAlign.forward; public SyncedOwnerComp(PlayerAgent agent, Transform muzzleAlign) : base(agent, muzzleAlign) { _type = OwnerType.Player; if (agent.Owner.IsBot && SNet.IsMaster) { _type |= OwnerType.Managed; } else { _type |= OwnerType.Unmanaged; } } } } namespace EWC.Attributes { [AttributeUsage(AttributeTargets.Method)] internal sealed class InvokeOnAssetLoadAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] internal sealed class InvokeOnBuildDoneAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] internal sealed class InvokeOnCheckpointAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] internal sealed class InvokeOnCleanupAttribute : Attribute { public bool OnCheckpoint { get; set; } public InvokeOnCleanupAttribute(bool onCheckpoint = false) { OnCheckpoint = onCheckpoint; } } [AttributeUsage(AttributeTargets.Method)] internal sealed class InvokeOnEnterAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] internal sealed class InvokeOnLoadAttribute : Attribute { } } namespace EWC.API { public static class DamageAPI { public delegate void DamageCallback(float damage, EnemyAgent enemy, Dam_EnemyDamageLimb limb, PlayerAgent? source, OwnerType ownerType); public static event DamageCallback? PreDOTDamage; public static event DamageCallback? PostDOTDamage; public static event DamageCallback? PreExplosiveDamage; public static event DamageCallback? PostExplosiveDamage; public static event DamageCallback? PreShrapnelDamage; public static event DamageCallback? PostShrapnelDamage; internal static void FirePreDOTCallbacks(float damage, EnemyAgent enemy, Dam_EnemyDamageLimb limb, PlayerAgent? source, OwnerType ownerType) { DamageAPI.PreDOTDamage?.Invoke(damage, enemy, limb, source, ownerType); } internal static void FirePostDOTCallbacks(float damage, EnemyAgent enemy, Dam_EnemyDamageLimb limb, PlayerAgent? source, OwnerType ownerType) { DamageAPI.PostDOTDamage?.Invoke(damage, enemy, limb, source, ownerType); } internal static void FirePreExplosiveCallbacks(float damage, EnemyAgent enemy, Dam_EnemyDamageLimb limb, PlayerAgent? source, OwnerType ownerType) { DamageAPI.PreExplosiveDamage?.Invoke(damage, enemy, limb, source, ownerType); } internal static void FirePostExplosiveCallbacks(float damage, EnemyAgent enemy, Dam_EnemyDamageLimb limb, PlayerAgent? source, OwnerType ownerType) { DamageAPI.PostExplosiveDamage?.Invoke(damage, enemy, limb, source, ownerType); } internal static void FirePreShrapnelCallbacks(float damage, EnemyAgent enemy, Dam_EnemyDamageLimb limb, PlayerAgent? source, OwnerType ownerType) { DamageAPI.PreShrapnelDamage?.Invoke(damage, enemy, limb, source, ownerType); } internal static void FirePostShrapnelCallbacks(float damage, EnemyAgent enemy, Dam_EnemyDamageLimb limb, PlayerAgent? source, OwnerType ownerType) { DamageAPI.PostShrapnelDamage?.Invoke(damage, enemy, limb, source, ownerType); } } public static class DataAPI { public static void ReadDirectory(string directory, bool liveEdit = true) { if (!string.IsNullOrEmpty(directory)) { CustomDataManager.Current.ReadDirectory(directory, liveEdit); } } } public static class ExplosionAPI { public delegate void ExplosionSpawnedCallback(Vector3 position, Explosive property); public static event ExplosionSpawnedCallback? OnExplosionSpawned; internal static void FireExplosionSpawnedCallback(Vector3 position, Explosive property) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) ExplosionAPI.OnExplosionSpawned?.Invoke(position, property); } } public static class FireRateAPI { public delegate void CooldownSetCallback(BulletWeapon weapon, float shotDelay, float burstDelay, float cooldownDelay); public delegate void CooldownInterruptCallback(BulletWeapon weapon); public static event CooldownSetCallback? CooldownSet; public static event CooldownInterruptCallback? CooldownInterrupt; internal static void FireCooldownSetCallback(BulletWeapon weapon, float shotDelay, float burstDelay, float cooldownDelay) { FireRateAPI.CooldownSet?.Invoke(weapon, shotDelay, burstDelay, cooldownDelay); } internal static void FireCooldownInterruptCallback(BulletWeapon weapon) { FireRateAPI.CooldownInterrupt?.Invoke(weapon); } } public static class FireShotAPI { public delegate void PreShotFiredCallback(HitData hitData, Ray ray, WeaponType weaponType); public delegate void ShotFiredCallback(HitData hitData, Vector3 startPos, Vector3 endPos, WeaponType weaponType); public static event PreShotFiredCallback? PreShotFired; public static event ShotFiredCallback? OnShotFired; internal static void FirePreShotFiredCallback(HitData hitData, Ray ray, WeaponType weaponType) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) FireShotAPI.PreShotFired?.Invoke(hitData, ray, weaponType); } internal static void FireShotFiredCallback(HitData hitData, Vector3 startPos, Vector3 endPos, WeaponType weaponType) { //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) FireShotAPI.OnShotFired?.Invoke(hitData, startPos, endPos, weaponType); } } public static class NativePatchAPI { public delegate bool DetectOnNoisePrefix(EnemyDetection __instance, AgentTarget agentTarget, float movementDetectionDistance, float shootDetectionDistance, float delta, ref float output); public delegate void DetectOnNoisePostfix(EnemyDetection __instance, AgentTarget agentTarget, float movementDetectionDistance, float shootDetectionDistance, float delta, ref float output); private static readonly List s_detectPrefix = new List(); private static readonly List s_detectPostfix = new List(); public static bool Loaded => EntryPoint.Loaded; public static void AddDetectPrefix(DetectOnNoisePrefix detectPrefix) { s_detectPrefix.Add(detectPrefix); } public static void AddDetectPostfix(DetectOnNoisePostfix detectPostfix) { s_detectPostfix.Add(detectPostfix); } internal static bool RunDetectPrefix(EnemyDetection __instance, AgentTarget agentTarget, float movementDetectionDistance, float shootDetectionDistance, float delta, ref float output) { bool flag = true; foreach (DetectOnNoisePrefix item in s_detectPrefix) { flag &= item(__instance, agentTarget, movementDetectionDistance, shootDetectionDistance, delta, ref output); } return flag; } internal static void RunDetectPostfix(EnemyDetection __instance, AgentTarget agentTarget, float movementDetectionDistance, float shootDetectionDistance, float delta, ref float output) { foreach (DetectOnNoisePostfix item in s_detectPostfix) { item(__instance, agentTarget, movementDetectionDistance, shootDetectionDistance, delta, ref output); } } } public static class ProjectileAPI { public delegate void ProjectileCallback(EWCProjectileComponentBase projectile); public delegate void ProjectileHitCallback(EWCProjectileComponentBase projectile, IDamageable? damageable); public static event ProjectileCallback? OnProjectileSpawned; public static event ProjectileHitCallback? OnProjectileHit; public static event ProjectileCallback? OnProjectileDestroyed; internal static void FireProjectileSpawnedCallback(EWCProjectileComponentBase projectile) { ProjectileAPI.OnProjectileSpawned?.Invoke(projectile); } internal static void FireProjectileHitCallback(EWCProjectileComponentBase projectile, IDamageable? damageable) { ProjectileAPI.OnProjectileHit?.Invoke(projectile, damageable); } internal static void FireProjectileDestroyedCallback(EWCProjectileComponentBase projectile) { ProjectileAPI.OnProjectileDestroyed?.Invoke(projectile); } } }