using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.Json; using System.Text.Json.Serialization; using BepInEx; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Microsoft.CodeAnalysis; using ProjectM; using ProjectM.Gameplay.Systems; using ProjectM.Gameplay.WarEvents; using ProjectM.Network; using ProjectM.Scripting; using ProjectM.Shared; using Stunlock.Core; using Stunlock.Network; using Unity.Collections; using Unity.Entities; using UnityEngine; using VampireCommandFramework; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("HexesAndSanguineSteel")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Server-side V Rising custom weapon, spell override, stat, weapon-type buff, and school on-hit mod.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("HexesAndSanguineSteel")] [assembly: AssemblyTitle("HexesAndSanguineSteel")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HexesAndSanguineSteel { [HarmonyPatch(typeof(WarEventRegistrySystem), "RegisterWarEventEntities")] internal static class Bootstrap { private static ManualLogSource? _log; private static bool _initialized; internal static void Initialize(Harmony harmony, ManualLogSource log) { _log = log; harmony.CreateClassProcessor(typeof(Bootstrap)).Patch(); } [HarmonyPostfix] private static void Postfix() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown if (_initialized) { return; } _initialized = true; try { CustomWeaponRegistry.ApplyAll(); RuntimeOptimization.InfoOnce("bootstrap-prefab-mutations", "Hexes and Sanguine Steel bootstrap completed; runtime systems registered."); } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(32, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Custom weapon bootstrap failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } log.LogError(val); } } } } internal static class CustomWeaponConfig { internal const int DefaultRuntimeCarrierBuff = -1721561549; internal const int DefaultRuntimeStatCarrierBuff = -1122472005; private const string DirectoryName = "HexesAndSanguineSteel"; private const string LegacyDirectoryName = "CustomWeaponMod"; private const string FileName = "weapons.json"; private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { WriteIndented = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true, PropertyNameCaseInsensitive = true }; private static WeaponConfigFile? _currentFile; private static IReadOnlyList _currentDefinitions = Array.Empty(); private static IReadOnlyList _currentTypeBuffDefinitions = Array.Empty(); private static IReadOnlyList _globalUpgradeCost = Array.Empty(); internal static string ConfigDirectory => Path.Combine(Paths.ConfigPath, "HexesAndSanguineSteel"); internal static string ConfigPath => Path.Combine(ConfigDirectory, "weapons.json"); private static string LegacyConfigDirectory => Path.Combine(Paths.ConfigPath, "CustomWeaponMod"); private static string LegacyConfigPath => Path.Combine(LegacyConfigDirectory, "weapons.json"); internal static int CustomWeaponCarrierBuff => _currentFile?.DefaultCustomWeaponCarrierBuff ?? (-1721561549); internal static int CustomWeaponStatCarrierBuff => _currentFile?.DefaultCustomWeaponStatCarrierBuff ?? (-1122472005); internal static IReadOnlyList WeaponTypeBuffs => _currentTypeBuffDefinitions; internal static IReadOnlyList GlobalUpgradeCost => _globalUpgradeCost; internal static bool DebugLogging => _currentFile?.DebugLogging ?? false; internal static double AdminRefreshCooldownSeconds => _currentFile?.AdminRefreshCooldownSeconds ?? 5.0; private static void CopyLegacyConfigIfNeeded() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (!File.Exists(ConfigPath) && File.Exists(LegacyConfigPath)) { Directory.CreateDirectory(ConfigDirectory); File.Copy(LegacyConfigPath, ConfigPath, overwrite: false); ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(70, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Migrated legacy CustomWeaponMod config file to HexesAndSanguineSteel: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigPath); } logInstance.LogInfo(val); } } internal static IReadOnlyList LoadOrCreate() { //IL_05ef: Unknown result type (might be due to invalid IL or missing references) //IL_05f6: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_066e: Expected O, but got Unknown Directory.CreateDirectory(ConfigDirectory); CopyLegacyConfigIfNeeded(); bool flag = default(bool); if (!File.Exists(ConfigPath)) { _currentFile = WeaponConfigFile.CreateDefault(); _currentDefinitions = _currentFile.ToDefinitions(); _currentTypeBuffDefinitions = _currentFile.ToWeaponTypeBuffDefinitions(); _globalUpgradeCost = _currentFile.ToGlobalUpgradeCost(); Save(_currentFile); ManualLogSource logInstance = Plugin.LogInstance; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(30, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Created custom weapon config: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigPath); } logInstance.LogInfo(val); return _currentDefinitions; } try { WeaponConfigFile weaponConfigFile = JsonSerializer.Deserialize(File.ReadAllText(ConfigPath), JsonOptions); if (weaponConfigFile == null) { weaponConfigFile = WeaponConfigFile.CreateDefault(); Save(weaponConfigFile); } WeaponConfigFile weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.Weapons == null) { List list = (weaponConfigFile2.Weapons = new List()); } weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.WeaponTypeBuffs == null) { List list3 = (weaponConfigFile2.WeaponTypeBuffs = new List()); } weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.GlobalUpgradeCost == null) { List list5 = (weaponConfigFile2.GlobalUpgradeCost = new List()); } bool flag2 = false; if (weaponConfigFile.ConfigVersion < 6) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 6; flag2 = true; if (weaponConfigFile.DefaultCustomWeaponCarrierBuff == 0) { weaponConfigFile.DefaultCustomWeaponCarrierBuff = -1721561549; } if (weaponConfigFile.DefaultCustomWeaponStatCarrierBuff == 0) { weaponConfigFile.DefaultCustomWeaponStatCarrierBuff = -1122472005; } Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v6. Custom weapon stats are now applied with runtime stat carrier buffs."); } if (weaponConfigFile.ConfigVersion < 7) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 7; weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.WeaponTypeBuffs == null) { List list3 = (weaponConfigFile2.WeaponTypeBuffs = new List()); } flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v7. Added WeaponTypeBuffs[] using the same runtime stat carrier."); } if (weaponConfigFile.ConfigVersion < 8) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 9; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v8. Custom weapons can now override R and C slots."); } if (weaponConfigFile.ConfigVersion < 10) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 10; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v10. Legacy PhysicalPower/SpellPower are ignored when Stats[] is non-empty; generated configs set them to 0 to avoid double-stat confusion."); } if (weaponConfigFile.ConfigVersion < 11) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 11; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v11. Added DebugLogging and AdminRefreshCooldownSeconds for lower-noise live operation."); } if (weaponConfigFile.ConfigVersion < 12) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 12; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v12. Added per-weapon UpgradeCost[] consumed by .csw upgrade."); } if (weaponConfigFile.ConfigVersion < 13) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 13; weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.GlobalUpgradeCost == null) { List list5 = (weaponConfigFile2.GlobalUpgradeCost = new List()); } flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v13. Added GlobalUpgradeCost[] used as the default cost for every .csw upgrade."); } if (weaponConfigFile.ConfigVersion < 14) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 14; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v14. Removed per-weapon UpgradeCost[]; .csw upgrade now uses GlobalUpgradeCost only."); } if (weaponConfigFile.ConfigVersion < 15) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 15; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v15. Added custom weapon OnHitEffects[] for spell-school/coating-style procs."); } if (weaponConfigFile.ConfigVersion < 16) { BackupPreMigrationConfig(weaponConfigFile.ConfigVersion); weaponConfigFile.ConfigVersion = 16; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded weapons.json to schema v16. Removed SecondaryBuff on-hit behavior; OnHitEffects now apply only the Bloodcraft class school debuffs."); } if (weaponConfigFile.DefaultCustomWeaponCarrierBuff == 0) { weaponConfigFile.DefaultCustomWeaponCarrierBuff = -1721561549; flag2 = true; } if (weaponConfigFile.DefaultCustomWeaponStatCarrierBuff == 0) { weaponConfigFile.DefaultCustomWeaponStatCarrierBuff = -1122472005; flag2 = true; } weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.GlobalUpgradeCost == null) { List list5 = (weaponConfigFile2.GlobalUpgradeCost = new List()); } foreach (WeaponConfigEntry weapon in weaponConfigFile.Weapons) { if (weapon.SpellSlot1 == 0 && weapon.R != 0) { weapon.SpellSlot1 = weapon.R; weapon.SpellSlot1Cooldown = weapon.RCooldown; weapon.R = 0; weapon.RCooldown = 0f; flag2 = true; } if (weapon.SpellSlot2 == 0 && weapon.C != 0) { weapon.SpellSlot2 = weapon.C; weapon.SpellSlot2Cooldown = weapon.CCooldown; weapon.C = 0; weapon.CCooldown = 0f; flag2 = true; } WeaponConfigEntry weaponConfigEntry = weapon; if (weaponConfigEntry.Stats == null) { List list10 = (weaponConfigEntry.Stats = new List()); } weaponConfigEntry = weapon; if (weaponConfigEntry.OnHitEffects == null) { List list12 = (weaponConfigEntry.OnHitEffects = new List()); } if (weapon.Stats.Count == 0) { if (weapon.PhysicalPower != 0f) { weapon.Stats.Add(new WeaponStatConfigEntry { StatType = "PhysicalPower", ModificationType = "AddToBase", AttributeCapType = "SoftCapped", Value = weapon.PhysicalPower }); } if (weapon.SpellPower != 0f) { weapon.Stats.Add(new WeaponStatConfigEntry { StatType = "SpellPower", ModificationType = "AddToBase", AttributeCapType = "SoftCapped", Value = weapon.SpellPower }); } if (weapon.Stats.Count > 0) { flag2 = true; } } if (weapon.Stats.Count > 0 && (weapon.PhysicalPower != 0f || weapon.SpellPower != 0f)) { weapon.PhysicalPower = 0f; weapon.SpellPower = 0f; flag2 = true; } } if (flag2) { Save(weaponConfigFile); } _currentFile = weaponConfigFile; _currentDefinitions = weaponConfigFile.ToDefinitions(); _currentTypeBuffDefinitions = weaponConfigFile.ToWeaponTypeBuffDefinitions(); _globalUpgradeCost = weaponConfigFile.ToGlobalUpgradeCost(); return _currentDefinitions; } catch (Exception ex) { string text = ConfigPath + ".broken"; try { if (File.Exists(text)) { File.Delete(text); } if (File.Exists(ConfigPath)) { File.Move(ConfigPath, text); } } catch (Exception ex2) { ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not back up broken config: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex2.Message); } logInstance2.LogWarning(val2); } _currentFile = WeaponConfigFile.CreateDefault(); _currentDefinitions = _currentFile.ToDefinitions(); _currentTypeBuffDefinitions = _currentFile.ToWeaponTypeBuffDefinitions(); _globalUpgradeCost = _currentFile.ToGlobalUpgradeCost(); Save(_currentFile); ManualLogSource logInstance3 = Plugin.LogInstance; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(92, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Failed to read custom weapon config. Backed up broken file to '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' and wrote defaults. Error: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex); } logInstance3.LogError(val3); return _currentDefinitions; } } private static void BackupPreMigrationConfig(int oldVersion) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown try { string text = ConfigPath + $".v{oldVersion}.backup"; if (File.Exists(text)) { File.Delete(text); } if (File.Exists(ConfigPath)) { File.Copy(ConfigPath, text); } } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(48, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not create weapons.json migration backup: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logInstance.LogWarning(val); } } private static void Save(WeaponConfigFile config) { Directory.CreateDirectory(ConfigDirectory); File.WriteAllText(ConfigPath, JsonSerializer.Serialize(config, JsonOptions)); } } internal sealed class WeaponConfigFile { public int ConfigVersion { get; set; } = 16; public bool DebugLogging { get; set; } public double AdminRefreshCooldownSeconds { get; set; } = 5.0; public int DefaultCustomWeaponCarrierBuff { get; set; } = -1721561549; public int DefaultCustomWeaponStatCarrierBuff { get; set; } = -1122472005; public List GlobalUpgradeCost { get; set; } = new List(); public List Weapons { get; set; } = new List(); public List WeaponTypeBuffs { get; set; } = new List(); public static WeaponConfigFile CreateDefault() { return new WeaponConfigFile { ConfigVersion = 16, DefaultCustomWeaponCarrierBuff = -1721561549, DefaultCustomWeaponStatCarrierBuff = -1122472005, GlobalUpgradeCost = new List(), WeaponTypeBuffs = new List(1) { new WeaponTypeBuffConfigEntry { Enabled = false, WeaponType = "Mace", ApplyToCustomWeapons = true, Stats = new List(1) { new WeaponStatConfigEntry { StatType = "AttackSpeed", ModificationType = "AddToBase", AttributeCapType = "SoftCapped", Value = 0.1f } } } }, Weapons = new List(1) { new WeaponConfigEntry { Enabled = true, Name = "Crimson Thorns", ItemWeapon = 1307774440, EquipBuff = 673013659, WeaponLevel = 100f, PhysicalPower = 0f, SpellPower = 0f, Stats = new List(3) { new WeaponStatConfigEntry { StatType = "PhysicalPower", ModificationType = "AddToBase", AttributeCapType = "SoftCapped", Value = 35f }, new WeaponStatConfigEntry { StatType = "SpellPower", ModificationType = "AddToBase", AttributeCapType = "SoftCapped", Value = 10f }, new WeaponStatConfigEntry { StatType = "PhysicalResistance", ModificationType = "AddToBase", AttributeCapType = "SoftCapped", Value = 6f } }, OnHitEffects = new List(), Attack = -208121356, AttackCooldown = 0f, Primary = 1826128809, PrimaryCooldown = 8f, Secondary = 1730729556, SecondaryCooldown = 10f, Dash = -1940289109, DashCooldown = 6f, Ultimate = -1730693034, UltimateCooldown = 60f, SpellSlot1 = 841757706, SpellSlot1Cooldown = 8f, SpellSlot2 = 1295370119, SpellSlot2Cooldown = 8f } } }; } public IReadOnlyList ToDefinitions() { List list = new List(); foreach (WeaponConfigEntry weapon in Weapons) { if (weapon.Enabled) { list.Add(weapon.ToDefinition(DefaultCustomWeaponCarrierBuff, DefaultCustomWeaponStatCarrierBuff)); } } return list; } public IReadOnlyList ToGlobalUpgradeCost() { if (GlobalUpgradeCost == null) { List list = (GlobalUpgradeCost = new List()); } return WeaponConfigEntry.BuildUpgradeCost("GlobalUpgradeCost", GlobalUpgradeCost); } public IReadOnlyList ToWeaponTypeBuffDefinitions() { List list = new List(); foreach (WeaponTypeBuffConfigEntry weaponTypeBuff in WeaponTypeBuffs) { if (weaponTypeBuff.Enabled) { WeaponTypeBuffConfigEntry weaponTypeBuffConfigEntry = weaponTypeBuff; if (weaponTypeBuffConfigEntry.Stats == null) { List list2 = (weaponTypeBuffConfigEntry.Stats = new List()); } list.Add(new WeaponTypeBuffDef(weaponTypeBuff.WeaponType, weaponTypeBuff.ApplyToCustomWeapons, StatConfigBuilder.BuildStats("WeaponTypeBuff:" + weaponTypeBuff.WeaponType, weaponTypeBuff.Stats))); } } return list; } } internal sealed class WeaponConfigEntry { public bool Enabled { get; set; } = true; public string Name { get; set; } = "Custom Weapon"; public int ItemWeapon { get; set; } public int EquipBuff { get; set; } public int CarrierBuff { get; set; } public int StatCarrierBuff { get; set; } public float WeaponLevel { get; set; } = 100f; public float PhysicalPower { get; set; } = 35f; public float SpellPower { get; set; } = 10f; public List Stats { get; set; } = new List(); public List OnHitEffects { get; set; } = new List(); [JsonIgnore] public List UpgradeCost { get; set; } = new List(); public int Attack { get; set; } public float AttackCooldown { get; set; } public int Primary { get; set; } public float PrimaryCooldown { get; set; } public int Secondary { get; set; } public float SecondaryCooldown { get; set; } public int Dash { get; set; } public float DashCooldown { get; set; } public int Ultimate { get; set; } public float UltimateCooldown { get; set; } [JsonPropertyName("Spell Slot 1")] public int SpellSlot1 { get; set; } [JsonPropertyName("Spell Slot 1 Cooldown")] public float SpellSlot1Cooldown { get; set; } [JsonPropertyName("Spell Slot 2")] public int SpellSlot2 { get; set; } [JsonPropertyName("Spell Slot 2 Cooldown")] public float SpellSlot2Cooldown { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public int R { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public float RCooldown { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public int C { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public float CCooldown { get; set; } public CustomWeaponDef ToDefinition(int defaultCarrierBuff, int defaultStatCarrierBuff) { //IL_000c: 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_002d: 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) return new CustomWeaponDef(Name, Guid(ItemWeapon), Guid(EquipBuff), Guid((CarrierBuff != 0) ? CarrierBuff : defaultCarrierBuff), Guid((StatCarrierBuff != 0) ? StatCarrierBuff : defaultStatCarrierBuff), Array.Empty(), new WeaponPowerDef(WeaponLevel, PhysicalPower, SpellPower), StatConfigBuilder.BuildStats(Name, Stats), BuildOnHitEffects(Name, OnHitEffects), Slot(Attack, AttackCooldown), Slot(Primary, PrimaryCooldown), Slot(Secondary, SecondaryCooldown), Slot(Dash, DashCooldown), Slot(Ultimate, UltimateCooldown), Slot(SpellSlot1, SpellSlot1Cooldown), Slot(SpellSlot2, SpellSlot2Cooldown)); } private static IReadOnlyList BuildStats(string weaponName, List stats) { //IL_00e7: 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) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (WeaponStatConfigEntry stat in stats) { ModificationType result2; AttributeCapType result3; if (!Enum.TryParse(stat.StatType, ignoreCase: true, out UnitStatType result)) { RuntimeOptimization.WarnOnce("stat-unknown:" + weaponName + ":" + stat.StatType, weaponName + ": unknown UnitStatType '" + stat.StatType + "'. Stat entry skipped."); } else if (!Enum.TryParse(stat.ModificationType, ignoreCase: true, out result2)) { RuntimeOptimization.WarnOnce("modtype-unknown:" + weaponName + ":" + stat.ModificationType, weaponName + ": unknown ModificationType '" + stat.ModificationType + "'. Stat entry skipped."); } else if (!Enum.TryParse(stat.AttributeCapType, ignoreCase: true, out result3)) { RuntimeOptimization.WarnOnce("captype-unknown:" + weaponName + ":" + stat.AttributeCapType, weaponName + ": unknown AttributeCapType '" + stat.AttributeCapType + "'. Stat entry skipped."); } else { list.Add(new CustomWeaponStatDef(result, result2, result3, stat.Value)); } } return list; } private static IReadOnlyList BuildOnHitEffects(string weaponName, List effects) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if (effects == null) { effects = new List(); } foreach (WeaponOnHitEffectConfigEntry effect in effects) { if (effect.Enabled && !(effect.Chance <= 0f)) { if (effect.TargetBuff == 0) { RuntimeOptimization.WarnOnce("onhit-target0:" + weaponName + ":" + effect.Name, weaponName + ": on-hit effect '" + effect.Name + "' has TargetBuff 0. Effect skipped."); continue; } list.Add(new CustomWeaponOnHitEffectDef(string.IsNullOrWhiteSpace(effect.Name) ? $"OnHit:{effect.TargetBuff}" : effect.Name, effect.School ?? string.Empty, Math.Clamp(effect.Chance, 0f, 1f), Guid(effect.TargetBuff), effect.AffectPlayers, effect.AffectNonPlayers)); } } return list; } internal static IReadOnlyList BuildUpgradeCost(string weaponName, List costs) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if (costs == null) { costs = new List(); } bool flag = default(bool); foreach (WeaponUpgradeCostConfigEntry cost in costs) { if (cost.Amount <= 0) { ManualLogSource logInstance = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(63, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(weaponName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": upgrade cost '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(cost.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' has non-positive Amount "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(cost.Amount); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Cost entry skipped."); } logInstance.LogWarning(val); } else if (cost.Item == 0) { ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(49, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(weaponName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": upgrade cost '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(cost.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' has Item 0. Cost entry skipped."); } logInstance2.LogWarning(val); } else { list.Add(new CustomWeaponCostDef(string.IsNullOrWhiteSpace(cost.Name) ? cost.Item.ToString() : cost.Name, Guid(cost.Item), cost.Amount)); } } return list; } private static PrefabGUID Guid(int hash) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new PrefabGUID(hash); } private static AbilitySlotDef Slot(int guidHash, float cooldown) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new AbilitySlotDef(Guid(guidHash), cooldown); } } internal sealed class WeaponOnHitEffectConfigEntry { public bool Enabled { get; set; } = true; public string Name { get; set; } = string.Empty; public string School { get; set; } = string.Empty; public float Chance { get; set; } = 0.15f; public int TargetBuff { get; set; } public bool AffectPlayers { get; set; } public bool AffectNonPlayers { get; set; } = true; } internal sealed class WeaponUpgradeCostConfigEntry { public string Name { get; set; } = string.Empty; public int Item { get; set; } public int Amount { get; set; } } internal sealed class WeaponTypeBuffConfigEntry { public bool Enabled { get; set; } = true; public string WeaponType { get; set; } = "Mace"; public bool ApplyToCustomWeapons { get; set; } = true; public List Stats { get; set; } = new List(); } internal static class StatConfigBuilder { private static readonly Dictionary UnitStatAliases = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["AS"] = "PrimaryAttackSpeed", ["AttackSpeed"] = "PrimaryAttackSpeed", ["PrimaryAttackSpeed"] = "PrimaryAttackSpeed", ["AAS"] = "AbilityAttackSpeed", ["AbilitySpeed"] = "AbilityAttackSpeed", ["AbilityAttackSpeed"] = "AbilityAttackSpeed", ["MS"] = "MovementSpeed", ["MoveSpeed"] = "MovementSpeed", ["MovementSpeed"] = "MovementSpeed" }; private static readonly Dictionary AttributeCapAliases = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["UnCapped"] = "Uncapped", ["Uncapped"] = "Uncapped", ["NoCap"] = "Uncapped", ["NoCaps"] = "Uncapped", ["IgnoreCap"] = "Uncapped", ["IgnoreCaps"] = "Uncapped", ["None"] = "Uncapped" }; internal static IReadOnlyList BuildStats(string ownerName, List stats) { //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (WeaponStatConfigEntry stat in stats) { if (!TryParseUnitStatType(stat.StatType, out UnitStatType value, out string resolvedName)) { RuntimeOptimization.WarnOnce("stat-unknown:" + ownerName + ":" + stat.StatType, ownerName + ": unknown UnitStatType '" + stat.StatType + "'. Stat entry skipped. Run .csw stattypes or use aliases like AttackSpeed/AS -> PrimaryAttackSpeed."); continue; } if (!Enum.TryParse(stat.ModificationType, ignoreCase: true, out ModificationType result)) { RuntimeOptimization.WarnOnce("modtype-unknown:" + ownerName + ":" + stat.ModificationType, ownerName + ": unknown ModificationType '" + stat.ModificationType + "'. Stat entry skipped."); continue; } if (!TryParseAttributeCapType(stat.AttributeCapType, out AttributeCapType value2, out string resolvedName2)) { RuntimeOptimization.WarnOnce("captype-unknown:" + ownerName + ":" + stat.AttributeCapType, ownerName + ": unknown AttributeCapType '" + stat.AttributeCapType + "'. Stat entry skipped."); continue; } if (!string.Equals(stat.StatType, resolvedName, StringComparison.OrdinalIgnoreCase)) { RuntimeOptimization.Debug($"{ownerName}: mapped UnitStatType alias '{stat.StatType}' -> '{resolvedName}'."); } if (!string.Equals(stat.AttributeCapType, resolvedName2, StringComparison.OrdinalIgnoreCase)) { RuntimeOptimization.Debug($"{ownerName}: mapped AttributeCapType alias '{stat.AttributeCapType}' -> '{resolvedName2}'."); } list.Add(new CustomWeaponStatDef(value, result, value2, stat.Value)); } return list; } private static bool TryParseUnitStatType(string rawName, out UnitStatType value, out string resolvedName) { resolvedName = rawName?.Trim() ?? string.Empty; if (Enum.TryParse(resolvedName, ignoreCase: true, out value)) { return true; } if (UnitStatAliases.TryGetValue(resolvedName, out string value2) && Enum.TryParse(value2, ignoreCase: true, out value)) { resolvedName = value2; return true; } value = (UnitStatType)0; return false; } private static bool TryParseAttributeCapType(string rawName, out AttributeCapType value, out string resolvedName) { resolvedName = rawName?.Trim() ?? string.Empty; if (Enum.TryParse(resolvedName, ignoreCase: true, out value)) { return true; } if (AttributeCapAliases.TryGetValue(resolvedName, out string value2) && Enum.TryParse(value2, ignoreCase: true, out value)) { resolvedName = value2; return true; } value = (AttributeCapType)0; return false; } } internal sealed class WeaponStatConfigEntry { public string StatType { get; set; } = "PhysicalPower"; public string ModificationType { get; set; } = "AddToBase"; public string AttributeCapType { get; set; } = "SoftCapped"; public float Value { get; set; } } internal enum SpellSlotKind { Q, E, Dash, R, C, T } internal sealed class PlayerSpellOverrideFile { public int ConfigVersion { get; set; } = 8; public int DefaultCarrierBuff { get; set; } = 1644894901; public Dictionary Players { get; set; } = new Dictionary(); } internal sealed class PlayerSpellOverrideEntry { public bool Enabled { get; set; } = true; public ulong PlatformId { get; set; } public string LastKnownName { get; set; } = string.Empty; public int CarrierBuff { get; set; } public Dictionary WeaponScopes { get; set; } = new Dictionary(); public int Q { get; set; } public float QCooldown { get; set; } public int E { get; set; } public float ECooldown { get; set; } public int Dash { get; set; } public float DashCooldown { get; set; } public int R { get; set; } public float RCooldown { get; set; } public int C { get; set; } public float CCooldown { get; set; } public int T { get; set; } public float TCooldown { get; set; } } internal sealed class PlayerSpellScopeEntry { public int Q { get; set; } public float QCooldown { get; set; } public int E { get; set; } public float ECooldown { get; set; } public int Dash { get; set; } public float DashCooldown { get; set; } public int R { get; set; } public float RCooldown { get; set; } public int C { get; set; } public float CCooldown { get; set; } public int T { get; set; } public float TCooldown { get; set; } public bool HasAnySpell() { if (Q == 0 && E == 0 && Dash == 0 && R == 0 && C == 0) { return T != 0; } return true; } } internal static class PlayerSpellOverrideConfig { internal const int LegacyConflictingCarrierBuff = 673013659; internal const int SafeDefaultCarrierBuff = 1644894901; private const string DirectoryName = "HexesAndSanguineSteel"; private const string LegacyDirectoryName = "CustomWeaponMod"; private const string FileName = "player-spells.json"; private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { WriteIndented = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true, PropertyNameCaseInsensitive = true }; private static PlayerSpellOverrideFile? _cache; internal static string ConfigDirectory => Path.Combine(Paths.ConfigPath, "HexesAndSanguineSteel"); internal static string ConfigPath => Path.Combine(ConfigDirectory, "player-spells.json"); private static string LegacyConfigDirectory => Path.Combine(Paths.ConfigPath, "CustomWeaponMod"); private static string LegacyConfigPath => Path.Combine(LegacyConfigDirectory, "player-spells.json"); internal static PlayerSpellOverrideFile Current => _cache ?? LoadOrCreate(); private static void CopyLegacyConfigIfNeeded() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (!File.Exists(ConfigPath) && File.Exists(LegacyConfigPath)) { Directory.CreateDirectory(ConfigDirectory); File.Copy(LegacyConfigPath, ConfigPath, overwrite: false); ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(70, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Migrated legacy CustomWeaponMod config file to HexesAndSanguineSteel: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigPath); } logInstance.LogInfo(val); } } internal static PlayerSpellOverrideFile LoadOrCreate() { //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown Directory.CreateDirectory(ConfigDirectory); CopyLegacyConfigIfNeeded(); bool flag = default(bool); if (!File.Exists(ConfigPath)) { _cache = new PlayerSpellOverrideFile(); Save(_cache); ManualLogSource logInstance = Plugin.LogInstance; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(38, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Created player spell override config: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigPath); } logInstance.LogInfo(val); return _cache; } try { _cache = JsonSerializer.Deserialize(File.ReadAllText(ConfigPath), JsonOptions) ?? new PlayerSpellOverrideFile(); PlayerSpellOverrideFile cache = _cache; if (cache.Players == null) { Dictionary dictionary = (cache.Players = new Dictionary()); } foreach (PlayerSpellOverrideEntry value in _cache.Players.Values) { if (value.WeaponScopes == null) { Dictionary dictionary3 = (value.WeaponScopes = new Dictionary()); } } bool flag2 = false; if (_cache.ConfigVersion < 3) { BackupPreMigrationConfig(); _cache.ConfigVersion = 3; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded player spell override config to weapon-scoped schema v3. Legacy flat Q/E/T fields were preserved but are no longer applied unless re-saved with commands."); } if (_cache.ConfigVersion < 4 || _cache.DefaultCarrierBuff == 673013659) { BackupPreMigrationConfig(); if (_cache.DefaultCarrierBuff == 673013659) { _cache.DefaultCarrierBuff = 1644894901; flag2 = true; ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(124, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Migrated DefaultCarrierBuff away from "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(673013659); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" because it conflicts with the default custom spear equip buff. New default carrier: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(1644894901); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } logInstance2.LogWarning(val2); } foreach (PlayerSpellOverrideEntry value2 in _cache.Players.Values) { if (value2.CarrierBuff == 673013659) { value2.CarrierBuff = 0; flag2 = true; } } _cache.ConfigVersion = 4; flag2 = true; } if (_cache.ConfigVersion < 5) { BackupPreMigrationConfig(); _cache.ConfigVersion = 5; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded player spell override config to schema v5. Dash, R, and C weapon-scoped spell slots are now supported."); } if (_cache.ConfigVersion < 6) { BackupPreMigrationConfig(); _cache.ConfigVersion = 6; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded player spell override config to schema v6. SpellPool support was removed."); } if (_cache.ConfigVersion < 8) { BackupPreMigrationConfig(); _cache.ConfigVersion = 8; flag2 = true; Plugin.LogInstance.LogInfo((object)"Upgraded player spell override config to schema v8. Experimental spell charge fields were removed."); } if (flag2) { Save(_cache); } return _cache; } catch (Exception ex) { string text = ConfigPath + ".broken"; try { if (File.Exists(text)) { File.Delete(text); } File.Move(ConfigPath, text); } catch (Exception ex2) { ManualLogSource logInstance3 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not back up broken player spell config: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex2.Message); } logInstance3.LogWarning(val2); } _cache = new PlayerSpellOverrideFile(); Save(_cache); ManualLogSource logInstance4 = Plugin.LogInstance; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(59, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Failed to read player spell config. Wrote defaults. Error: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex); } logInstance4.LogError(val3); return _cache; } } private static void BackupPreMigrationConfig() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown try { string text = ConfigPath + ".backup"; if (File.Exists(text)) { File.Delete(text); } if (File.Exists(ConfigPath)) { File.Copy(ConfigPath, text); } } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(55, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not create player spell config migration backup: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logInstance.LogWarning(val); } } internal static void Save() { Save(Current); } private static void Save(PlayerSpellOverrideFile config) { Directory.CreateDirectory(ConfigDirectory); File.WriteAllText(ConfigPath, JsonSerializer.Serialize(config, JsonOptions)); } } internal static class Core { private static World? _server; internal static World Server { get { World? server = _server; if (server != null && server.IsCreated) { return _server; } _server = WorldUtility.FindServerWorld(true); World? server2 = _server; if (server2 == null || !server2.IsCreated) { throw new InvalidOperationException("Server world is not ready."); } return _server; } } internal static EntityManager EntityManager => Server.EntityManager; internal static ServerGameManager ServerGameManager => Server.GetExistingSystemManaged().GetServerGameManager(); } internal readonly record struct AbilitySlotDef(PrefabGUID AbilityGroup, float CooldownSeconds = 0f); internal readonly record struct WeaponPowerDef(float WeaponLevel, float PhysicalPower, float SpellPower) { internal static WeaponPowerDef Default => new WeaponPowerDef(100f, 35f, 10f); } internal readonly record struct CustomWeaponStatDef(UnitStatType StatType, ModificationType ModificationType, AttributeCapType AttributeCapType, float Value, float Modifier = 1f) { [CompilerGenerated] public void Deconstruct(out UnitStatType StatType, out ModificationType ModificationType, out AttributeCapType AttributeCapType, out float Value, out float Modifier) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected I4, but got Unknown //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected I4, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected I4, but got Unknown StatType = (UnitStatType)(int)this.StatType; ModificationType = (ModificationType)(int)this.ModificationType; AttributeCapType = (AttributeCapType)(int)this.AttributeCapType; Value = this.Value; Modifier = this.Modifier; } } internal readonly record struct WeaponTypeBuffDef(string WeaponType, bool ApplyToCustomWeapons, IReadOnlyList Stats); internal readonly record struct CustomWeaponCostDef(string Name, PrefabGUID Item, int Amount); internal readonly record struct CustomWeaponOnHitEffectDef(string Name, string School, float Chance, PrefabGUID TargetBuff, bool AffectPlayers, bool AffectNonPlayers); internal readonly record struct CustomWeaponDef(string Name, PrefabGUID ItemWeapon, PrefabGUID EquipBuff, PrefabGUID CarrierBuff, PrefabGUID StatCarrierBuff, IReadOnlyList UpgradeCost, WeaponPowerDef Power, IReadOnlyList Stats, IReadOnlyList OnHitEffects, AbilitySlotDef Attack, AbilitySlotDef Primary, AbilitySlotDef Secondary, AbilitySlotDef Dash, AbilitySlotDef Ultimate, AbilitySlotDef SpellSlot1, AbilitySlotDef SpellSlot2); internal static class CustomWeaponRegistry { private static readonly Dictionary _customWeaponsByItem = new Dictionary(); private static readonly Dictionary _customWeaponNamesByItem = new Dictionary(); private static readonly Dictionary _customWeaponsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly HashSet _reservedRuntimeCarrierBuffs = new HashSet(); private static readonly HashSet _reservedRuntimeStatCarrierBuffs = new HashSet(); internal static IReadOnlyList CurrentWeapons { get; private set; } = Array.Empty(); internal static IReadOnlyCollection ReservedRuntimeCarrierBuffs => _reservedRuntimeCarrierBuffs; internal static IReadOnlyCollection ReservedRuntimeStatCarrierBuffs => _reservedRuntimeStatCarrierBuffs; internal static bool IsCustomWeaponItem(int itemWeaponGuidHash) { return _customWeaponsByItem.ContainsKey(itemWeaponGuidHash); } internal static bool TryGetCustomWeapon(int itemWeaponGuidHash, out CustomWeaponDef weapon) { return _customWeaponsByItem.TryGetValue(itemWeaponGuidHash, out weapon); } internal static bool TryGetCustomWeaponByName(string name, out CustomWeaponDef weapon) { weapon = default(CustomWeaponDef); if (string.IsNullOrWhiteSpace(name)) { return false; } return _customWeaponsByName.TryGetValue(name, out weapon); } internal static bool TryGetCustomWeaponForCharacter(Entity character, out CustomWeaponDef weapon, out string source) { //IL_0007: 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) source = string.Empty; if (CustomWeaponInstanceStore.TryGetHeldInstanceWeapon(character, out weapon, out CustomWeaponInstanceEntry instance)) { source = $"instance:{instance.SequenceGuidHash}"; return true; } if (ItemInstanceUtility.TryGetHeldWeaponPrefab(character, out var prefabGuid) && TryGetCustomWeapon(((PrefabGUID)(ref prefabGuid)).GuidHash, out weapon)) { source = $"prefab:{((PrefabGUID)(ref prefabGuid)).GuidHash}"; return true; } weapon = default(CustomWeaponDef); return false; } internal static bool IsCustomWeaponEquipBuff(int equipBuffGuidHash) { if (!_reservedRuntimeCarrierBuffs.Contains(equipBuffGuidHash)) { return _reservedRuntimeStatCarrierBuffs.Contains(equipBuffGuidHash); } return true; } internal static string GetCustomWeaponUsingEquipBuff(int equipBuffGuidHash) { if (!_reservedRuntimeCarrierBuffs.Contains(equipBuffGuidHash)) { if (_reservedRuntimeStatCarrierBuffs.Contains(equipBuffGuidHash)) { return $"custom weapon runtime stat carrier {equipBuffGuidHash}"; } return $"custom weapon using equip buff {equipBuffGuidHash}"; } return $"custom weapon runtime ability carrier {equipBuffGuidHash}"; } internal static string GetCustomWeaponName(int itemWeaponGuidHash) { if (!_customWeaponNamesByItem.TryGetValue(itemWeaponGuidHash, out string value)) { return $"Custom weapon {itemWeaponGuidHash}"; } return value; } internal static void ApplyAll() { //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Expected O, but got Unknown //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_04a1: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_017b: 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_01b2: 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_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_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_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_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: 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_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) RuntimePrefabCache.Clear(); CustomWeaponStatCarrierService.Reset(); IReadOnlyList readOnlyList = (CurrentWeapons = CustomWeaponConfig.LoadOrCreate()); _customWeaponsByItem.Clear(); _customWeaponNamesByItem.Clear(); _customWeaponsByName.Clear(); _reservedRuntimeCarrierBuffs.Clear(); _reservedRuntimeStatCarrierBuffs.Clear(); Dictionary dictionary = readOnlyList.GroupBy(delegate(CustomWeaponDef w) { //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) PrefabGUID itemWeapon = w.ItemWeapon; return ((PrefabGUID)(ref itemWeapon)).GuidHash; }).ToDictionary((IGrouping g) => g.Key, (IGrouping g) => g.Count()); PrefabGUID val; foreach (CustomWeaponDef item in readOnlyList) { if (!_customWeaponsByName.TryAdd(item.Name, item)) { RuntimeOptimization.WarnOnce("dup-name:" + item.Name, "Duplicate custom weapon name '" + item.Name + "'. .csw wepgive uses names, so only the first definition with this name can be targeted reliably."); } val = item.ItemWeapon; if (dictionary.TryGetValue(((PrefabGUID)(ref val)).GuidHash, out var value) && value == 1) { Dictionary customWeaponsByItem = _customWeaponsByItem; val = item.ItemWeapon; customWeaponsByItem[((PrefabGUID)(ref val)).GuidHash] = item; Dictionary customWeaponNamesByItem = _customWeaponNamesByItem; val = item.ItemWeapon; customWeaponNamesByItem[((PrefabGUID)(ref val)).GuidHash] = item.Name; } else { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(9, 1); defaultInterpolatedStringHandler.AppendLiteral("dup-item:"); val = item.ItemWeapon; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); string key = defaultInterpolatedStringHandler.ToStringAndClear(); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler2 = new DefaultInterpolatedStringHandler(178, 1); defaultInterpolatedStringHandler2.AppendLiteral("ItemWeapon "); val = item.ItemWeapon; defaultInterpolatedStringHandler2.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler2.AppendLiteral(" is used by multiple custom weapon definitions. It will not be prefab-bound; give it with .csw wepgive so the generated item instance decides which definition applies."); RuntimeOptimization.WarnOnce(key, defaultInterpolatedStringHandler2.ToStringAndClear()); } val = item.CarrierBuff; if (((PrefabGUID)(ref val)).HasValue()) { HashSet reservedRuntimeCarrierBuffs = _reservedRuntimeCarrierBuffs; val = item.CarrierBuff; reservedRuntimeCarrierBuffs.Add(((PrefabGUID)(ref val)).GuidHash); } val = item.StatCarrierBuff; if (((PrefabGUID)(ref val)).HasValue()) { HashSet reservedRuntimeStatCarrierBuffs = _reservedRuntimeStatCarrierBuffs; val = item.StatCarrierBuff; reservedRuntimeStatCarrierBuffs.Add(((PrefabGUID)(ref val)).GuidHash); } } if (CustomWeaponConfig.CustomWeaponCarrierBuff != 0) { _reservedRuntimeCarrierBuffs.Add(CustomWeaponConfig.CustomWeaponCarrierBuff); } if (CustomWeaponConfig.CustomWeaponStatCarrierBuff != 0) { _reservedRuntimeStatCarrierBuffs.Add(CustomWeaponConfig.CustomWeaponStatCarrierBuff); } CustomWeaponValidationService.ValidateCarriers(); if (readOnlyList.Count == 0) { RuntimeOptimization.WarnOnce("no-enabled-weapons", "No enabled custom weapons found in " + CustomWeaponConfig.ConfigPath + "."); return; } RuntimeOptimization.InfoOnce("custom-weapon-apply-summary", $"Loaded {readOnlyList.Count} custom weapon definition(s), {CustomWeaponConfig.WeaponTypeBuffs.Count} weapon type buff(s), runtime carrier {CustomWeaponConfig.CustomWeaponCarrierBuff}, stat carrier {CustomWeaponConfig.CustomWeaponStatCarrierBuff}. Use .csw validate for details."); RuntimeOptimization.Debug($"WeaponTypeBuffs loaded: {CustomWeaponConfig.WeaponTypeBuffs.Count}. They share the runtime stat carrier {CustomWeaponConfig.CustomWeaponStatCarrierBuff} and are merged into one active player stat carrier."); bool flag = default(bool); foreach (CustomWeaponDef item2 in readOnlyList) { try { val = item2.ItemWeapon; if (dictionary.TryGetValue(((PrefabGUID)(ref val)).GuidHash, out var value2) && value2 == 1) { ApplyPrefabWeaponLevelOnly(item2); } else { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler3 = new DefaultInterpolatedStringHandler(174, 2); defaultInterpolatedStringHandler3.AppendFormatted(item2.Name); defaultInterpolatedStringHandler3.AppendLiteral(": skipped prefab WeaponLevelSource mutation because ItemWeapon "); val = item2.ItemWeapon; defaultInterpolatedStringHandler3.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler3.AppendLiteral(" is shared by multiple custom weapon definitions. Ability/stat behavior will be instance-bound by .csw wepgive."); RuntimeOptimization.Debug(defaultInterpolatedStringHandler3.ToStringAndClear()); } ValidateRuntimeCarriers(item2); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler4 = new DefaultInterpolatedStringHandler(83, 6); defaultInterpolatedStringHandler4.AppendLiteral("Registered runtime custom weapon: "); defaultInterpolatedStringHandler4.AppendFormatted(item2.Name); defaultInterpolatedStringHandler4.AppendLiteral(" item:"); val = item2.ItemWeapon; defaultInterpolatedStringHandler4.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler4.AppendLiteral(" abilityCarrier:"); val = item2.CarrierBuff; defaultInterpolatedStringHandler4.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler4.AppendLiteral(" statCarrier:"); val = item2.StatCarrierBuff; defaultInterpolatedStringHandler4.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler4.AppendLiteral(" stats:"); defaultInterpolatedStringHandler4.AppendFormatted(item2.Stats.Count); defaultInterpolatedStringHandler4.AppendLiteral(" onHit:"); defaultInterpolatedStringHandler4.AppendFormatted(item2.OnHitEffects.Count); RuntimeOptimization.Debug(defaultInterpolatedStringHandler4.ToStringAndClear()); } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(25, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed custom weapon '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(item2.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("': "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex); } logInstance.LogError(val2); } } } private static void ApplyPrefabWeaponLevelOnly(CustomWeaponDef weapon) { //IL_0013: 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_0042: 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_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) if (!weapon.ItemWeapon.TryGetPrefabEntity(out var entity)) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 1); defaultInterpolatedStringHandler.AppendLiteral("missing-item:"); PrefabGUID itemWeapon = weapon.ItemWeapon; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref itemWeapon)).GuidHash); string key = defaultInterpolatedStringHandler.ToStringAndClear(); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler2 = new DefaultInterpolatedStringHandler(25, 2); defaultInterpolatedStringHandler2.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler2.AppendLiteral(": item prefab not found: "); itemWeapon = weapon.ItemWeapon; defaultInterpolatedStringHandler2.AppendFormatted(((PrefabGUID)(ref itemWeapon)).GuidHash); RuntimeOptimization.WarnOnce(key, defaultInterpolatedStringHandler2.ToStringAndClear()); } else { entity.With((EntityExtensions.WithRefHandler)delegate(ref WeaponLevelSource source) { source.Level = weapon.Power.WeaponLevel; }); } } private static void ValidateRuntimeCarriers(CustomWeaponDef weapon) { //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_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_0016: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_016b: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_022a: 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_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: 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_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: 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_01ea: Unknown result type (might be due to invalid IL or missing references) PrefabGUID val = weapon.CarrierBuff; if (((PrefabGUID)(ref val)).HasValue()) { if (weapon.CarrierBuff.TryGetPrefabEntity(out var entity)) { if (!entity.TryGetBuffer(out DynamicBuffer _)) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(26, 1); defaultInterpolatedStringHandler.AppendLiteral("ability-carrier-no-buffer:"); val = weapon.CarrierBuff; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); string key = defaultInterpolatedStringHandler.ToStringAndClear(); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler2 = new DefaultInterpolatedStringHandler(58, 2); defaultInterpolatedStringHandler2.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler2.AppendLiteral(": ability carrier "); val = weapon.CarrierBuff; defaultInterpolatedStringHandler2.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler2.AppendLiteral(" does not have ReplaceAbilityOnSlotBuff."); RuntimeOptimization.WarnOnce(key, defaultInterpolatedStringHandler2.ToStringAndClear()); } } else { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler3 = new DefaultInterpolatedStringHandler(24, 1); defaultInterpolatedStringHandler3.AppendLiteral("ability-carrier-missing:"); val = weapon.CarrierBuff; defaultInterpolatedStringHandler3.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); string key2 = defaultInterpolatedStringHandler3.ToStringAndClear(); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler4 = new DefaultInterpolatedStringHandler(29, 2); defaultInterpolatedStringHandler4.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler4.AppendLiteral(": ability carrier "); val = weapon.CarrierBuff; defaultInterpolatedStringHandler4.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler4.AppendLiteral(" not found."); RuntimeOptimization.WarnOnce(key2, defaultInterpolatedStringHandler4.ToStringAndClear()); } } val = weapon.StatCarrierBuff; if (!((PrefabGUID)(ref val)).HasValue() || weapon.Stats.Count <= 0) { return; } if (weapon.StatCarrierBuff.TryGetPrefabEntity(out var entity2)) { if (!entity2.TryGetBuffer(out DynamicBuffer _)) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler5 = new DefaultInterpolatedStringHandler(23, 1); defaultInterpolatedStringHandler5.AppendLiteral("stat-carrier-no-buffer:"); val = weapon.StatCarrierBuff; defaultInterpolatedStringHandler5.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); string key3 = defaultInterpolatedStringHandler5.ToStringAndClear(); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler6 = new DefaultInterpolatedStringHandler(54, 2); defaultInterpolatedStringHandler6.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler6.AppendLiteral(": stat carrier "); val = weapon.StatCarrierBuff; defaultInterpolatedStringHandler6.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler6.AppendLiteral(" does not have ModifyUnitStatBuff_DOTS."); RuntimeOptimization.WarnOnce(key3, defaultInterpolatedStringHandler6.ToStringAndClear()); } } else { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler7 = new DefaultInterpolatedStringHandler(21, 1); defaultInterpolatedStringHandler7.AppendLiteral("stat-carrier-missing:"); val = weapon.StatCarrierBuff; defaultInterpolatedStringHandler7.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); string key4 = defaultInterpolatedStringHandler7.ToStringAndClear(); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler8 = new DefaultInterpolatedStringHandler(26, 2); defaultInterpolatedStringHandler8.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler8.AppendLiteral(": stat carrier "); val = weapon.StatCarrierBuff; defaultInterpolatedStringHandler8.AppendFormatted(((PrefabGUID)(ref val)).GuidHash); defaultInterpolatedStringHandler8.AppendLiteral(" not found."); RuntimeOptimization.WarnOnce(key4, defaultInterpolatedStringHandler8.ToStringAndClear()); } } } [BepInPlugin("com.hexesandsanguinesteel.server", "Hexes and Sanguine Steel", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] internal sealed class Plugin : BasePlugin { internal const string PluginGuid = "com.hexesandsanguinesteel.server"; internal const string PluginName = "Hexes and Sanguine Steel"; internal static ManualLogSource LogInstance; internal static Harmony Harmony; public override void Load() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown LogInstance = ((BasePlugin)this).Log; if (Application.productName != "VRisingServer") { ((BasePlugin)this).Log.LogWarning((object)"Hexes and Sanguine Steel is server-side only; skipping load on non-server process."); return; } Harmony = new Harmony("com.hexesandsanguinesteel.server"); Bootstrap.Initialize(Harmony, ((BasePlugin)this).Log); Harmony.PatchAll(); PlayerSpellOverrideService.Initialize(); CustomWeaponInstanceStore.Initialize(); CommandRegistry.RegisterAll(); ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(39, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("Hexes and Sanguine Steel"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("1.0.1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; waiting for server bootstrap."); } log.LogInfo(val); } public override bool Unload() { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } CommandRegistry.UnregisterAssembly(); return true; } } internal static class AbilityReplacementInjectionService { private static readonly int[] CustomWeaponManagedSlots = new int[7] { 0, 1, 2, 4, 5, 6, 7 }; private static readonly int[] PlayerSpellManagedSlots = new int[6] { 1, 2, 4, 5, 6, 7 }; internal static bool TryInjectForBuff(Entity buffEntity, out string message) { //IL_0007: 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_0019: 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_002f: 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) //IL_003d: 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_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_0052: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_007c: 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_00ad: 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_00a5: 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_00bd: 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_020c: 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_00ee: 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_0150: 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_0297: 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_0316: Unknown result type (might be due to invalid IL or missing references) message = string.Empty; if (!buffEntity.ExistsSafe() || buffEntity.Has()) { return false; } if (!buffEntity.TryGetBuffer(out DynamicBuffer buffer)) { return false; } if (!buffEntity.TryRead(out EntityOwner value) || !value.Owner.ExistsSafe() || value.Owner.Has()) { return false; } Entity owner = value.Owner; if (!owner.Has()) { return false; } if (ShapeshiftUtility.IsFormReplacementBuff(buffEntity) || ShapeshiftUtility.IsActiveForm(owner)) { CustomWeaponRuntimeOverrideService.RemoveAbilityCarriers(owner); if (PlayerLookup.TryFindOnlinePlayer(owner, out var result)) { PlayerSpellOverrideService.RemoveRuntimeCarrierForForm(owner, result.PlatformId); } message = "Skipped ability injection while shapeshift/form is active. form:" + ShapeshiftUtility.DescribeActiveForm(owner); return false; } if (FeedInteractionUtility.IsFeedOrExtractionReplacementBuff(buffEntity) || FeedInteractionUtility.IsActiveFeedOrExtraction(owner)) { CustomWeaponRuntimeOverrideService.RemoveAbilityCarriers(owner); if (PlayerLookup.TryFindOnlinePlayer(owner, out var result2)) { PlayerSpellOverrideService.RemoveRuntimeCarrierForTemporaryAbilityState(owner, result2.PlatformId); } message = "Skipped ability injection while feed/V Blood extraction is active. feed:" + FeedInteractionUtility.DescribeActiveFeedOrExtraction(owner); return false; } if (CustomWeaponRegistry.TryGetCustomWeaponForCharacter(owner, out CustomWeaponDef weapon, out string source)) { if (!IsExpectedCurrentWeaponReplacementBuff(buffEntity, owner, weapon, out string detail)) { message = $"Skipped custom weapon injection into non-weapon replacement buff {detail} for '{weapon.Name}'."; return false; } InjectCustomWeapon(buffer, weapon); PlayerSpellOverrideService.ClearRuntimeSpellState(owner); CustomWeaponRuntimeOverrideService.QueueRuntimeRefresh($"ReplaceAbilityOnSlotSystem injection custom weapon {weapon.Name} ({source})"); message = $"Injected custom weapon '{weapon.Name}' ({source}) into live ReplaceAbilityOnSlotBuff {detail}."; return true; } if (!PlayerLookup.TryFindOnlinePlayer(owner, out var result3)) { return false; } if (!PlayerSpellOverrideConfig.Current.Players.TryGetValue(result3.PlatformId.ToString(), out PlayerSpellOverrideEntry value2) || !value2.Enabled) { return false; } PlayerSpellOverrideEntry playerSpellOverrideEntry = value2; if (playerSpellOverrideEntry.WeaponScopes == null) { Dictionary dictionary = (playerSpellOverrideEntry.WeaponScopes = new Dictionary()); } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(owner); if (currentScope.IsCustomWeapon) { return false; } if (!value2.WeaponScopes.TryGetValue(currentScope.ScopeKey, out PlayerSpellScopeEntry value3) || !value3.HasAnySpell()) { return false; } if (!IsExpectedCurrentWeaponReplacementBuff(buffEntity, owner, default(CustomWeaponDef), out string detail2)) { message = $"Skipped spell override injection into non-weapon replacement buff {detail2} for {result3.Name}:{currentScope.ScopeKey}."; return false; } InjectPlayerSpellProfile(buffer, value3); PlayerSpellOverrideService.QueueCooldownRefresh("ReplaceAbilityOnSlotSystem injection spell override " + result3.Name + ":" + currentScope.ScopeKey); message = $"Injected spell override profile for {result3.Name} scope '{currentScope.ScopeKey}' into live ReplaceAbilityOnSlotBuff {detail2}."; return true; } private static bool IsExpectedCurrentWeaponReplacementBuff(Entity buffEntity, Entity character, CustomWeaponDef weapon, out string detail) { //IL_0001: 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_0032: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) detail = DescribeBuff(buffEntity); if (!buffEntity.TryRead(out PrefabGUID value) || !((PrefabGUID)(ref value)).HasValue()) { return false; } if (CustomWeaponRegistry.ReservedRuntimeCarrierBuffs.Contains(((PrefabGUID)(ref value)).GuidHash)) { return true; } if (ItemInstanceUtility.TryGetHeldWeaponEquipBuff(character, out var buffGuid) && ((PrefabGUID)(ref buffGuid)).HasValue()) { if (((PrefabGUID)(ref value)).GuidHash == ((PrefabGUID)(ref buffGuid)).GuidHash) { return true; } return false; } PrefabGUID equipBuff = weapon.EquipBuff; if (((PrefabGUID)(ref equipBuff)).HasValue()) { _ = ((PrefabGUID)(ref value)).GuidHash; equipBuff = weapon.EquipBuff; _ = ((PrefabGUID)(ref equipBuff)).GuidHash; return true; } return true; } private static string DescribeBuff(Entity buffEntity) { //IL_0000: 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_008a: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!buffEntity.ExistsSafe()) { return ""; } if (buffEntity.TryRead(out PrefabGUID value) && ((PrefabGUID)(ref value)).HasValue()) { return $"{((PrefabGUID)(ref value)).GuidHash} entity:{buffEntity.Index}:{buffEntity.Version}"; } return $"entity:{buffEntity.Index}:{buffEntity.Version}"; } private static void InjectCustomWeapon(DynamicBuffer replacements, CustomWeaponDef weapon) { //IL_0000: 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_0016: 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_002c: 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_0042: 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_0058: 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_006e: 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_0084: 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) AddOrReplace(replacements, 0, weapon.Attack.AbilityGroup); AddOrReplace(replacements, 1, weapon.Primary.AbilityGroup); AddOrReplace(replacements, 2, weapon.Dash.AbilityGroup); AddOrReplace(replacements, 4, weapon.Secondary.AbilityGroup); AddOrReplace(replacements, 5, weapon.SpellSlot1.AbilityGroup); AddOrReplace(replacements, 6, weapon.SpellSlot2.AbilityGroup); AddOrReplace(replacements, 7, weapon.Ultimate.AbilityGroup); } private static void InjectPlayerSpellProfile(DynamicBuffer replacements, PlayerSpellScopeEntry profile) { //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_0012: 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_0024: 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_0036: 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_0048: 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_005a: 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) AddOrReplace(replacements, 1, new PrefabGUID(profile.Q)); AddOrReplace(replacements, 2, new PrefabGUID(profile.Dash)); AddOrReplace(replacements, 4, new PrefabGUID(profile.E)); AddOrReplace(replacements, 5, new PrefabGUID(profile.R)); AddOrReplace(replacements, 6, new PrefabGUID(profile.C)); AddOrReplace(replacements, 7, new PrefabGUID(profile.T)); } private static void AddOrReplace(DynamicBuffer replacements, int slot, PrefabGUID abilityGroup) { //IL_000a: 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_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_0033: Unknown result type (might be due to invalid IL or missing references) if (((PrefabGUID)(ref abilityGroup)).HasValue()) { RemoveSlot(replacements, slot); replacements.Add(new ReplaceAbilityOnSlotBuff { Slot = slot, NewGroupId = abilityGroup, CopyCooldown = false }); } } private static void RemoveSlot(DynamicBuffer replacements, int slot) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) for (int num = replacements.Length - 1; num >= 0; num--) { if (replacements[num].Slot == slot) { replacements.RemoveAt(num); } } } } [HarmonyPatch(typeof(StatChangeSystem), "OnUpdate")] internal static class CustomWeaponOnHitService { private static readonly Random Rng = new Random(); [HarmonyPostfix] private static void Postfix(StatChangeSystem __instance) { //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_000f: 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_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_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_0033: 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_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_0046: 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_0058: 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_005f: 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_006d: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0093: 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_00c0: 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_012e: Unknown result type (might be due to invalid IL or missing references) if (CustomWeaponRegistry.CurrentWeapons.Count == 0) { return; } NativeArray val = default(NativeArray); NativeArray val2 = default(NativeArray); try { EntityQuery damageTakenEventQuery = __instance._DamageTakenEventQuery; val = ((EntityQuery)(ref damageTakenEventQuery)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); damageTakenEventQuery = __instance._DamageTakenEventQuery; val2 = ((EntityQuery)(ref damageTakenEventQuery)).ToComponentDataArray(AllocatorHandle.op_Implicit((Allocator)2)); for (int i = 0; i < val2.Length; i++) { DamageTakenEvent val3 = val2[i]; Entity entity = val3.Entity; if (!entity.ExistsSafe() || !entity.Has()) { continue; } Entity val4 = ResolveOwner(val3.Source); if (!val4.ExistsSafe() || !val4.Has() || !CustomWeaponRegistry.TryGetCustomWeaponForCharacter(val4, out CustomWeaponDef weapon, out string _) || weapon.OnHitEffects.Count == 0) { continue; } bool flag = entity.Has(); foreach (CustomWeaponOnHitEffectDef onHitEffect in weapon.OnHitEffects) { if ((!flag || onHitEffect.AffectPlayers) && (flag || onHitEffect.AffectNonPlayers) && !(onHitEffect.Chance <= 0f) && (!(onHitEffect.Chance < 1f) || !(Rng.NextDouble() > (double)onHitEffect.Chance))) { ApplyEffect(val4, entity, weapon, onHitEffect); } } } } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; bool flag2 = default(bool); BepInExWarningLogInterpolatedStringHandler val5 = new BepInExWarningLogInterpolatedStringHandler(38, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[CustomWeaponOnHitService] Exception: "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(ex); } logInstance.LogWarning(val5); } finally { if (val2.IsCreated) { val2.Dispose(); } if (val.IsCreated) { val.Dispose(); } } } private static Entity ResolveOwner(Entity source) { //IL_0000: 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_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_0016: 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_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_002f: 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 (!source.ExistsSafe()) { return Entity.Null; } if (source.Has()) { return source; } if (source.TryRead(out EntityOwner value) && value.Owner.ExistsSafe()) { return value.Owner; } return source; } private static void ApplyEffect(Entity sourcePlayer, Entity target, CustomWeaponDef weapon, CustomWeaponOnHitEffectDef effect) { //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_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_0016: 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) PrefabGUID targetBuff = effect.TargetBuff; if (((PrefabGUID)(ref targetBuff)).HasValue() && target.TryApplyBuffWithOwner(sourcePlayer, effect.TargetBuff)) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(40, 4); defaultInterpolatedStringHandler.AppendLiteral("OnHit '"); defaultInterpolatedStringHandler.AppendFormatted(effect.Name); defaultInterpolatedStringHandler.AppendLiteral("' ("); defaultInterpolatedStringHandler.AppendFormatted(effect.School); defaultInterpolatedStringHandler.AppendLiteral(") from "); defaultInterpolatedStringHandler.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler.AppendLiteral(": applied school buff "); targetBuff = effect.TargetBuff; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref targetBuff)).GuidHash); defaultInterpolatedStringHandler.AppendLiteral("."); RuntimeOptimization.Debug(defaultInterpolatedStringHandler.ToStringAndClear()); } } } internal static class CustomWeaponRuntimeCooldownService { internal static int ApplyAllOnline() { //IL_0027: 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_0050: Unknown result type (might be due to invalid IL or missing references) if (CustomWeaponRegistry.CurrentWeapons.Count == 0) { return 0; } int num = 0; foreach (PlayerLookupResult onlinePlayer in PlayerLookup.GetOnlinePlayers()) { if (WeaponScopeResolver.GetCurrentScope(onlinePlayer.CharacterEntity).IsCustomWeapon && CustomWeaponRegistry.TryGetCustomWeaponForCharacter(onlinePlayer.CharacterEntity, out CustomWeaponDef weapon, out string _)) { num += ApplyWeaponCooldowns(onlinePlayer.CharacterEntity, weapon); } } return num; } private static int ApplyWeaponCooldowns(Entity character, CustomWeaponDef weapon) { //IL_0001: 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_0035: 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_0069: 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_009d: Unknown result type (might be due to invalid IL or missing references) return 0 + ApplySlot(character, weapon.Name, "Attack", weapon.Attack) + ApplySlot(character, weapon.Name, "Primary/Q", weapon.Primary) + ApplySlot(character, weapon.Name, "Secondary/E", weapon.Secondary) + ApplySlot(character, weapon.Name, "Dash", weapon.Dash) + ApplySlot(character, weapon.Name, "Ultimate/T", weapon.Ultimate) + ApplySlot(character, weapon.Name, "Spell Slot 1", weapon.SpellSlot1) + ApplySlot(character, weapon.Name, "Spell Slot 2", weapon.SpellSlot2); } private static int ApplySlot(Entity character, string weaponName, string slotName, AbilitySlotDef ability) { //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_0021: 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) PrefabGUID abilityGroup = ability.AbilityGroup; if (!((PrefabGUID)(ref abilityGroup)).HasValue() || ability.CooldownSeconds <= 0f) { return 0; } return AbilityCooldownUtility.SetCooldownOnAttachedAbilityGroup(character, ability.AbilityGroup, ability.CooldownSeconds, $"CustomWeaponRuntimeCooldown[{weaponName}:{slotName}]"); } } internal static class CustomWeaponRuntimeOverrideService { internal static void QueueRuntimeRefresh(string reason) { PlayerSpellOverrideService.QueueCooldownRefresh(reason); } internal static void ForceStatReconcile(Entity character, string reason) { //IL_0000: 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_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_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) if (character.ExistsSafe()) { CustomWeaponStatCarrierService.ClearPendingForCharacter(character); RemoveStatCarriers(character); RuntimeStateCache.ClearRuntimeStatHash(character); RuntimeOptimization.Debug($"Forced stat reconcile for character {character.Index}:{character.Version}. Reason:{reason}"); } } internal static int ApplyAllOnline() { int num = 0; foreach (PlayerLookupResult onlinePlayer in PlayerLookup.GetOnlinePlayers()) { if (TryApplyForPlayer(onlinePlayer, out string _)) { num++; } } return num; } internal static bool TryApplyForPlayer(PlayerLookupResult player, out string message) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return TryApplyForCharacter(player.CharacterEntity, out message); } internal static bool TryApplyForCharacter(Entity character, out string message) { //IL_0007: 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_003a: 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_002c: 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_0042: 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_0054: 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_0075: 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_0081: 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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) message = string.Empty; if (!character.ExistsSafe()) { message = "Invalid character entity."; return false; } if (ShapeshiftUtility.IsActiveForm(character)) { RemoveAllRuntimeCarriers(character); message = "Shapeshift/form active; custom weapon runtime override suppressed. form:" + ShapeshiftUtility.DescribeActiveForm(character); return false; } if (FeedInteractionUtility.IsActiveFeedOrExtraction(character)) { RemoveAbilityCarriers(character); RuntimeStateCache.ClearCustomWeaponAbilityHash(character); message = "Feed/V Blood extraction active; custom weapon ability override suppressed. feed:" + FeedInteractionUtility.DescribeActiveFeedOrExtraction(character); return false; } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(character); if (!currentScope.IsCustomWeapon) { RemoveAbilityCarriers(character); RuntimeStateCache.ClearCustomWeaponAbilityHash(character); int num = ApplyMergedStats(character, Array.Empty(), new PrefabGUID(CustomWeaponConfig.CustomWeaponStatCarrierBuff), CustomWeaponConfig.CustomWeaponStatCarrierBuff, "WeaponType[" + currentScope.ScopeKey + "]", customWeaponActive: false); message = ((num > 0) ? $"No custom weapon equipped. Applied weapon-type stat buff for current scope:{currentScope.ScopeKey}, stats:{num}." : ("No custom weapon equipped. Current scope:" + currentScope.ScopeKey + ".")); return num > 0; } if (!CustomWeaponRegistry.TryGetCustomWeaponForCharacter(character, out CustomWeaponDef weapon, out string source)) { RemoveAllRuntimeCarriers(character); message = "Custom weapon scope detected, but no matching definition exists for current held weapon. Scope:" + currentScope.ScopeKey + "."; return false; } return ApplyWeapon(character, weapon, source, out message); } private static bool ApplyWeapon(Entity character, CustomWeaponDef weapon, string source, out string message) { //IL_000f: 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_016c: 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_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02da: 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_0191: 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) //IL_019c: 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_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: 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) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_024f: 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_026d: 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_028b: Unknown result type (might be due to invalid IL or missing references) //IL_029a: 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_02b8: Unknown result type (might be due to invalid IL or missing references) int num = ResolveAbilityCarrier(weapon); PrefabGUID val = default(PrefabGUID); ((PrefabGUID)(ref val))..ctor(num); if (!val.TryGetPrefabEntity(out var entity)) { message = $"Custom weapon ability carrier buff prefab {num} was not found for {weapon.Name}."; return false; } if (!entity.TryGetBuffer(out DynamicBuffer _)) { message = $"Custom weapon ability carrier buff prefab {num} does not have ReplaceAbilityOnSlotBuff buffer."; return false; } int num2 = ResolveStatCarrier(weapon); PrefabGUID val2 = default(PrefabGUID); ((PrefabGUID)(ref val2))..ctor(num2); if (weapon.Stats.Count > 0) { if (!val2.TryGetPrefabEntity(out var entity2)) { message = $"Custom weapon stat carrier buff prefab {num2} was not found for {weapon.Name}."; return false; } if (!entity2.TryGetBuffer(out DynamicBuffer _)) { message = $"Custom weapon stat carrier buff prefab {num2} does not have ModifyUnitStatBuff_DOTS buffer."; return false; } } int hash = ComputeWeaponAbilityHash(weapon, source, num); Entity buffEntity; bool flag = RuntimeStateCache.ShouldSkipCustomWeaponAbilityApply(character, hash) && character.TryGetBuff(val, out buffEntity); if (!flag) { RemoveAbilityCarriers(character); PlayerSpellOverrideService.ClearRuntimeSpellState(character); ServerGameManager serverGameManager = Core.ServerGameManager; Entity buffEntity2 = default(Entity); if (!((ServerGameManager)(ref serverGameManager)).TryInstantiateBuffEntityImmediate(character, character, val, ref buffEntity2, (OnSpawnedDelegate)null, 1) && !character.TryGetBuff(val, out buffEntity2)) { message = $"Failed to apply custom weapon runtime ability carrier buff {num} for {weapon.Name}."; return false; } if (!buffEntity2.TryGetBuffer(out DynamicBuffer buffer3)) { message = $"Applied custom weapon ability carrier buff {num}, but its instance has no ReplaceAbilityOnSlotBuff buffer."; return false; } buffer3.Clear(); AddSlot(buffer3, 0, weapon.Attack); AddSlot(buffer3, 1, weapon.Primary); AddSlot(buffer3, 2, weapon.Dash); AddSlot(buffer3, 5, weapon.SpellSlot1); AddSlot(buffer3, 4, weapon.Secondary); AddSlot(buffer3, 6, weapon.SpellSlot2); AddSlot(buffer3, 7, weapon.Ultimate); RuntimeStateCache.SetCustomWeaponAbilityHash(character, hash); } int value = ApplyMergedStats(character, weapon.Stats, val2, num2, weapon.Name, customWeaponActive: true); int value2 = ApplyCooldowns(character, weapon); message = (flag ? $"Runtime custom weapon '{weapon.Name}' already current ({source}). statUpdates:{value} cooldownAttachedUpdates:{value2}." : $"Applied runtime custom weapon '{weapon.Name}' ({source}) abilityCarrier:{num} statCarrier:{num2} stats:{value} cooldownAttachedUpdates:{value2}."); return true; } private static int ComputeWeaponAbilityHash(CustomWeaponDef weapon, string source, int carrierHash) { HashCode hash = default(HashCode); hash.Add(weapon.Name, StringComparer.OrdinalIgnoreCase); hash.Add(source); hash.Add(carrierHash); AddAbilityHash(ref hash, weapon.Attack); AddAbilityHash(ref hash, weapon.Primary); AddAbilityHash(ref hash, weapon.Secondary); AddAbilityHash(ref hash, weapon.Dash); AddAbilityHash(ref hash, weapon.Ultimate); AddAbilityHash(ref hash, weapon.SpellSlot1); AddAbilityHash(ref hash, weapon.SpellSlot2); return hash.ToHashCode(); } private static int ComputeStatHash(int carrierHash, IReadOnlyList stats, bool customWeaponActive, string label) { //IL_0039: 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_0055: Unknown result type (might be due to invalid IL or missing references) HashCode hashCode = default(HashCode); hashCode.Add(carrierHash); hashCode.Add(customWeaponActive); hashCode.Add(label, StringComparer.OrdinalIgnoreCase); foreach (CustomWeaponStatDef stat in stats) { hashCode.Add(stat.StatType); hashCode.Add(stat.ModificationType); hashCode.Add(stat.AttributeCapType); hashCode.Add(stat.Value); hashCode.Add(stat.Modifier); } return hashCode.ToHashCode(); } private static void AddAbilityHash(ref HashCode hash, AbilitySlotDef ability) { //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) PrefabGUID abilityGroup = ability.AbilityGroup; hash.Add(((PrefabGUID)(ref abilityGroup)).GuidHash); hash.Add(ability.CooldownSeconds); } private static int ResolveAbilityCarrier(CustomWeaponDef weapon) { //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_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) PrefabGUID carrierBuff = weapon.CarrierBuff; if (((PrefabGUID)(ref carrierBuff)).HasValue()) { carrierBuff = weapon.CarrierBuff; return ((PrefabGUID)(ref carrierBuff)).GuidHash; } return CustomWeaponConfig.CustomWeaponCarrierBuff; } private static int ResolveStatCarrier(CustomWeaponDef weapon) { //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_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) PrefabGUID statCarrierBuff = weapon.StatCarrierBuff; if (((PrefabGUID)(ref statCarrierBuff)).HasValue()) { statCarrierBuff = weapon.StatCarrierBuff; return ((PrefabGUID)(ref statCarrierBuff)).GuidHash; } return CustomWeaponConfig.CustomWeaponStatCarrierBuff; } private static void AddSlot(DynamicBuffer replacements, int slot, AbilitySlotDef ability) { //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_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_002d: 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) PrefabGUID abilityGroup = ability.AbilityGroup; if (((PrefabGUID)(ref abilityGroup)).HasValue()) { replacements.Add(new ReplaceAbilityOnSlotBuff { Slot = slot, NewGroupId = ability.AbilityGroup, CopyCooldown = false }); } } private static int ApplyMergedStats(Entity character, IReadOnlyList baseStats, PrefabGUID statCarrierGuid, int statCarrierHash, string label, bool customWeaponActive) { //IL_0016: 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_00c6: 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_00eb: 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_00de: 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) List list = new List(); if (baseStats.Count > 0) { list.AddRange(baseStats); } if (CustomWeaponTypeBuffService.TryGetMatchingStats(character, customWeaponActive, out IReadOnlyList stats, out string weaponType, out int matchedEntries)) { list.AddRange(stats); RuntimeOptimization.Debug($"Merged weapon-type stats '{weaponType}' into runtime stat carrier for {label}. customWeapon:{customWeaponActive} typeEntries:{matchedEntries} typeStats:{stats.Count}"); } int num = ComputeStatHash(statCarrierHash, list, customWeaponActive, label); if (list.Count == 0) { RemoveStatCarriers(character); RuntimeStateCache.ClearRuntimeStatHash(character); return 0; } if (RuntimeStateCache.ShouldSkipRuntimeStats(character, num) && character.TryGetBuff(statCarrierGuid, out var _)) { return 0; } return CustomWeaponStatCarrierService.ApplyStats(character, statCarrierGuid, statCarrierHash, list, num, label); } private static int ApplyCooldowns(Entity character, CustomWeaponDef weapon) { //IL_0001: 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_0035: 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_0069: 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_009d: Unknown result type (might be due to invalid IL or missing references) return 0 + ApplySlotCooldown(character, weapon.Name, "Attack", weapon.Attack) + ApplySlotCooldown(character, weapon.Name, "Primary/Q", weapon.Primary) + ApplySlotCooldown(character, weapon.Name, "Secondary/E", weapon.Secondary) + ApplySlotCooldown(character, weapon.Name, "Dash", weapon.Dash) + ApplySlotCooldown(character, weapon.Name, "Ultimate/T", weapon.Ultimate) + ApplySlotCooldown(character, weapon.Name, "Spell Slot 1", weapon.SpellSlot1) + ApplySlotCooldown(character, weapon.Name, "Spell Slot 2", weapon.SpellSlot2); } private static int ApplySlotCooldown(Entity character, string weaponName, string slotName, AbilitySlotDef ability) { //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_0021: 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) PrefabGUID abilityGroup = ability.AbilityGroup; if (!((PrefabGUID)(ref abilityGroup)).HasValue() || ability.CooldownSeconds <= 0f) { return 0; } return AbilityCooldownUtility.SetCooldownOnAttachedAbilityGroup(character, ability.AbilityGroup, ability.CooldownSeconds, $"CustomWeaponRuntimeOverride[{weaponName}:{slotName}]"); } internal static void RemoveAllRuntimeCarriers(Entity character) { //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_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) RemoveAbilityCarriers(character); RemoveStatCarriers(character); RuntimeStateCache.ClearCustomWeaponAbilityHash(character); RuntimeStateCache.ClearRuntimeStatHash(character); } internal static void RemoveAbilityCarriers(Entity character) { //IL_0000: 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_004d: 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) if (!character.ExistsSafe()) { return; } PrefabGUID buffPrefabGuid = default(PrefabGUID); foreach (int reservedRuntimeCarrierBuff in CustomWeaponRegistry.ReservedRuntimeCarrierBuffs) { if (reservedRuntimeCarrierBuff != 0) { ((PrefabGUID)(ref buffPrefabGuid))..ctor(reservedRuntimeCarrierBuff); if (character.TryGetBuff(buffPrefabGuid, out var buffEntity)) { buffEntity.DestroySafe(); } } } RuntimeStateCache.ClearCustomWeaponAbilityHash(character); } internal static void RemoveStatCarriers(Entity character) { //IL_0000: 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_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) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe()) { return; } CustomWeaponStatCarrierService.ClearPendingForCharacter(character); PrefabGUID buffPrefabGuid = default(PrefabGUID); foreach (int reservedRuntimeStatCarrierBuff in CustomWeaponRegistry.ReservedRuntimeStatCarrierBuffs) { if (reservedRuntimeStatCarrierBuff != 0) { ((PrefabGUID)(ref buffPrefabGuid))..ctor(reservedRuntimeStatCarrierBuff); if (character.TryGetBuff(buffPrefabGuid, out var buffEntity)) { buffEntity.DestroySafe(); } } } RuntimeStateCache.ClearRuntimeStatHash(character); } } internal static class CustomWeaponStatCarrierService { private sealed class PendingPayload { public Entity Character = Entity.Null; public Entity User = Entity.Null; public PrefabGUID Carrier; public CustomWeaponStatDef[] Stats = Array.Empty(); public int DesiredHash; public string Label = string.Empty; public DateTime CreatedAtUtc = DateTime.UtcNow; public float? HealthRatioBeforeRebuild; } private const string ScriptSpawnTypeName = "ProjectM.Scripting.ScriptSpawn"; private static int _preparedCarrierGuid; private static Type? _scriptSpawnManagedType; private static Type? _scriptSpawnIl2CppType; private static readonly Dictionary _pendingByCharacterAndCarrier = new Dictionary(); private static readonly TimeSpan PendingPayloadTimeout = TimeSpan.FromSeconds(30.0); internal static int PendingPayloadCount => _pendingByCharacterAndCarrier.Count; internal static void ClearPendingForCharacter(Entity character) { //IL_0000: 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) if (!character.ExistsSafe() || _pendingByCharacterAndCarrier.Count == 0) { return; } KeyValuePair[] array = _pendingByCharacterAndCarrier.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; if (((Entity)(ref keyValuePair.Value.Character)).Equals(character)) { _pendingByCharacterAndCarrier.Remove(keyValuePair.Key); } } } internal static void Reset() { _preparedCarrierGuid = 0; _pendingByCharacterAndCarrier.Clear(); } internal static int ApplyStats(Entity character, PrefabGUID carrierGuid, int carrierHash, IReadOnlyList stats, int desiredHash, string label) { //IL_0000: 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_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_002e: 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_0055: 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_005d: 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_0093: 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_00a2: 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_015d: 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_0166: 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_0168: 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_01cc: 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_0175: 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_01d8: 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_01e8: 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_00d7: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe() || !((PrefabGUID)(ref carrierGuid)).HasValue() || stats.Count == 0) { return 0; } if (!PrepareStatCarrierPrefab(carrierGuid)) { return 0; } Entity user = Entity.Null; ulong value = 0uL; if (PlayerLookup.TryFindOnlinePlayer(character, out var result)) { user = result.UserEntity; value = result.PlatformId; } float? healthRatioBeforeRebuild = CaptureHealthRatio(character); PendingPayload pendingPayload = new PendingPayload { Character = character, User = user, Carrier = carrierGuid, Stats = stats.ToArray(), DesiredHash = desiredHash, Label = label, HealthRatioBeforeRebuild = healthRatioBeforeRebuild }; _pendingByCharacterAndCarrier[Key(character, carrierHash)] = pendingPayload; if (character.TryGetBuff(carrierGuid, out var buffEntity) && buffEntity.ExistsSafe() && !buffEntity.Has()) { int num = PopulateStatCarrier(buffEntity, pendingPayload); if (num > 0) { RuntimeStateCache.SetRuntimeStatHash(character, desiredHash); RuntimeOptimization.Debug($"[StatCarrier] Rebuilt existing stat carrier {carrierHash} for {label}; stats:{num} platform:{value}."); return num; } buffEntity.DestroySafe(); } ServerGameManager serverGameManager = Core.ServerGameManager; Entity buffEntity2 = default(Entity); if (!((ServerGameManager)(ref serverGameManager)).TryInstantiateBuffEntityImmediate(character, character, carrierGuid, ref buffEntity2, (OnSpawnedDelegate)null, 1) && !character.TryGetBuff(carrierGuid, out buffEntity2)) { RuntimeOptimization.Debug($"[StatCarrier] Queued payload for {label}, but immediate carrier spawn {carrierHash} did not return an entity."); return 0; } if (buffEntity2.ExistsSafe()) { int num2 = PopulateStatCarrier(buffEntity2, pendingPayload); if (num2 > 0) { RuntimeStateCache.SetRuntimeStatHash(character, desiredHash); RuntimeOptimization.Debug($"[StatCarrier] Populated immediate stat carrier {carrierHash} for {label}; stats:{num2} platform:{value}."); return num2; } } return 0; } internal static bool TryPopulateSpawnedCarrier(Entity buffEntity) { //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_0010: 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_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_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_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_0033: 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_003f: 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_0068: 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) if (!buffEntity.ExistsSafe() || !buffEntity.Has() || !buffEntity.Has()) { return false; } EntityManager entityManager = Core.EntityManager; PrefabGUID componentData = ((EntityManager)(ref entityManager)).GetComponentData(buffEntity); entityManager = Core.EntityManager; Entity target = ((EntityManager)(ref entityManager)).GetComponentData(buffEntity).Target; if (!target.ExistsSafe()) { return false; } long key = Key(target, ((PrefabGUID)(ref componentData)).GuidHash); if (!_pendingByCharacterAndCarrier.TryGetValue(key, out PendingPayload value)) { return false; } int num = PopulateStatCarrier(buffEntity, value); if (num <= 0) { return false; } RuntimeStateCache.SetRuntimeStatHash(target, value.DesiredHash); RuntimeOptimization.Debug($"[StatCarrier] Populated spawned stat carrier {((PrefabGUID)(ref componentData)).GuidHash} for {value.Label}; stats:{num}."); return true; } internal static void CleanupExpiredPayloads() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (_pendingByCharacterAndCarrier.Count == 0) { return; } DateTime utcNow = DateTime.UtcNow; KeyValuePair[] array = _pendingByCharacterAndCarrier.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; PendingPayload value = keyValuePair.Value; if (!value.Character.ExistsSafe() || utcNow - value.CreatedAtUtc > PendingPayloadTimeout) { _pendingByCharacterAndCarrier.Remove(keyValuePair.Key); RuntimeOptimization.Debug("[StatCarrier] Expired pending stat payload for " + value.Label + "."); } } } private static int PopulateStatCarrier(Entity buffEntity, PendingPayload payload) { //IL_0000: 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_0019: 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_0021: 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_0041: 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_0037: 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_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_007a: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_011e: Unknown result type (might be due to invalid IL or missing references) if (!buffEntity.ExistsSafe() || payload.Stats.Length == 0) { return 0; } EntityManager entityManager = Core.EntityManager; TryStabilizeRuntimeCarrier(buffEntity); TryAddSyncToUser(buffEntity, payload.User); DynamicBuffer val = (((EntityManager)(ref entityManager)).HasBuffer(buffEntity) ? ((EntityManager)(ref entityManager)).GetBuffer(buffEntity, false) : ((EntityManager)(ref entityManager)).AddBuffer(buffEntity)); val.Clear(); CustomWeaponStatDef[] stats = payload.Stats; for (int i = 0; i < stats.Length; i++) { CustomWeaponStatDef customWeaponStatDef = stats[i]; ModifyUnitStatBuff_DOTS val2 = new ModifyUnitStatBuff_DOTS { StatType = customWeaponStatDef.StatType, ModificationType = customWeaponStatDef.ModificationType, AttributeCapType = customWeaponStatDef.AttributeCapType, SoftCapValue = 0f, Value = customWeaponStatDef.Value, Modifier = 1f, IncreaseByStacks = false, ValueByStacks = 0f, Priority = 0 }; ModificationIDs val3 = ModificationIDs.Create(); val2.Id = ((ModificationIDs)(ref val3)).NewModificationId(); val.Add(val2); } NormalizeHealthAfterStatCarrierUpdate(payload.Character, payload.HealthRatioBeforeRebuild); _pendingByCharacterAndCarrier.Remove(Key(payload.Character, ((PrefabGUID)(ref payload.Carrier)).GuidHash)); return val.Length; } internal static bool PrepareStatCarrierPrefab(PrefabGUID carrier) { //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_00c1: 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: Expected O, but got Unknown //IL_00d6: 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_00cb: 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) bool flag = default(bool); try { if (!((PrefabGUID)(ref carrier)).HasValue()) { return false; } if (_preparedCarrierGuid == ((PrefabGUID)(ref carrier)).GuidHash) { return true; } if (!carrier.TryGetPrefabEntity(out var entity)) { ManualLogSource logInstance = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(61, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[StatCarrier] Could not find stat carrier prefab entity for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((PrefabGUID)(ref carrier)).GuidHash); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance.LogWarning(val); return false; } EntityManager entityManager = Core.EntityManager; if (!TryEnsureScriptSpawn(entityManager, entity)) { ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(124, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[StatCarrier] Could not resolve/add ScriptSpawn dynamically for carrier "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((PrefabGUID)(ref carrier)).GuidHash); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Immediate stat-buffer fallback will still be used."); } logInstance2.LogWarning(val); } if (!((EntityManager)(ref entityManager)).HasBuffer(entity)) { ((EntityManager)(ref entityManager)).AddBuffer(entity); } else { ((EntityManager)(ref entityManager)).GetBuffer(entity, false).Clear(); } _preparedCarrierGuid = ((PrefabGUID)(ref carrier)).GuidHash; RuntimeOptimization.Debug($"[StatCarrier] Prepared stat carrier prefab {((PrefabGUID)(ref carrier)).GuidHash} with ScriptSpawn/ModifyUnitStatBuff_DOTS."); return true; } catch (Exception ex) { ManualLogSource logInstance3 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(47, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[StatCarrier] Failed to prepare stat carrier "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((PrefabGUID)(ref carrier)).GuidHash); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logInstance3.LogWarning(val); return false; } } private static bool TryEnsureScriptSpawn(EntityManager em, Entity prefabEntity) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) Type val = ResolveScriptSpawnIl2CppType(); if (val == (Type)null) { return false; } ComponentType val2 = default(ComponentType); ((ComponentType)(ref val2))..ctor(val, (AccessMode)0); if (!((EntityManager)(ref em)).HasComponent(prefabEntity, val2)) { ((EntityManager)(ref em)).AddComponent(prefabEntity, val2); } return true; } private static Type? ResolveScriptSpawnIl2CppType() { if (_scriptSpawnIl2CppType != (Type)null) { return _scriptSpawnIl2CppType; } if ((object)_scriptSpawnManagedType == null) { _scriptSpawnManagedType = AccessTools.TypeByName("ProjectM.Scripting.ScriptSpawn") ?? AccessTools.TypeByName("ProjectM.Gameplay.Scripting.ScriptSpawn") ?? AccessTools.TypeByName("ProjectM.ScriptSpawn") ?? AccessTools.TypeByName("ScriptSpawn"); } if (_scriptSpawnManagedType == null) { return null; } MethodInfo methodInfo = typeof(Il2CppType).GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "Of" && method.IsGenericMethodDefinition && method.GetParameters().Length == 0); if (methodInfo == null) { return null; } object? obj = methodInfo.MakeGenericMethod(_scriptSpawnManagedType).Invoke(null, null); _scriptSpawnIl2CppType = (Type?)((obj is Type) ? obj : null); return _scriptSpawnIl2CppType; } private static void TryAddSyncToUser(Entity buffEntity, Entity userEntity) { //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_0006: 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_0019: 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_002f: 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_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_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_0049: 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_006c: 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) EntityManager entityManager = Core.EntityManager; if (!buffEntity.ExistsSafe() || !userEntity.ExistsSafe()) { return; } DynamicBuffer val = (((EntityManager)(ref entityManager)).HasBuffer(buffEntity) ? ((EntityManager)(ref entityManager)).GetBuffer(buffEntity, false) : ((EntityManager)(ref entityManager)).AddBuffer(buffEntity)); SyncToUserBuffer val2; for (int i = 0; i < val.Length; i++) { val2 = val[i]; if (((Entity)(ref val2.UserEntity)).Equals(userEntity)) { return; } } val2 = new SyncToUserBuffer { UserEntity = userEntity }; val.Add(val2); } private static void TryStabilizeRuntimeCarrier(Entity buffEntity) { //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_0006: 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_0024: 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_0037: 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_0041: Unknown result type (might be due to invalid IL or missing references) EntityManager entityManager = Core.EntityManager; if (buffEntity.ExistsSafe()) { if (((EntityManager)(ref entityManager)).HasComponent(buffEntity)) { ((EntityManager)(ref entityManager)).RemoveComponent(buffEntity); } if (((EntityManager)(ref entityManager)).HasComponent(buffEntity)) { ((EntityManager)(ref entityManager)).RemoveComponent(buffEntity); } if (((EntityManager)(ref entityManager)).HasComponent(buffEntity)) { ((EntityManager)(ref entityManager)).RemoveComponent(buffEntity); } } } private static float? CaptureHealthRatio(Entity character) { //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_0006: 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_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_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_002d: 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) EntityManager entityManager = Core.EntityManager; if (!character.ExistsSafe() || !((EntityManager)(ref entityManager)).HasComponent(character)) { return null; } Health componentData = ((EntityManager)(ref entityManager)).GetComponentData(character); float value = componentData.MaxHealth._Value; if (value <= 0f) { return null; } float num = componentData.Value / value; if (num < 0f) { num = 0f; } if (num > 1f) { num = 1f; } return num; } private static void NormalizeHealthAfterStatCarrierUpdate(Entity character, float? previousRatio) { //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_0006: 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_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_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_0089: 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_009d: 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_0081: 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) EntityManager entityManager = Core.EntityManager; if (!character.ExistsSafe() || !((EntityManager)(ref entityManager)).HasComponent(character)) { return; } Health componentData = ((EntityManager)(ref entityManager)).GetComponentData(character); float value = componentData.MaxHealth._Value; if (value <= 0f) { return; } if (previousRatio.HasValue) { float num = previousRatio.Value; if (num < 0f) { num = 0f; } if (num > 1f) { num = 1f; } componentData.Value = value * num; if (componentData.Value > value) { componentData.Value = value; } ((EntityManager)(ref entityManager)).SetComponentData(character, componentData); } else if (componentData.Value > value) { componentData.Value = value; ((EntityManager)(ref entityManager)).SetComponentData(character, componentData); } } private static long Key(Entity character, int carrierHash) { //IL_0000: 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) return ((long)character.Index << 32) ^ (uint)character.Version ^ carrierHash; } } [HarmonyPatch] internal static class CustomWeaponScriptSpawnServerPatch { private static EntityQuery? _scriptSpawnQuery; private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("ScriptSpawnServer") ?? AccessTools.TypeByName("ProjectM.ScriptSpawnServer") ?? AccessTools.TypeByName("ProjectM.Shared.Systems.ScriptSpawnServer"); if (type == null) { throw new MissingMethodException("Unable to find ScriptSpawnServer type."); } MethodInfo methodInfo = AccessTools.Method(type, "OnUpdate", (Type[])null, (Type[])null); if (methodInfo == null) { throw new MissingMethodException(type.FullName, "OnUpdate"); } return methodInfo; } [HarmonyPrefix] private static void Prefix(object __instance) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //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_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_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) try { if (CustomWeaponStatCarrierService.PendingPayloadCount == 0) { return; } EntityQuery scriptSpawnServerQuery = GetScriptSpawnServerQuery(__instance); NativeArray val = ((EntityQuery)(ref scriptSpawnServerQuery)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { for (int i = 0; i < val.Length; i++) { CustomWeaponStatCarrierService.TryPopulateSpawnedCarrier(val[i]); } } finally { if (val.IsCreated) { val.Dispose(); } } CustomWeaponStatCarrierService.CleanupExpiredPayloads(); } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[StatCarrier] ScriptSpawnServer patch failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } logInstance.LogWarning(val2); } } private static EntityQuery GetScriptSpawnServerQuery(object instance) { //IL_0022: 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_0011: Unknown result type (might be due to invalid IL or missing references) if (_scriptSpawnQuery.HasValue) { return _scriptSpawnQuery.Value; } _scriptSpawnQuery = ResolveSystemQuery(instance, "ScriptSpawnServer", "_EntityQuery"); return _scriptSpawnQuery.Value; } private static EntityQuery ResolveSystemQuery(object instance, string systemName, string preferredQueryName) { //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_0030: 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) //IL_005b: 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_00b9: Unknown result type (might be due to invalid IL or missing references) Type type = instance.GetType(); object obj = type.GetField(preferredQueryName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance); if (obj is EntityQuery) { return (EntityQuery)obj; } obj = type.GetProperty(preferredQueryName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance); if (obj is EntityQuery) { return (EntityQuery)obj; } if (type.GetProperty("EntityQueries", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance) is EntityQuery[] array && array.Length != 0) { return array[0]; } if (type.GetField("EntityQueries", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance) is EntityQuery[] array2 && array2.Length != 0) { return array2[0]; } throw new InvalidOperationException("Unable to resolve " + systemName + " query."); } } internal static class CustomWeaponTypeBuffService { internal static IReadOnlyList CurrentBuffs => CustomWeaponConfig.WeaponTypeBuffs; internal static bool TryGetMatchingStats(Entity character, bool customWeaponActive, out IReadOnlyList stats, out string weaponType, out int matchedEntries) { //IL_0012: 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) stats = Array.Empty(); weaponType = string.Empty; matchedEntries = 0; if (!character.ExistsSafe()) { return false; } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(character); if (currentScope.IsUnarmed || currentScope.WeaponPrefabGuid == 0) { return false; } if (!WeaponScopeResolver.TryGetWeaponTypeForPrefab(currentScope.WeaponPrefabGuid, out weaponType)) { return false; } List list = new List(); foreach (WeaponTypeBuffDef currentBuff in CurrentBuffs) { if ((!customWeaponActive || currentBuff.ApplyToCustomWeapons) && string.Equals(currentBuff.WeaponType, weaponType, StringComparison.OrdinalIgnoreCase)) { if (currentBuff.Stats.Count == 0) { RuntimeOptimization.Debug($"WeaponTypeBuff '{currentBuff.WeaponType}' matched {weaponType}, but it has no valid stats after config parsing."); } else { matchedEntries++; list.AddRange(currentBuff.Stats); } } } if (list.Count == 0) { return false; } stats = list; return true; } internal static int ApplyAllOnline(bool forceReconcile = false) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (PlayerLookupResult onlinePlayer in PlayerLookup.GetOnlinePlayers()) { if (forceReconcile) { CustomWeaponRuntimeOverrideService.ForceStatReconcile(onlinePlayer.CharacterEntity, "applytypebuffs"); } if (CustomWeaponRuntimeOverrideService.TryApplyForPlayer(onlinePlayer, out string _)) { num++; } } return num; } internal static string Describe() { IReadOnlyList currentBuffs = CurrentBuffs; if (currentBuffs.Count == 0) { return "No enabled WeaponTypeBuffs are loaded. Check that entries have \"Enabled\": true and run .csw reload."; } return string.Join("\n", currentBuffs.Select((WeaponTypeBuffDef b) => $"{b.WeaponType}: applyToCustom:{b.ApplyToCustomWeapons} validStats:{b.Stats.Count}")); } internal static string DescribeCurrentScope(Entity character) { //IL_0000: 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_00a8: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe()) { return "Invalid character entity."; } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(character); if (currentScope.IsUnarmed) { return "Current weapon scope is unarmed. detail:" + currentScope.Detail; } if (WeaponScopeResolver.TryGetWeaponTypeForPrefab(currentScope.WeaponPrefabGuid, out string weaponType)) { bool isCustomWeapon = currentScope.IsCustomWeapon; if (TryGetMatchingStats(character, isCustomWeapon, out IReadOnlyList stats, out string _, out int matchedEntries)) { return $"Current weapon type '{weaponType}' matches {matchedEntries} WeaponTypeBuff entr{((matchedEntries == 1) ? "y" : "ies")} with {stats.Count} valid stat row(s). customWeapon:{isCustomWeapon} scope:{currentScope.ScopeKey} detail:{currentScope.Detail}"; } return $"Current weapon type '{weaponType}' has no matching enabled WeaponTypeBuffs. customWeapon:{isCustomWeapon} scope:{currentScope.ScopeKey} detail:{currentScope.Detail}"; } return $"Current weapon prefab {currentScope.WeaponPrefabGuid} is not in the WeaponScopeResolver type map. scope:{currentScope.ScopeKey} detail:{currentScope.Detail}"; } } internal static class CustomWeaponValidationService { internal static string ValidateCarriers(bool log = true) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //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_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_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) List list = new List(); int defaultCarrierBuff = PlayerSpellOverrideConfig.Current.DefaultCarrierBuff; int customWeaponCarrierBuff = CustomWeaponConfig.CustomWeaponCarrierBuff; int customWeaponStatCarrierBuff = CustomWeaponConfig.CustomWeaponStatCarrierBuff; AddCarrier(list, "player spell override ability carrier", defaultCarrierBuff, requiresAbilityBuffer: true, requiresStatBuffer: false); AddCarrier(list, "custom weapon ability carrier", customWeaponCarrierBuff, requiresAbilityBuffer: true, requiresStatBuffer: false); AddCarrier(list, "custom weapon/stat/typebuff carrier", customWeaponStatCarrierBuff, requiresAbilityBuffer: false, requiresStatBuffer: true); Dictionary>> rolesByHash = new Dictionary>>(); Mark(defaultCarrierBuff, "PlayerSpellAbilityCarrier", "player-spells.json DefaultCarrierBuff"); Mark(customWeaponCarrierBuff, "CustomWeaponAbilityCarrier", "weapons.json DefaultCustomWeaponCarrierBuff"); Mark(customWeaponStatCarrierBuff, "CustomWeaponStatCarrier", "weapons.json DefaultCustomWeaponStatCarrierBuff"); foreach (CustomWeaponDef currentWeapon in CustomWeaponRegistry.CurrentWeapons) { PrefabGUID val = currentWeapon.CarrierBuff; Mark(((PrefabGUID)(ref val)).GuidHash, "CustomWeaponAbilityCarrier", "weapon ability carrier: " + currentWeapon.Name); val = currentWeapon.StatCarrierBuff; Mark(((PrefabGUID)(ref val)).GuidHash, "CustomWeaponStatCarrier", "weapon stat carrier: " + currentWeapon.Name); val = currentWeapon.EquipBuff; if (((PrefabGUID)(ref val)).HasValue()) { val = currentWeapon.EquipBuff; Mark(((PrefabGUID)(ref val)).GuidHash, "LegacyEquipBuffField", "legacy EquipBuff field: " + currentWeapon.Name); } } foreach (KeyValuePair>> item in rolesByHash.OrderBy>>, int>((KeyValuePair>> k) => k.Key)) { List list2 = item.Value.Keys.OrderBy((string k) => k).ToList(); if (list2.Count > 1 && (list2.Contains("PlayerSpellAbilityCarrier") || list2.Contains("LegacyEquipBuffField") || (list2.Contains("CustomWeaponAbilityCarrier") && list2.Contains("CustomWeaponStatCarrier")))) { List values = item.Value.Select((KeyValuePair> role) => role.Key + ": " + string.Join(", ", role.Value.Distinct().Take(6))).ToList(); list.Add($"WARNING carrier/buff GUID {item.Key} is shared across different carrier roles: {string.Join(" | ", values)}"); } } string text = string.Join("\n", list); if (log) { foreach (string item2 in list) { if (item2.StartsWith("WARNING", StringComparison.OrdinalIgnoreCase) || item2.Contains("missing", StringComparison.OrdinalIgnoreCase) || item2.Contains("does not have", StringComparison.OrdinalIgnoreCase)) { RuntimeOptimization.WarnOnce("carrier-validation:" + item2, item2); } else { RuntimeOptimization.Debug(item2); } } } if (!string.IsNullOrWhiteSpace(text)) { return text; } return "No carrier validation output."; void Mark(int hash, string role, string owner) { if (hash != 0) { if (!rolesByHash.TryGetValue(hash, out Dictionary> value)) { value = new Dictionary>(StringComparer.OrdinalIgnoreCase); rolesByHash[hash] = value; } if (!value.TryGetValue(role, out var value2)) { value2 = (value[role] = new List()); } value2.Add(owner); } } } private static void AddCarrier(List lines, string label, int hash, bool requiresAbilityBuffer, bool requiresStatBuffer) { //IL_001b: 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_007e: Unknown result type (might be due to invalid IL or missing references) if (hash == 0) { lines.Add("WARNING " + label + ": 0 / not configured."); return; } if (!EntityExtensions.TryGetPrefabEntity(new PrefabGUID(hash), out var entity)) { lines.Add($"WARNING {label}: {hash} missing prefab."); return; } DynamicBuffer buffer; bool flag = entity.TryGetBuffer(out buffer); DynamicBuffer buffer2; bool flag2 = entity.TryGetBuffer(out buffer2); lines.Add($"{label}: {hash} exists. ReplaceAbilityOnSlotBuff:{flag} ModifyUnitStatBuff_DOTS:{flag2}"); if (requiresAbilityBuffer && !flag) { lines.Add($"WARNING {label}: {hash} does not have ReplaceAbilityOnSlotBuff."); } if (requiresStatBuffer && !flag2) { lines.Add($"WARNING {label}: {hash} does not have ModifyUnitStatBuff_DOTS."); } } } internal static class PlayerSpellOverrideService { private static bool _scopeScanQueued; private static int _scopeScanDelayTicks; private static int _cooldownRefreshTicks; private static readonly Dictionary _lastScopeByPlayer = new Dictionary(); internal static void QueueReapplyAllOnline(string reason) { _scopeScanQueued = true; _scopeScanDelayTicks = Math.Max(_scopeScanDelayTicks, 2); _cooldownRefreshTicks = Math.Max(_cooldownRefreshTicks, 12); RuntimeOptimization.Debug("Queued coalesced scope scan. Reason: " + reason); } internal static void QueueCooldownRefresh(string reason) { _cooldownRefreshTicks = Math.Max(_cooldownRefreshTicks, 12); RuntimeOptimization.Debug("Queued cooldown refresh. Reason: " + reason); } internal static void ProcessQueuedAfterReplaceAbilitySystem() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown int num = 0; if (_scopeScanQueued) { if (_scopeScanDelayTicks > 0) { _scopeScanDelayTicks--; } else { _scopeScanQueued = false; num = ApplyScopeChangesOnline(); if (num > 0) { _cooldownRefreshTicks = Math.Max(_cooldownRefreshTicks, 12); } RuntimeOptimization.Debug($"Processed coalesced scope scan after ReplaceAbilityOnSlotSystem. scopeChanges:{num}."); } } if (_cooldownRefreshTicks <= 0) { return; } _cooldownRefreshTicks--; int num2 = CustomWeaponRuntimeOverrideService.ApplyAllOnline(); int num3 = CustomWeaponRuntimeCooldownService.ApplyAllOnline(); int num4 = RefreshAllOnlineCooldowns(); if (RuntimeOptimization.DebugLogging && (num > 0 || num2 > 0 || num3 > 0 || num4 > 0)) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(131, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Runtime refresh: scope changes:"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", custom weapon overrides applied:"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num2); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", custom weapon cooldown updates:"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num3); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", player spell cooldown updates:"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num4); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance.LogInfo(val); } } private static int ApplyScopeChangesOnline() { //IL_001c: 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) int num = 0; foreach (PlayerLookupResult onlinePlayer in PlayerLookup.GetOnlinePlayers()) { string scopeKey = WeaponScopeResolver.GetCurrentScope(onlinePlayer.CharacterEntity).ScopeKey; _lastScopeByPlayer.TryGetValue(onlinePlayer.PlatformId, out string value); _lastScopeByPlayer[onlinePlayer.PlatformId] = scopeKey; RuntimeStateCache.ClearSpellHash(onlinePlayer.CharacterEntity); CustomWeaponRuntimeOverrideService.ForceStatReconcile(onlinePlayer.CharacterEntity, "queued equipment/scope refresh"); TryApplyForPlayer(onlinePlayer, out string message); num++; if (!string.Equals(value, scopeKey, StringComparison.Ordinal)) { RuntimeOptimization.Debug($"Scope changed for {onlinePlayer.Name}: {value ?? ""} -> {scopeKey}. {message}"); } else { RuntimeOptimization.Debug($"Scope refresh for {onlinePlayer.Name}: {scopeKey}. {message}"); } } return num; } private static void RecordCurrentScopes() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) foreach (PlayerLookupResult onlinePlayer in PlayerLookup.GetOnlinePlayers()) { WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(onlinePlayer.CharacterEntity); _lastScopeByPlayer[onlinePlayer.PlatformId] = currentScope.ScopeKey; } } internal static int RefreshAllOnlineCooldowns() { int num = 0; foreach (PlayerLookupResult onlinePlayer in PlayerLookup.GetOnlinePlayers()) { num += RefreshCooldownsForPlayer(onlinePlayer); } return num; } private static int RefreshCooldownsForPlayer(PlayerLookupResult player) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!TryGetActiveScopeProfile(player, out PlayerSpellOverrideEntry _, out PlayerSpellScopeEntry profile, out WeaponScopeResult _, removeCarrierOnNoProfile: false)) { return 0; } return ApplyCooldownOverridesCount(player.CharacterEntity, profile); } internal static void Initialize() { PlayerSpellOverrideConfig.LoadOrCreate(); } internal static bool TrySetSlot(PlayerLookupResult player, SpellSlotKind slot, int abilityGroupGuid, int carrierBuffGuid, out string message) { return TrySetSlotInternal(player, slot, abilityGroupGuid, null, carrierBuffGuid, out message); } internal static bool TrySetSlotAndCooldown(PlayerLookupResult player, SpellSlotKind slot, int abilityGroupGuid, float cooldownSeconds, int carrierBuffGuid, out string message) { if (cooldownSeconds < 0f) { message = "Cooldown cannot be negative."; return false; } return TrySetSlotInternal(player, slot, abilityGroupGuid, cooldownSeconds, carrierBuffGuid, out message); } internal static bool TrySetCooldown(PlayerLookupResult player, SpellSlotKind slot, float cooldownSeconds, out string message) { //IL_0013: 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 (cooldownSeconds < 0f) { message = "Cooldown cannot be negative."; return false; } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(player.CharacterEntity); if (currentScope.IsCustomWeapon) { message = "Cannot set custom spell cooldown while a custom weapon is equipped (" + currentScope.Detail + "). Custom weapons suppress player spell overrides."; return false; } PlayerSpellOverrideFile current = PlayerSpellOverrideConfig.Current; string key = player.PlatformId.ToString(); if (!current.Players.TryGetValue(key, out PlayerSpellOverrideEntry value) || !value.WeaponScopes.TryGetValue(currentScope.ScopeKey, out PlayerSpellScopeEntry value2)) { message = $"No spell override exists for {player.Name} on current scope '{currentScope.ScopeKey}'. Set an ability first while wielding that weapon type."; return false; } switch (slot) { case SpellSlotKind.Q: if (value2.Q == 0) { message = "No Q spell exists on scope '" + currentScope.ScopeKey + "'."; return false; } value2.QCooldown = cooldownSeconds; break; case SpellSlotKind.E: if (value2.E == 0) { message = "No E spell exists on scope '" + currentScope.ScopeKey + "'."; return false; } value2.ECooldown = cooldownSeconds; break; case SpellSlotKind.Dash: if (value2.Dash == 0) { message = "No Dash spell exists on scope '" + currentScope.ScopeKey + "'."; return false; } value2.DashCooldown = cooldownSeconds; break; case SpellSlotKind.R: if (value2.R == 0) { message = "No R spell exists on scope '" + currentScope.ScopeKey + "'."; return false; } value2.RCooldown = cooldownSeconds; break; case SpellSlotKind.C: if (value2.C == 0) { message = "No C spell exists on scope '" + currentScope.ScopeKey + "'."; return false; } value2.CCooldown = cooldownSeconds; break; case SpellSlotKind.T: if (value2.T == 0) { message = "No T spell exists on scope '" + currentScope.ScopeKey + "'."; return false; } value2.TCooldown = cooldownSeconds; break; default: message = $"Unsupported slot {slot}."; return false; } PlayerSpellOverrideConfig.Save(); if (!TryApply(player.CharacterEntity, value, value2, currentScope, out string message2)) { message = message2; return false; } message = $"{message2} Saved {slot} cooldown override on scope '{currentScope.ScopeKey}': {cooldownSeconds:0.##}s."; return true; } private static bool TrySetSlotInternal(PlayerLookupResult player, SpellSlotKind slot, int abilityGroupGuid, float? cooldownSeconds, int carrierBuffGuid, out string message) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) if (abilityGroupGuid == 0) { message = "Ability group GUID cannot be 0."; return false; } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(player.CharacterEntity); if (currentScope.IsCustomWeapon) { message = "Cannot bind player custom spells while a custom weapon is equipped (" + currentScope.Detail + "). Unequip it or switch to a normal weapon/unarmed first."; return false; } PlayerSpellOverrideFile current = PlayerSpellOverrideConfig.Current; string key = player.PlatformId.ToString(); if (!current.Players.TryGetValue(key, out PlayerSpellOverrideEntry value)) { value = new PlayerSpellOverrideEntry { Enabled = true, PlatformId = player.PlatformId, LastKnownName = player.Name }; current.Players[key] = value; } value.Enabled = true; value.PlatformId = player.PlatformId; value.LastKnownName = player.Name; PlayerSpellOverrideEntry playerSpellOverrideEntry = value; if (playerSpellOverrideEntry.WeaponScopes == null) { Dictionary dictionary = (playerSpellOverrideEntry.WeaponScopes = new Dictionary()); } if (carrierBuffGuid != 0) { value.CarrierBuff = carrierBuffGuid; } if (!value.WeaponScopes.TryGetValue(currentScope.ScopeKey, out PlayerSpellScopeEntry value2)) { value2 = new PlayerSpellScopeEntry(); value.WeaponScopes[currentScope.ScopeKey] = value2; } switch (slot) { case SpellSlotKind.Q: value2.Q = abilityGroupGuid; if (cooldownSeconds.HasValue) { value2.QCooldown = cooldownSeconds.Value; } break; case SpellSlotKind.E: value2.E = abilityGroupGuid; if (cooldownSeconds.HasValue) { value2.ECooldown = cooldownSeconds.Value; } break; case SpellSlotKind.Dash: value2.Dash = abilityGroupGuid; if (cooldownSeconds.HasValue) { value2.DashCooldown = cooldownSeconds.Value; } break; case SpellSlotKind.R: value2.R = abilityGroupGuid; if (cooldownSeconds.HasValue) { value2.RCooldown = cooldownSeconds.Value; } break; case SpellSlotKind.C: value2.C = abilityGroupGuid; if (cooldownSeconds.HasValue) { value2.CCooldown = cooldownSeconds.Value; } break; case SpellSlotKind.T: value2.T = abilityGroupGuid; if (cooldownSeconds.HasValue) { value2.TCooldown = cooldownSeconds.Value; } break; default: message = $"Unsupported slot {slot}."; return false; } PlayerSpellOverrideConfig.Save(); if (!TryApply(player.CharacterEntity, value, value2, currentScope, out message)) { return false; } message += $" Bound to current weapon scope '{currentScope.ScopeKey}' ({currentScope.Detail})."; return true; } internal static bool TryClearSlot(PlayerLookupResult player, string slotText, out string message) { //IL_0063: 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) PlayerSpellOverrideFile current = PlayerSpellOverrideConfig.Current; string key = player.PlatformId.ToString(); if (!current.Players.TryGetValue(key, out PlayerSpellOverrideEntry value)) { message = "No spell override exists for " + player.Name + "."; return false; } if (string.Equals(slotText, "all", StringComparison.OrdinalIgnoreCase)) { current.Players.Remove(key); PlayerSpellOverrideConfig.Save(); RemoveCarrierBuff(player.CharacterEntity, value); message = "Cleared all weapon-scoped spell overrides for " + player.Name + "."; return true; } if (!TryParseSlot(slotText, out var slot)) { message = "Invalid slot. Use q, e, dash, r, c, t, or all."; return false; } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(player.CharacterEntity); if (currentScope.IsCustomWeapon) { message = "Cannot clear a scoped player spell while custom weapon is equipped (" + currentScope.Detail + "). Use '.csw spellclear all' or switch to the target weapon type first."; return false; } if (!value.WeaponScopes.TryGetValue(currentScope.ScopeKey, out PlayerSpellScopeEntry value2)) { message = $"No spell profile exists for {player.Name} on current scope '{currentScope.ScopeKey}'."; return false; } switch (slot) { case SpellSlotKind.Q: value2.Q = 0; value2.QCooldown = 0f; break; case SpellSlotKind.E: value2.E = 0; value2.ECooldown = 0f; break; case SpellSlotKind.Dash: value2.Dash = 0; value2.DashCooldown = 0f; break; case SpellSlotKind.R: value2.R = 0; value2.RCooldown = 0f; break; case SpellSlotKind.C: value2.C = 0; value2.CCooldown = 0f; break; case SpellSlotKind.T: value2.T = 0; value2.TCooldown = 0f; break; } if (!value2.HasAnySpell()) { value.WeaponScopes.Remove(currentScope.ScopeKey); } if (value.WeaponScopes.Count == 0) { current.Players.Remove(key); } PlayerSpellOverrideConfig.Save(); return TryApplyForPlayer(player, out message); } internal static bool TryApplyForPlayer(PlayerLookupResult player, out string message) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!TryGetActiveScopeProfile(player, out PlayerSpellOverrideEntry entry, out PlayerSpellScopeEntry profile, out WeaponScopeResult scope, removeCarrierOnNoProfile: true)) { message = player.Name + ": no active scoped override for current weapon."; return false; } return TryApply(player.CharacterEntity, entry, profile, scope, out message); } internal static int ApplyAllOnline() { int num = 0; foreach (PlayerLookupResult onlinePlayer in PlayerLookup.GetOnlinePlayers()) { if (TryApplyForPlayer(onlinePlayer, out string _)) { num++; } } return num; } internal static string Describe(PlayerLookupResult player) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) PlayerSpellOverrideFile current = PlayerSpellOverrideConfig.Current; WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(player.CharacterEntity); if (!current.Players.TryGetValue(player.PlatformId.ToString(), out PlayerSpellOverrideEntry value)) { return $"{player.Name}: no override. Current scope:{currentScope.ScopeKey} ({currentScope.Detail}) customWeapon:{currentScope.IsCustomWeapon}."; } int value2 = ResolveCarrier(value); List list = new List { $"{player.Name} ({player.PlatformId}) carrier:{value2} enabled:{value.Enabled} currentScope:{currentScope.ScopeKey} detail:{currentScope.Detail} customWeapon:{currentScope.IsCustomWeapon}" }; if (value.WeaponScopes.Count == 0) { list.Add("No weapon-scoped profiles saved."); } else { foreach (KeyValuePair item in value.WeaponScopes.OrderBy, string>((KeyValuePair k) => k.Key)) { PlayerSpellScopeEntry value3 = item.Value; list.Add($"{item.Key}: Q:{value3.Q} cd:{value3.QCooldown:0.##}s E:{value3.E} cd:{value3.ECooldown:0.##}s Dash:{value3.Dash} cd:{value3.DashCooldown:0.##}s R:{value3.R} cd:{value3.RCooldown:0.##}s C:{value3.C} cd:{value3.CCooldown:0.##}s T:{value3.T} cd:{value3.TCooldown:0.##}s"); } } return string.Join("\n", list); } internal static string DescribeCurrentScope(PlayerLookupResult player) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(player.CharacterEntity); return $"{player.Name} current weapon scope: {currentScope.ScopeKey} prefab:{currentScope.WeaponPrefabGuid} unarmed:{currentScope.IsUnarmed} customWeapon:{currentScope.IsCustomWeapon} detail:{currentScope.Detail}"; } internal static bool TryParseSlot(string slotText, out SpellSlotKind slot) { slot = SpellSlotKind.Q; if (string.Equals(slotText, "q", StringComparison.OrdinalIgnoreCase)) { slot = SpellSlotKind.Q; return true; } if (string.Equals(slotText, "e", StringComparison.OrdinalIgnoreCase)) { slot = SpellSlotKind.E; return true; } if (string.Equals(slotText, "dash", StringComparison.OrdinalIgnoreCase) || string.Equals(slotText, "d", StringComparison.OrdinalIgnoreCase) || string.Equals(slotText, "space", StringComparison.OrdinalIgnoreCase)) { slot = SpellSlotKind.Dash; return true; } if (string.Equals(slotText, "r", StringComparison.OrdinalIgnoreCase)) { slot = SpellSlotKind.R; return true; } if (string.Equals(slotText, "c", StringComparison.OrdinalIgnoreCase)) { slot = SpellSlotKind.C; return true; } if (string.Equals(slotText, "t", StringComparison.OrdinalIgnoreCase) || string.Equals(slotText, "ult", StringComparison.OrdinalIgnoreCase) || string.Equals(slotText, "ultimate", StringComparison.OrdinalIgnoreCase)) { slot = SpellSlotKind.T; return true; } return false; } internal static bool TryApplyByPlatformId(ulong platformId, Entity character, out string message) { //IL_0057: 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_0066: 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_0079: 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_0097: 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_0133: Unknown result type (might be due to invalid IL or missing references) if (!PlayerSpellOverrideConfig.Current.Players.TryGetValue(platformId.ToString(), out PlayerSpellOverrideEntry value) || !value.Enabled) { message = $"No enabled override for platform id {platformId}."; return false; } WeaponScopeResult currentScope = WeaponScopeResolver.GetCurrentScope(character); if (ShapeshiftUtility.IsActiveForm(character)) { RemoveCarrierBuff(character, value); RuntimeStateCache.ClearSpellHash(character); message = "Shapeshift/form active; player spell override suppressed. form:" + ShapeshiftUtility.DescribeActiveForm(character); return false; } if (currentScope.IsCustomWeapon) { RemoveCarrierBuff(character, value); if (CustomWeaponRuntimeOverrideService.TryApplyForCharacter(character, out string message2)) { message = "Custom weapon equipped (" + currentScope.Detail + "); player spell override suppressed. " + message2; return true; } message = "Custom weapon equipped (" + currentScope.Detail + "); player spell override suppressed. " + message2; return false; } PlayerSpellOverrideEntry playerSpellOverrideEntry = value; if (playerSpellOverrideEntry.WeaponScopes == null) { Dictionary dictionary = (playerSpellOverrideEntry.WeaponScopes = new Dictionary()); } if (!value.WeaponScopes.TryGetValue(currentScope.ScopeKey, out PlayerSpellScopeEntry value2) || !value2.HasAnySpell()) { RemoveCarrierBuff(character, value); message = "No player spell profile for scope '" + currentScope.ScopeKey + "'."; return false; } return TryApply(character, value, value2, currentScope, out message); } internal static void RemoveRuntimeCarrierForForm(Entity character, ulong platformId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) RemoveRuntimeCarrierForTemporaryAbilityState(character, platformId); } internal static void RemoveRuntimeCarrierForTemporaryAbilityState(Entity character, ulong platformId) { //IL_0000: 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_0023: Unknown result type (might be due to invalid IL or missing references) if (character.ExistsSafe()) { if (PlayerSpellOverrideConfig.Current.Players.TryGetValue(platformId.ToString(), out PlayerSpellOverrideEntry value)) { RemoveCarrierBuff(character, value); } RuntimeStateCache.ClearSpellHash(character); } } private static bool TryGetActiveScopeProfile(PlayerLookupResult player, out PlayerSpellOverrideEntry entry, out PlayerSpellScopeEntry profile, out WeaponScopeResult scope, bool removeCarrierOnNoProfile) { //IL_0009: 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_0028: 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_00be: 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) entry = null; profile = null; scope = WeaponScopeResolver.GetCurrentScope(player.CharacterEntity); if (ShapeshiftUtility.IsActiveForm(player.CharacterEntity) || FeedInteractionUtility.IsActiveFeedOrExtraction(player.CharacterEntity)) { PlayerSpellOverrideFile current = PlayerSpellOverrideConfig.Current; if (removeCarrierOnNoProfile && current.Players.TryGetValue(player.PlatformId.ToString(), out PlayerSpellOverrideEntry value)) { RemoveCarrierBuff(player.CharacterEntity, value); } return false; } if (!PlayerSpellOverrideConfig.Current.Players.TryGetValue(player.PlatformId.ToString(), out entry) || !entry.Enabled) { return false; } PlayerSpellOverrideEntry playerSpellOverrideEntry = entry; if (playerSpellOverrideEntry.WeaponScopes == null) { Dictionary dictionary = (playerSpellOverrideEntry.WeaponScopes = new Dictionary()); } if (scope.IsCustomWeapon) { if (removeCarrierOnNoProfile) { RemoveCarrierBuff(player.CharacterEntity, entry); } return false; } if (!entry.WeaponScopes.TryGetValue(scope.ScopeKey, out profile) || !profile.HasAnySpell()) { if (removeCarrierOnNoProfile) { RemoveCarrierBuff(player.CharacterEntity, entry); } return false; } return true; } private static bool TryApply(Entity character, PlayerSpellOverrideEntry entry, PlayerSpellScopeEntry profile, WeaponScopeResult scope, out string message) { //IL_0000: 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_001a: 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_002e: 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_0045: 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_00df: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_024e: 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_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_015c: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: 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_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021d: 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_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe()) { message = "Target character entity is not valid."; return false; } if (ShapeshiftUtility.IsActiveForm(character)) { RemoveCarrierBuff(character, entry); RuntimeStateCache.ClearSpellHash(character); message = "Shapeshift/form active; player spell override suppressed. form:" + ShapeshiftUtility.DescribeActiveForm(character); return false; } if (scope.IsCustomWeapon) { RemoveCarrierBuff(character, entry); if (CustomWeaponRuntimeOverrideService.TryApplyForCharacter(character, out string message2)) { message = "Custom weapon equipped (" + scope.Detail + "); player spell override suppressed. " + message2; return true; } message = "Custom weapon equipped (" + scope.Detail + "); player spell override suppressed. " + message2; return false; } int num = ResolveCarrier(entry); PrefabGUID val = default(PrefabGUID); ((PrefabGUID)(ref val))..ctor(num); if (!val.TryGetPrefabEntity(out var entity)) { message = $"Carrier buff prefab {num} was not found."; return false; } if (!entity.TryGetBuffer(out DynamicBuffer _)) { message = $"Carrier buff prefab {num} does not have ReplaceAbilityOnSlotBuff buffer."; return false; } int hash = ComputeSpellHash(scope.ScopeKey, num, profile); Entity buffEntity; bool flag = RuntimeStateCache.ShouldSkipSpellApply(character, hash) && character.TryGetBuff(val, out buffEntity); if (!flag) { RemoveCarrierBuff(character, entry); ServerGameManager serverGameManager = Core.ServerGameManager; Entity buffEntity2 = default(Entity); if (!((ServerGameManager)(ref serverGameManager)).TryInstantiateBuffEntityImmediate(character, character, val, ref buffEntity2, (OnSpawnedDelegate)null, 1) && !character.TryGetBuff(val, out buffEntity2)) { message = $"Failed to apply carrier buff {num}."; return false; } if (!buffEntity2.TryGetBuffer(out DynamicBuffer buffer2)) { message = $"Applied carrier buff {num}, but its instance has no ReplaceAbilityOnSlotBuff buffer."; return false; } buffer2.Clear(); AddSlot(buffer2, 1, profile.Q); AddSlot(buffer2, 4, profile.E); AddSlot(buffer2, 2, profile.Dash); AddSlot(buffer2, 5, profile.R); AddSlot(buffer2, 6, profile.C); AddSlot(buffer2, 7, profile.T); RuntimeStateCache.SetSpellHash(character, hash); } string text = ApplyCooldownOverrides(character, profile); QueueCooldownRefresh("weapon-scoped spell override applied for " + scope.ScopeKey); message = (flag ? ("Spell overrides for scope '" + scope.ScopeKey + "' already current. " + text) : $"Applied spell overrides for scope '{scope.ScopeKey}' Q:{profile.Q} E:{profile.E} Dash:{profile.Dash} R:{profile.R} C:{profile.C} T:{profile.T} using carrier buff {num}. {text}"); return true; } private static int ComputeSpellHash(string scopeKey, int carrierHash, PlayerSpellScopeEntry profile) { HashCode hashCode = default(HashCode); hashCode.Add(scopeKey, StringComparer.Ordinal); hashCode.Add(carrierHash); hashCode.Add(profile.Q); hashCode.Add(profile.QCooldown); hashCode.Add(profile.E); hashCode.Add(profile.ECooldown); hashCode.Add(profile.Dash); hashCode.Add(profile.DashCooldown); hashCode.Add(profile.R); hashCode.Add(profile.RCooldown); hashCode.Add(profile.C); hashCode.Add(profile.CCooldown); hashCode.Add(profile.T); hashCode.Add(profile.TCooldown); return hashCode.ToHashCode(); } private static void AddSlot(DynamicBuffer replacements, int slot, int abilityGroupGuid) { //IL_0008: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (abilityGroupGuid != 0) { replacements.Add(new ReplaceAbilityOnSlotBuff { Slot = slot, NewGroupId = new PrefabGUID(abilityGroupGuid), CopyCooldown = false }); } } private static string ApplyCooldownOverrides(Entity character, PlayerSpellScopeEntry profile) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) int num = CountRequestedCooldowns(profile); if (num == 0) { return "No per-player cooldown overrides configured."; } int num2 = ApplyCooldownOverridesCount(character, profile); int value = Math.Max(0, num - num2); return $"Cooldown overrides requested:{num}, attached entities updated:{num2}, missing/not-ready:{value}."; } private static int ApplyCooldownOverridesCount(Entity character, PlayerSpellScopeEntry profile) { //IL_0001: 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_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_0061: 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) return 0 + ApplySlotCooldown(character, "Q", profile.Q, profile.QCooldown) + ApplySlotCooldown(character, "E", profile.E, profile.ECooldown) + ApplySlotCooldown(character, "Dash", profile.Dash, profile.DashCooldown) + ApplySlotCooldown(character, "R", profile.R, profile.RCooldown) + ApplySlotCooldown(character, "C", profile.C, profile.CCooldown) + ApplySlotCooldown(character, "T", profile.T, profile.TCooldown); } private static int CountRequestedCooldowns(PlayerSpellScopeEntry profile) { int num = 0; if (profile.Q != 0 && profile.QCooldown > 0f) { num++; } if (profile.E != 0 && profile.ECooldown > 0f) { num++; } if (profile.Dash != 0 && profile.DashCooldown > 0f) { num++; } if (profile.R != 0 && profile.RCooldown > 0f) { num++; } if (profile.C != 0 && profile.CCooldown > 0f) { num++; } if (profile.T != 0 && profile.TCooldown > 0f) { num++; } return num; } private static int ApplySlotCooldown(Entity character, string slotName, int abilityGroupGuidHash, float cooldownSeconds) { //IL_000d: 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 (abilityGroupGuidHash == 0 || cooldownSeconds <= 0f) { return 0; } return AbilityCooldownUtility.SetCooldownOnAttachedAbilityGroup(character, new PrefabGUID(abilityGroupGuidHash), cooldownSeconds, "PlayerSpellCooldown[" + slotName + "]"); } private static int ResolveCarrier(PlayerSpellOverrideEntry entry) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown int num = ((entry.CarrierBuff != 0) ? entry.CarrierBuff : PlayerSpellOverrideConfig.Current.DefaultCarrierBuff); if (!CustomWeaponRegistry.IsCustomWeaponEquipBuff(num)) { return num; } string customWeaponUsingEquipBuff = CustomWeaponRegistry.GetCustomWeaponUsingEquipBuff(num); int num2 = 1644894901; bool flag = default(bool); if (num2 != num && !CustomWeaponRegistry.IsCustomWeaponEquipBuff(num2)) { ManualLogSource logInstance = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(138, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Player spell carrier buff "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is also used by custom weapon '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(customWeaponUsingEquipBuff); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'. Falling back to reserved carrier "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num2); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" to avoid stripping custom weapon abilities."); } logInstance.LogWarning(val); return num2; } ManualLogSource logInstance2 = Plugin.LogInstance; BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(159, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Player spell carrier buff "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" conflicts with custom weapon '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(customWeaponUsingEquipBuff); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("', and fallback carrier "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(num2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" is also unavailable. Player spell overrides may conflict with custom weapons."); } logInstance2.LogError(val2); return num; } internal static void ClearRuntimeSpellState(Entity character) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) RuntimeStateCache.ClearSpellHash(character); } private static void RemoveCarrierBuff(Entity character, PlayerSpellOverrideEntry entry) { //IL_000f: 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_0020: 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) int num = ResolveCarrier(entry); PrefabGUID buffPrefabGuid = default(PrefabGUID); ((PrefabGUID)(ref buffPrefabGuid))..ctor(num); if (character.TryGetBuff(buffPrefabGuid, out var buffEntity)) { buffEntity.DestroySafe(); } RuntimeStateCache.ClearSpellHash(character); } } internal static class RuntimeOptimization { private static readonly HashSet _warnedOnce = new HashSet(StringComparer.Ordinal); private static readonly HashSet _infoOnce = new HashSet(StringComparer.Ordinal); private static readonly object _logLock = new object(); internal static bool DebugLogging => CustomWeaponConfig.DebugLogging; internal static void Debug(string message) { if (DebugLogging) { Plugin.LogInstance.LogInfo((object)message); } } internal static void InfoOnce(string key, string message) { lock (_logLock) { if (!_infoOnce.Add(key)) { return; } } Plugin.LogInstance.LogInfo((object)message); } internal static void WarnOnce(string key, string message) { lock (_logLock) { if (!_warnedOnce.Add(key)) { return; } } Plugin.LogInstance.LogWarning((object)message); } } internal static class RuntimePrefabCache { private static readonly Dictionary _prefabEntities = new Dictionary(); private static readonly Dictionary _abilityGroupStartPrefabs = new Dictionary(); internal static void Clear() { _prefabEntities.Clear(); _abilityGroupStartPrefabs.Clear(); } internal static bool TryGetPrefabEntity(PrefabGUID prefabGuid, out Entity entity) { //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_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_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_0042: 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_004b: 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_0068: Unknown result type (might be due to invalid IL or missing references) entity = Entity.Null; if (!((PrefabGUID)(ref prefabGuid)).HasValue()) { return false; } int guidHash = ((PrefabGUID)(ref prefabGuid)).GuidHash; if (_prefabEntities.TryGetValue(guidHash, out entity) && entity.ExistsSafe()) { return true; } try { ServerGameManager serverGameManager = Core.ServerGameManager; entity = ((ServerGameManager)(ref serverGameManager)).GetPrefabEntity(prefabGuid); if (!entity.ExistsSafe()) { return false; } _prefabEntities[guidHash] = entity; return true; } catch (Exception ex) { RuntimeOptimization.Debug($"Could not resolve prefab {guidHash}: {ex.Message}"); entity = Entity.Null; return false; } } internal static IReadOnlyList GetAbilityStartPrefabs(PrefabGUID abilityGroupGuid) { //IL_0028: 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_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_00a2: Unknown result type (might be due to invalid IL or missing references) if (!((PrefabGUID)(ref abilityGroupGuid)).HasValue()) { return Array.Empty(); } int guidHash = ((PrefabGUID)(ref abilityGroupGuid)).GuidHash; if (_abilityGroupStartPrefabs.TryGetValue(guidHash, out PrefabGUID[] value)) { return value; } if (!TryGetPrefabEntity(abilityGroupGuid, out var entity)) { _abilityGroupStartPrefabs[guidHash] = Array.Empty(); return _abilityGroupStartPrefabs[guidHash]; } if (!entity.TryGetBuffer(out DynamicBuffer buffer) || buffer.Length == 0) { _abilityGroupStartPrefabs[guidHash] = Array.Empty(); return _abilityGroupStartPrefabs[guidHash]; } PrefabGUID[] array = (PrefabGUID[])(object)new PrefabGUID[buffer.Length]; for (int i = 0; i < buffer.Length; i++) { array[i] = buffer[i].PrefabGUID; } _abilityGroupStartPrefabs[guidHash] = array; return array; } } internal static class RuntimeStateCache { private sealed class State { public string ScopeKey = string.Empty; public int SpellHash; public int CustomWeaponAbilityHash; public int RuntimeStatHash; public DateTime LastAdminWideRefreshUtc = DateTime.MinValue; } private static readonly Dictionary _states = new Dictionary(); private static long Key(Entity entity) { //IL_0000: 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) return ((long)entity.Index << 32) ^ (uint)entity.Version; } private static State Get(Entity character) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) long key = Key(character); if (!_states.TryGetValue(key, out State value)) { value = new State(); _states[key] = value; } return value; } internal static void Clear(Entity character) { //IL_0000: 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) if (character.ExistsSafe()) { _states.Remove(Key(character)); } } internal static bool IsSameScope(Entity character, string scopeKey) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return string.Equals(Get(character).ScopeKey, scopeKey, StringComparison.Ordinal); } internal static void SetScope(Entity character, string scopeKey) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Get(character).ScopeKey = scopeKey; } internal static bool ShouldSkipSpellApply(Entity character, int hash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Get(character).SpellHash == hash; } internal static void SetSpellHash(Entity character, int hash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Get(character).SpellHash = hash; } internal static void ClearSpellHash(Entity character) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Get(character).SpellHash = 0; } internal static bool ShouldSkipCustomWeaponAbilityApply(Entity character, int hash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Get(character).CustomWeaponAbilityHash == hash; } internal static void SetCustomWeaponAbilityHash(Entity character, int hash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Get(character).CustomWeaponAbilityHash = hash; } internal static void ClearCustomWeaponAbilityHash(Entity character) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Get(character).CustomWeaponAbilityHash = 0; } internal static bool ShouldSkipRuntimeStats(Entity character, int hash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Get(character).RuntimeStatHash == hash; } internal static void SetRuntimeStatHash(Entity character, int hash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Get(character).RuntimeStatHash = hash; } internal static void ClearRuntimeStatHash(Entity character) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Get(character).RuntimeStatHash = 0; } } internal static class AdminCommandRateLimiter { private static readonly Dictionary _lastRunUtc = new Dictionary(StringComparer.OrdinalIgnoreCase); internal static bool TryRun(string key, out string message) { double adminRefreshCooldownSeconds = CustomWeaponConfig.AdminRefreshCooldownSeconds; if (adminRefreshCooldownSeconds <= 0.0) { message = string.Empty; return true; } DateTime utcNow = DateTime.UtcNow; if (_lastRunUtc.TryGetValue(key, out var value)) { double totalSeconds = (utcNow - value).TotalSeconds; if (totalSeconds < adminRefreshCooldownSeconds) { message = $"Please wait {adminRefreshCooldownSeconds - totalSeconds:0.0}s before running '{key}' again."; return false; } } _lastRunUtc[key] = utcNow; message = string.Empty; return true; } } internal static class AbilityCooldownUtility { internal static int SetCooldownOnAttachedAbilityGroup(Entity character, PrefabGUID abilityGroupGuid, float cooldownSeconds, string sourceLabel) { //IL_0000: 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_0053: 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_0032: 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) if (!character.ExistsSafe() || !((PrefabGUID)(ref abilityGroupGuid)).HasValue() || cooldownSeconds <= 0f) { return 0; } IReadOnlyList abilityStartPrefabs = RuntimePrefabCache.GetAbilityStartPrefabs(abilityGroupGuid); int num = 0; if (abilityStartPrefabs.Count > 0) { for (int i = 0; i < abilityStartPrefabs.Count; i++) { num += SetCooldownOnAttachedPrefab(character, abilityStartPrefabs[i], cooldownSeconds, sourceLabel); } } else { num += SetCooldownOnAttachedPrefab(character, abilityGroupGuid, cooldownSeconds, sourceLabel); } return num; } internal static int SetCooldownOnAttachedPrefab(Entity character, PrefabGUID castGuid, float cooldownSeconds, string sourceLabel) { //IL_000d: 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_003d: 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_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_004e: 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_0059: 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_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_006a: 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_007c: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe() || !((PrefabGUID)(ref castGuid)).HasValue() || cooldownSeconds <= 0f) { return 0; } if (!character.TryGetBuffer(out DynamicBuffer buffer)) { return 0; } int num = 0; Enumerator enumerator = buffer.GetEnumerator(); while (enumerator.MoveNext()) { AttachedBuffer current = enumerator.Current; PrefabGUID prefabGuid = current.PrefabGuid; if (!((PrefabGUID)(ref prefabGuid)).Equals(castGuid)) { continue; } Entity entity = current.Entity; if (entity.ExistsSafe() && entity.Has()) { entity.With((EntityExtensions.WithRefHandler)delegate(ref AbilityCooldownData cooldown) { cooldown.Cooldown._Value = cooldownSeconds; }); num++; } } if (num > 0) { RuntimeOptimization.Debug($"{sourceLabel}: set runtime cooldown {cooldownSeconds:0.##}s on {num} attached instance(s) for prefab {((PrefabGUID)(ref castGuid)).GuidHash}."); } return num; } internal static int SetCooldownOnPrefabAbilityGroup(PrefabGUID abilityGroupGuid, float cooldownSeconds, string sourceLabel) { //IL_0013: 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_002d: 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_0052: 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_0060: 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 (!((PrefabGUID)(ref abilityGroupGuid)).HasValue() || cooldownSeconds <= 0f) { return 0; } if (!abilityGroupGuid.TryGetPrefabEntity(out var entity)) { return 0; } int num = 0; num += SetCooldownOnPrefabEntity(entity, abilityGroupGuid, cooldownSeconds, sourceLabel); if (entity.TryGetBuffer(out DynamicBuffer buffer) && buffer.Length > 0) { for (int i = 0; i < buffer.Length; i++) { PrefabGUID prefabGUID = buffer[i].PrefabGUID; if (prefabGUID.TryGetPrefabEntity(out var entity2)) { num += SetCooldownOnPrefabEntity(entity2, prefabGUID, cooldownSeconds, sourceLabel); } } } return num; } private static int SetCooldownOnPrefabEntity(Entity entity, PrefabGUID prefabGuid, float cooldownSeconds, string sourceLabel) { //IL_000d: 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 (!entity.ExistsSafe() || !entity.Has()) { return 0; } entity.With((EntityExtensions.WithRefHandler)delegate(ref AbilityCooldownData cooldown) { cooldown.Cooldown._Value = cooldownSeconds; }); RuntimeOptimization.Debug($"{sourceLabel}: set prefab cooldown {cooldownSeconds:0.##}s on prefab {((PrefabGUID)(ref prefabGuid)).GuidHash}."); return 1; } } internal static class BuffApplicationUtility { private static MethodInfo? _instantiateBuffEntityImmediate; private static bool _methodResolved; internal static bool TryApplyBuff(Entity target, Entity owner, PrefabGUID buffPrefabGuid) { //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_0029: 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_0100: 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_00d3: 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_009d: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0135: 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_0137: Unknown result type (might be due to invalid IL or missing references) if (!target.ExistsSafe() || !owner.ExistsSafe() || !((PrefabGUID)(ref buffPrefabGuid)).HasValue()) { return false; } try { if (!_methodResolved) { _methodResolved = true; _instantiateBuffEntityImmediate = ((object)Core.ServerGameManager).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "InstantiateBuffEntityImmediate"); } if ((object)_instantiateBuffEntityImmediate != null) { object[] array = _instantiateBuffEntityImmediate.GetParameters().Length switch { 5 => new object[5] { owner, target, buffPrefabGuid, null, 0 }, 4 => new object[4] { owner, target, buffPrefabGuid, 0 }, 3 => new object[3] { target, buffPrefabGuid, 0 }, _ => Array.Empty(), }; if (array.Length != 0) { _instantiateBuffEntityImmediate.Invoke(Core.ServerGameManager, array); TrySetOwner(target, owner, buffPrefabGuid); return true; } } } catch (Exception ex) { RuntimeOptimization.Debug($"InstantiateBuffEntityImmediate failed for buff {((PrefabGUID)(ref buffPrefabGuid)).GuidHash}: {ex.Message}"); } return false; } private static void TrySetOwner(Entity target, Entity owner, PrefabGUID buffPrefabGuid) { //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) //IL_000d: 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_0019: 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 (target.TryGetBuff(buffPrefabGuid, out var buffEntity) && buffEntity.Has()) { buffEntity.With((EntityExtensions.WithRefHandler)delegate(ref EntityOwner entityOwner) { //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) entityOwner.Owner = owner; }); } } } internal sealed class CustomWeaponInstanceFile { public int ConfigVersion { get; set; } = 1; public Dictionary Instances { get; set; } = new Dictionary(); } internal sealed class CustomWeaponInstanceEntry { public int SequenceGuidHash { get; set; } public string WeaponName { get; set; } = string.Empty; public int ItemWeapon { get; set; } public ulong LastKnownOwnerPlatformId { get; set; } public string LastKnownOwnerName { get; set; } = string.Empty; public string CreatedUtc { get; set; } = DateTime.UtcNow.ToString("O"); public string LastSeenUtc { get; set; } = DateTime.UtcNow.ToString("O"); } internal static class CustomWeaponInstanceStore { private const string DirectoryName = "HexesAndSanguineSteel"; private const string LegacyDirectoryName = "CustomWeaponMod"; private const string FileName = "weapon-instances.json"; private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { WriteIndented = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true, PropertyNameCaseInsensitive = true }; private static CustomWeaponInstanceFile _current = new CustomWeaponInstanceFile(); internal static string ConfigDirectory => Path.Combine(Paths.ConfigPath, "HexesAndSanguineSteel"); internal static string ConfigPath => Path.Combine(ConfigDirectory, "weapon-instances.json"); private static string LegacyConfigDirectory => Path.Combine(Paths.ConfigPath, "CustomWeaponMod"); private static string LegacyConfigPath => Path.Combine(LegacyConfigDirectory, "weapon-instances.json"); internal static int Count => _current.Instances.Count; private static void CopyLegacyConfigIfNeeded() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (!File.Exists(ConfigPath) && File.Exists(LegacyConfigPath)) { Directory.CreateDirectory(ConfigDirectory); File.Copy(LegacyConfigPath, ConfigPath, overwrite: false); ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(70, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Migrated legacy CustomWeaponMod config file to HexesAndSanguineSteel: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigPath); } logInstance.LogInfo(val); } } internal static void Initialize() { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown Directory.CreateDirectory(ConfigDirectory); CopyLegacyConfigIfNeeded(); bool flag = default(bool); if (!File.Exists(ConfigPath)) { _current = new CustomWeaponInstanceFile(); Save(); ManualLogSource logInstance = Plugin.LogInstance; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(37, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Created custom weapon instance file: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ConfigPath); } logInstance.LogInfo(val); return; } try { _current = JsonSerializer.Deserialize(File.ReadAllText(ConfigPath), JsonOptions) ?? new CustomWeaponInstanceFile(); CustomWeaponInstanceFile current = _current; if (current.Instances == null) { Dictionary dictionary = (current.Instances = new Dictionary()); } } catch (Exception ex) { string text = ConfigPath + ".broken"; try { if (File.Exists(text)) { File.Delete(text); } File.Move(ConfigPath, text); } catch (Exception ex2) { ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(47, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not back up broken weapon instance file: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex2.Message); } logInstance2.LogWarning(val2); } _current = new CustomWeaponInstanceFile(); Save(); ManualLogSource logInstance3 = Plugin.LogInstance; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(63, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Failed to load weapon instance file. Wrote a fresh one. Error: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex); } logInstance3.LogError(val3); } } internal static bool TryBindGeneratedItem(Entity itemEntity, CustomWeaponDef weapon, PlayerLookupResult receiver, out string message) { //IL_0007: 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_0058: 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) message = string.Empty; if (!itemEntity.ExistsSafe()) { message = "New item entity did not exist."; return false; } int orCreateSequenceGuid = ItemInstanceUtility.GetOrCreateSequenceGuid(itemEntity); if (orCreateSequenceGuid == 0) { message = "Could not assign a SequenceGUID to the generated weapon."; return false; } Dictionary instances = _current.Instances; string key = orCreateSequenceGuid.ToString(); CustomWeaponInstanceEntry obj = new CustomWeaponInstanceEntry { SequenceGuidHash = orCreateSequenceGuid, WeaponName = weapon.Name }; PrefabGUID itemWeapon = weapon.ItemWeapon; obj.ItemWeapon = ((PrefabGUID)(ref itemWeapon)).GuidHash; obj.LastKnownOwnerPlatformId = receiver.PlatformId; obj.LastKnownOwnerName = receiver.Name; obj.CreatedUtc = DateTime.UtcNow.ToString("O"); obj.LastSeenUtc = DateTime.UtcNow.ToString("O"); instances[key] = obj; Save(); message = $"Bound generated item instance {orCreateSequenceGuid} to custom weapon '{weapon.Name}'."; return true; } internal static bool TryBindHeldItem(Entity itemEntity, CustomWeaponDef weapon, PlayerLookupResult holder, out string message) { //IL_0007: 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_0097: 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) message = string.Empty; if (!itemEntity.ExistsSafe()) { message = "Held item entity did not exist."; return false; } int orCreateSequenceGuid = ItemInstanceUtility.GetOrCreateSequenceGuid(itemEntity); if (orCreateSequenceGuid == 0) { message = "Could not assign a SequenceGUID to the held weapon."; return false; } string key = orCreateSequenceGuid.ToString(); string value = string.Empty; if (_current.Instances.TryGetValue(key, out CustomWeaponInstanceEntry value2) && !string.IsNullOrWhiteSpace(value2.WeaponName)) { value = " Previous binding was '" + value2.WeaponName + "'."; } Dictionary instances = _current.Instances; CustomWeaponInstanceEntry obj = new CustomWeaponInstanceEntry { SequenceGuidHash = orCreateSequenceGuid, WeaponName = weapon.Name }; PrefabGUID itemWeapon = weapon.ItemWeapon; obj.ItemWeapon = ((PrefabGUID)(ref itemWeapon)).GuidHash; obj.LastKnownOwnerPlatformId = holder.PlatformId; obj.LastKnownOwnerName = holder.Name; obj.CreatedUtc = value2?.CreatedUtc ?? DateTime.UtcNow.ToString("O"); obj.LastSeenUtc = DateTime.UtcNow.ToString("O"); instances[key] = obj; Save(); message = $"Bound held item instance {orCreateSequenceGuid} to custom weapon '{weapon.Name}'.{value}"; return true; } internal static bool TryGetHeldInstanceWeapon(Entity character, out CustomWeaponDef weapon, out CustomWeaponInstanceEntry instance) { //IL_000a: 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) weapon = default(CustomWeaponDef); instance = null; if (!ItemInstanceUtility.TryGetHeldWeaponEntity(character, out var itemEntity)) { return false; } if (!ItemInstanceUtility.TryGetSequenceGuid(itemEntity, out var sequenceGuidHash)) { return false; } if (!_current.Instances.TryGetValue(sequenceGuidHash.ToString(), out instance)) { return false; } if (!CustomWeaponRegistry.TryGetCustomWeaponByName(instance.WeaponName, out weapon)) { return false; } instance.LastSeenUtc = DateTime.UtcNow.ToString("O"); return true; } internal static bool TryDescribeHeld(Entity character, out string message) { //IL_0007: 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) message = "No custom weapon instance is held."; if (!ItemInstanceUtility.TryGetHeldWeaponEntity(character, out var itemEntity)) { message = "No weapon entity is currently held."; return false; } if (!ItemInstanceUtility.TryGetSequenceGuid(itemEntity, out var sequenceGuidHash)) { message = "Held weapon has no SequenceGUID. It is not an instance-bound custom weapon."; return false; } if (!_current.Instances.TryGetValue(sequenceGuidHash.ToString(), out CustomWeaponInstanceEntry value)) { message = $"Held weapon SequenceGUID {sequenceGuidHash} is not bound to a custom weapon."; return false; } message = $"Held instance {sequenceGuidHash} -> '{value.WeaponName}' item:{value.ItemWeapon} lastOwner:{value.LastKnownOwnerName}/{value.LastKnownOwnerPlatformId}"; return true; } internal static string DescribeInstances(string filter = "") { if (_current.Instances.Count == 0) { return "No instance-bound custom weapons are saved."; } IEnumerable source = _current.Instances.Values; if (!string.IsNullOrWhiteSpace(filter)) { source = source.Where((CustomWeaponInstanceEntry e) => e.WeaponName.Contains(filter, StringComparison.OrdinalIgnoreCase) || e.SequenceGuidHash.ToString().Contains(filter, StringComparison.OrdinalIgnoreCase) || e.LastKnownOwnerName.Contains(filter, StringComparison.OrdinalIgnoreCase) || e.LastKnownOwnerPlatformId.ToString().Contains(filter, StringComparison.OrdinalIgnoreCase)); } List list = (from e in (from e in source orderby e.WeaponName, e.SequenceGuidHash select e).Take(50) select $"{e.SequenceGuidHash}: '{e.WeaponName}' item:{e.ItemWeapon} lastOwner:{e.LastKnownOwnerName}/{e.LastKnownOwnerPlatformId} lastSeen:{e.LastSeenUtc}").ToList(); if (list.Count == 0) { return "No saved instance weapons matched that filter."; } if (_current.Instances.Count > list.Count) { list.Add($"Showing {list.Count} of {_current.Instances.Count}. Use a filter to narrow results."); } return string.Join("\n", list); } internal static int PruneInvalidWeaponNames() { HashSet validNames = new HashSet(CustomWeaponRegistry.CurrentWeapons.Select((CustomWeaponDef w) => w.Name), StringComparer.OrdinalIgnoreCase); List list = (from kvp in _current.Instances where string.IsNullOrWhiteSpace(kvp.Value.WeaponName) || !validNames.Contains(kvp.Value.WeaponName) select kvp.Key).ToList(); foreach (string item in list) { _current.Instances.Remove(item); } if (list.Count > 0) { Save(); } return list.Count; } private static void Save() { Directory.CreateDirectory(ConfigDirectory); File.WriteAllText(ConfigPath, JsonSerializer.Serialize(_current, JsonOptions)); } } internal static class EntityExtensions { public delegate void WithRefHandler(ref T item) where T : struct; internal static bool ExistsSafe(this Entity entity) { //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_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_0015: Unknown result type (might be due to invalid IL or missing references) if (entity != Entity.Null) { EntityManager entityManager = Core.EntityManager; return ((EntityManager)(ref entityManager)).Exists(entity); } return false; } internal static bool Has(this Entity entity) where T : struct { //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_000d: 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) if (entity.ExistsSafe()) { EntityManager entityManager = Core.EntityManager; return ((EntityManager)(ref entityManager)).HasComponent(entity); } return false; } internal static bool TryRead(this Entity entity, out T value) where T : struct { //IL_0007: 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_0017: 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) value = default(T); if (!entity.Has()) { return false; } EntityManager entityManager = Core.EntityManager; value = ((EntityManager)(ref entityManager)).GetComponentData(entity); return true; } internal static void With(this Entity entity, WithRefHandler action) where T : struct { //IL_0000: 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_006e: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!entity.TryRead(out var value)) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(23, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Missing component "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(typeof(T).Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" on "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(entity); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance.LogWarning(val); } else { action(ref value); EntityManager entityManager = Core.EntityManager; ((EntityManager)(ref entityManager)).SetComponentData(entity, value); } } internal static bool TryGetBuffer(this Entity entity, out DynamicBuffer buffer) where T : struct { //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_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_0017: 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_0027: 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_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) buffer = default(DynamicBuffer); if (entity.ExistsSafe()) { EntityManager entityManager = Core.EntityManager; if (((EntityManager)(ref entityManager)).HasBuffer(entity)) { entityManager = Core.EntityManager; buffer = ((EntityManager)(ref entityManager)).GetBuffer(entity, false); return true; } } return false; } internal static void ClearBuffer(this Entity entity) where T : struct { //IL_0000: 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: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!entity.TryGetBuffer(out var buffer)) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(20, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Missing buffer "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(typeof(T).Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" on "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(entity); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance.LogWarning(val); } else { buffer.Clear(); } } internal static void AddToBuffer(this Entity entity, T element) where T : struct { //IL_0000: 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: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!entity.TryGetBuffer(out var buffer)) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(20, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Missing buffer "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(typeof(T).Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" on "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(entity); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance.LogWarning(val); } else { buffer.Add(element); } } internal static void EditBuffer(this Entity entity, int index, WithRefHandler action) where T : struct { //IL_0000: 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: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); if (!entity.TryGetBuffer(out var buffer)) { ManualLogSource logInstance = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(20, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Missing buffer "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(typeof(T).Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" on "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(entity); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance.LogWarning(val); } else if ((uint)index >= (uint)buffer.Length) { ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(38, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Buffer index "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(index); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" out of range for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(typeof(T).Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; len="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(buffer.Length); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance2.LogWarning(val); } else { T item = buffer[index]; action(ref item); buffer[index] = item; } } internal static void InsertBuffer(this Entity entity, int index, T element) where T : struct { //IL_0000: 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: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); if (!entity.TryGetBuffer(out var buffer)) { ManualLogSource logInstance = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(20, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Missing buffer "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(typeof(T).Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" on "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(entity); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance.LogWarning(val); } else if ((uint)index > (uint)buffer.Length) { ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(38, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Insert index "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(index); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" out of range for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(typeof(T).Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; len="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(buffer.Length); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logInstance2.LogWarning(val); } else { buffer.Insert(index, element); } } internal static bool TryGetBuff(this Entity target, PrefabGUID buffPrefabGuid, out Entity buffEntity) { //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_000b: 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_0026: 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_0037: Unknown result type (might be due to invalid IL or missing references) buffEntity = Entity.Null; if (!target.ExistsSafe() || !((PrefabGUID)(ref buffPrefabGuid)).HasValue()) { return false; } ServerGameManager serverGameManager = Core.ServerGameManager; if (((ServerGameManager)(ref serverGameManager)).TryGetBuff(target, ((PrefabGUID)(ref buffPrefabGuid)).ToIdentifier(), ref buffEntity)) { return buffEntity.ExistsSafe(); } return false; } internal static bool HasBuff(this Entity target, PrefabGUID buffPrefabGuid) { //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) Entity buffEntity; return target.TryGetBuff(buffPrefabGuid, out buffEntity); } internal static bool TryApplyBuffSimple(this Entity target, PrefabGUID buffPrefabGuid) { //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_0002: Unknown result type (might be due to invalid IL or missing references) return BuffApplicationUtility.TryApplyBuff(target, target, buffPrefabGuid); } internal static bool TryApplyBuffWithOwner(this Entity target, Entity owner, PrefabGUID buffPrefabGuid) { //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_0002: Unknown result type (might be due to invalid IL or missing references) return BuffApplicationUtility.TryApplyBuff(target, owner, buffPrefabGuid); } internal static void DestroySafe(this Entity entity) { //IL_0000: 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_006e: 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_0013: 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_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) if (!entity.ExistsSafe() || entity.Has()) { return; } try { if (entity.Has()) { DestroyUtility.Destroy(Core.EntityManager, entity, (DestroyDebugReason)13, (string)null, 0); } else { DestroyUtility.Destroy(Core.EntityManager, entity, (DestroyDebugReason)0, (string)null, 0); } } catch (Exception ex) { RuntimeOptimization.Debug($"DestroySafe skipped stale entity {entity.Index}:{entity.Version}: {ex.Message}"); } } internal static bool TryGetPrefabEntity(this PrefabGUID prefabGuid, out Entity entity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return RuntimePrefabCache.TryGetPrefabEntity(prefabGuid, out entity); } internal static bool HasValue(this PrefabGUID prefabGuid) { return ((PrefabGUID)(ref prefabGuid)).GuidHash != 0; } } internal static class FeedInteractionUtility { private static readonly HashSet FeedAndExtractionPrefabs = new HashSet { -1114937852, -376210658, 1535667383, 1231644507, -2068632541, -1414476683, 366323518, 1548379114, 1787637039, -1106009274, -1948299363, -139079478, 1418642324, -948311829, 1851942548, 697172810, -1347356700, -1797102561, -1031870834, 958508368, 1233405326, -670750933, 1790847128, -649630224, 51055185, -1560986745, 1340086775, 1306418337, 1229263634, 1186118159, -206231665, 1491658671, -1573506596, -1044861452, -1565434117, 250152500, 713711633, -1889378229, -331003702, 1815101964, 1393329717, -1529850854, -1551286374, 253163764, 1301390971, -1212689323, -526712042, -604904760, -1581547715, 391943159, 1283732362, 1798838621, -1365570044, 950997250, -1399190295, -578672354, -1213188934, -1006431398, -856042777, -264516260, 1501158829, -877555015, 1690123127, -1278121774, -316716610, 236713613, 117247654, 1739570447, -1275273993, -1745004158, 585228944, -1695763915, -234803016, -1335827123, -1446310610, 402061920, 1289149810, -1669827947, -354622715, 579690183, 1754040702, 1525766239, -595871655, 1586616867, 1508231357, -205830402, 2072201164, -1354315272, -938281780, -179005483 }; internal static bool IsActiveFeedOrExtraction(Entity character) { //IL_0000: 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_0021: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe()) { return false; } foreach (int feedAndExtractionPrefab in FeedAndExtractionPrefabs) { if (character.TryGetBuff(new PrefabGUID(feedAndExtractionPrefab), out var _)) { return true; } } return false; } internal static bool IsFeedOrExtractionReplacementBuff(Entity buffEntity) { //IL_0000: 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) if (!buffEntity.ExistsSafe()) { return false; } if (!buffEntity.TryRead(out PrefabGUID value)) { return false; } return FeedAndExtractionPrefabs.Contains(((PrefabGUID)(ref value)).GuidHash); } internal static string DescribeActiveFeedOrExtraction(Entity character) { //IL_0000: 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_0025: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe()) { return "none"; } foreach (int feedAndExtractionPrefab in FeedAndExtractionPrefabs) { if (character.TryGetBuff(new PrefabGUID(feedAndExtractionPrefab), out var _)) { return feedAndExtractionPrefab.ToString(); } } return "none"; } } internal static class InventoryCostUtility { private static readonly string[] RemoveMethodNames = new string[6] { "TryRemoveInventoryItem", "RemoveInventoryItem", "TryRemoveItem", "RemoveItem", "ConsumeInventoryItem", "TryConsumeInventoryItem" }; internal static bool TryConsumeUpgradeCost(PlayerLookupResult player, IReadOnlyList costs, out string message) { //IL_0018: 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_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_0083: 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_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) message = string.Empty; if (costs.Count == 0) { message = "No extra upgrade cost configured."; return true; } Entity inventoryEntity = default(Entity); if (!InventoryUtilities.TryGetInventoryEntity(Core.EntityManager, player.CharacterEntity, ref inventoryEntity, 0)) { message = "Could not resolve inventory entity for '" + player.Name + "'."; return false; } List list = new List(); foreach (CustomWeaponCostDef cost in costs) { PrefabGUID item = cost.Item; if (((PrefabGUID)(ref item)).HasValue() && cost.Amount > 0) { if (!TryRemoveItem(inventoryEntity, cost.Item, cost.Amount, out string message2)) { string value = ((list.Count == 0) ? string.Empty : (" Already consumed before failure: " + string.Join(", ", list) + ".")); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(49, 5); defaultInterpolatedStringHandler.AppendLiteral("Missing or could not consume upgrade cost "); defaultInterpolatedStringHandler.AppendFormatted(cost.Amount); defaultInterpolatedStringHandler.AppendLiteral("x "); defaultInterpolatedStringHandler.AppendFormatted(cost.Name); defaultInterpolatedStringHandler.AppendLiteral(" ("); item = cost.Item; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref item)).GuidHash); defaultInterpolatedStringHandler.AppendLiteral("). "); defaultInterpolatedStringHandler.AppendFormatted(message2); defaultInterpolatedStringHandler.AppendFormatted(value); message = defaultInterpolatedStringHandler.ToStringAndClear(); return false; } list.Add($"{cost.Amount}x {cost.Name}"); } } message = ((list.Count == 0) ? "No valid extra upgrade cost configured." : ("Consumed upgrade cost: " + string.Join(", ", list) + ".")); return true; } private static bool TryRemoveItem(Entity inventoryEntity, PrefabGUID item, int amount, out string message) { //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_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_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) message = string.Empty; if (TryInvokeRemoveMethod(Core.ServerGameManager, ((object)Core.ServerGameManager).GetType(), inventoryEntity, item, amount, out var success, out message)) { return success; } Assembly assembly = typeof(InventoryUtilities).Assembly; string[] array = new string[3] { "ProjectM.InventoryUtilities", "ProjectM.InventoryUtilitiesServer", "ProjectM.InventoryUtilities_Server" }; foreach (string name in array) { Type type = assembly.GetType(name); if ((object)type != null && TryInvokeRemoveMethod(null, type, inventoryEntity, item, amount, out success, out message)) { return success; } } message = "No compatible inventory item removal method was found in this VRA build."; return false; } private static bool TryInvokeRemoveMethod(object? instance, Type type, Entity inventoryEntity, PrefabGUID item, int amount, out bool success, out string message) { //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) success = false; message = string.Empty; BindingFlags bindingAttr = (BindingFlags)(0x30 | ((instance == null) ? 8 : 4)); MethodInfo[] methods = type.GetMethods(bindingAttr); foreach (MethodInfo method in methods) { if (RemoveMethodNames.Any((string name) => string.Equals(method.Name, name, StringComparison.OrdinalIgnoreCase)) && TryBuildArguments(method, inventoryEntity, item, amount, out object[] args)) { try { object result = method.Invoke(instance, args); success = InterpretResult(result); message = (success ? $"Removed {amount}x {((PrefabGUID)(ref item)).GuidHash} using {type.Name}.{method.Name}." : (type.Name + "." + method.Name + " returned failure.")); return true; } catch (TargetInvocationException ex) { message = $"{type.Name}.{method.Name} failed: {ex.InnerException?.Message ?? ex.Message}"; return true; } catch (Exception ex2) { message = $"{type.Name}.{method.Name} failed: {ex2.Message}"; return true; } } } return false; } private static bool TryBuildArguments(MethodInfo method, Entity inventoryEntity, PrefabGUID item, int amount, out object?[] args) { //IL_0043: 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_008e: Unknown result type (might be due to invalid IL or missing references) ParameterInfo[] parameters = method.GetParameters(); args = new object[parameters.Length]; bool flag = false; bool flag2 = false; bool flag3 = false; for (int i = 0; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; if (parameterType == typeof(EntityManager)) { args[i] = Core.EntityManager; continue; } if (parameterType == typeof(Entity)) { args[i] = inventoryEntity; flag = true; continue; } if (parameterType == typeof(PrefabGUID)) { args[i] = item; flag2 = true; continue; } if (parameterType == typeof(int)) { args[i] = amount; flag3 = true; continue; } if (parameterType == typeof(bool)) { args[i] = false; continue; } return false; } return flag && flag2 && flag3; } private static bool InterpretResult(object? result) { if (result == null) { return true; } if (result is bool) { return (bool)result; } Type type = result.GetType(); PropertyInfo property = type.GetProperty("Success", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property != null && property.PropertyType == typeof(bool)) { return (bool)(property.GetValue(result) ?? ((object)false)); } FieldInfo field = type.GetField("Success", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)field != null && field.FieldType == typeof(bool)) { return (bool)(field.GetValue(result) ?? ((object)false)); } return true; } } internal static class ItemInstanceUtility { internal static bool TryGetHeldWeaponEntity(Entity character, out Entity itemEntity) { //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_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_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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_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) itemEntity = Entity.Null; if (!character.ExistsSafe() || !character.TryRead(out Equipment value)) { return false; } itemEntity = value.WeaponSlot.SlotEntity._Entity; return itemEntity.ExistsSafe(); } internal static bool TryGetHeldWeaponPrefab(Entity character, out PrefabGUID prefabGuid) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) prefabGuid = default(PrefabGUID); if (!TryGetHeldWeaponEntity(character, out var itemEntity)) { return false; } if (itemEntity.TryRead(out prefabGuid)) { return ((PrefabGUID)(ref prefabGuid)).HasValue(); } return false; } internal static bool TryGetHeldWeaponEquipBuff(Entity character, out PrefabGUID buffGuid) { //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_001c: 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_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_003b: Unknown result type (might be due to invalid IL or missing references) buffGuid = default(PrefabGUID); if (!TryGetHeldWeaponPrefab(character, out var prefabGuid) || !((PrefabGUID)(ref prefabGuid)).HasValue()) { return false; } if (!prefabGuid.TryGetPrefabEntity(out var entity)) { return false; } if (!entity.TryRead(out EquippableData value)) { return false; } buffGuid = value.BuffGuid; return ((PrefabGUID)(ref buffGuid)).HasValue(); } internal static bool TryGetSequenceGuid(Entity itemEntity, out int sequenceGuidHash) { //IL_0003: 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_001a: Unknown result type (might be due to invalid IL or missing references) sequenceGuidHash = 0; if (!itemEntity.ExistsSafe()) { return false; } if (!itemEntity.TryRead(out SequenceGUID value)) { return false; } sequenceGuidHash = value.GuidHash; return sequenceGuidHash != 0; } internal static int GetOrCreateSequenceGuid(Entity itemEntity) { //IL_0000: 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_002a: Unknown result type (might be due to invalid IL or missing references) if (TryGetSequenceGuid(itemEntity, out var sequenceGuidHash)) { return sequenceGuidHash; } int hashCode = Guid.NewGuid().GetHashCode(); EntityManager entityManager = Core.EntityManager; ((EntityManager)(ref entityManager)).AddComponentData(itemEntity, new SequenceGUID(hashCode)); return hashCode; } } internal readonly record struct PlayerLookupResult(ulong PlatformId, string Name, Entity UserEntity, Entity CharacterEntity, User User); internal static class PlayerLookup { internal static bool TryFindOnlinePlayer(string nameOrPlatformId, out PlayerLookupResult result) { //IL_001d: 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_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_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) //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_004b: 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_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_0063: 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_0075: 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_0087: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) result = default(PlayerLookupResult); if (string.IsNullOrWhiteSpace(nameOrPlatformId)) { return false; } ulong result2 = 0uL; bool flag = ulong.TryParse(nameOrPlatformId, out result2); EntityManager entityManager = Core.EntityManager; EntityQuery val = ((EntityManager)(ref entityManager)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly() }); NativeArray val2 = ((EntityQuery)(ref val)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { Enumerator enumerator = val2.GetEnumerator(); while (enumerator.MoveNext()) { Entity current = enumerator.Current; if (!current.ExistsSafe()) { continue; } entityManager = Core.EntityManager; if (((EntityManager)(ref entityManager)).HasComponent(current)) { entityManager = Core.EntityManager; User componentData = ((EntityManager)(ref entityManager)).GetComponentData(current); ulong platformId = componentData.PlatformId; string value = ((FixedString64Bytes)(ref componentData.CharacterName)).Value; if (flag ? (platformId == result2) : string.Equals(value, nameOrPlatformId, StringComparison.OrdinalIgnoreCase)) { Entity entityOnServer = ((NetworkedEntity)(ref componentData.LocalCharacter)).GetEntityOnServer(); result = new PlayerLookupResult(platformId, value, current, entityOnServer, componentData); return entityOnServer.ExistsSafe(); } } } } finally { val2.Dispose(); ((EntityQuery)(ref val)).Dispose(); } return false; } internal static bool TryFindOnlinePlayer(Entity characterEntity, out PlayerLookupResult result) { //IL_0007: 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) result = default(PlayerLookupResult); if (!characterEntity.ExistsSafe()) { return false; } foreach (PlayerLookupResult onlinePlayer in GetOnlinePlayers()) { Entity characterEntity2 = onlinePlayer.CharacterEntity; if (((Entity)(ref characterEntity2)).Equals(characterEntity)) { result = onlinePlayer; return true; } } return false; } internal static List GetOnlinePlayers() { //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_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_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_0029: 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_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_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_0048: 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_0059: 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_006a: 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_007a: 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_0081: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) List list = new List(); EntityManager entityManager = Core.EntityManager; EntityQuery val = ((EntityManager)(ref entityManager)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly() }); NativeArray val2 = ((EntityQuery)(ref val)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { Enumerator enumerator = val2.GetEnumerator(); while (enumerator.MoveNext()) { Entity current = enumerator.Current; if (!current.ExistsSafe()) { continue; } entityManager = Core.EntityManager; if (((EntityManager)(ref entityManager)).HasComponent(current)) { entityManager = Core.EntityManager; User componentData = ((EntityManager)(ref entityManager)).GetComponentData(current); Entity entityOnServer = ((NetworkedEntity)(ref componentData.LocalCharacter)).GetEntityOnServer(); if (entityOnServer.ExistsSafe()) { list.Add(new PlayerLookupResult(componentData.PlatformId, ((FixedString64Bytes)(ref componentData.CharacterName)).Value, current, entityOnServer, componentData)); } } } return list; } finally { val2.Dispose(); ((EntityQuery)(ref val)).Dispose(); } } } internal static class ShapeshiftUtility { private static readonly HashSet ActiveFormBuffs = new HashSet { 1205505492, -1569370346, -858273386, -1447419822, 914043867, -53860211, -434940480, -868350144, 902394170, -2126626806, 124832551, -1665328650, -1038422434, 332075952, -351718282, -46579774, -1687924191, -1158884666, -395216184, 1352541204, 361281067, -222170350, 1199823151, -728707862, -1882904996, -1075909278 }; internal static bool IsActiveForm(Entity character) { //IL_0000: 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_0021: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe()) { return false; } foreach (int activeFormBuff in ActiveFormBuffs) { if (character.TryGetBuff(new PrefabGUID(activeFormBuff), out var _)) { return true; } } return false; } internal static bool IsFormReplacementBuff(Entity buffEntity) { //IL_0000: 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) if (!buffEntity.ExistsSafe()) { return false; } if (!buffEntity.TryRead(out PrefabGUID value)) { return false; } return ActiveFormBuffs.Contains(((PrefabGUID)(ref value)).GuidHash); } internal static string DescribeActiveForm(Entity character) { //IL_0000: 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_0025: Unknown result type (might be due to invalid IL or missing references) if (!character.ExistsSafe()) { return "none"; } foreach (int activeFormBuff in ActiveFormBuffs) { if (character.TryGetBuff(new PrefabGUID(activeFormBuff), out var _)) { return activeFormBuff.ToString(); } } return "none"; } } internal readonly record struct WeaponScopeResult(string ScopeKey, int WeaponPrefabGuid, bool IsUnarmed, bool IsCustomWeapon, string Detail); internal static class WeaponScopeResolver { internal const string UnarmedScope = "Unarmed"; private static readonly Dictionary WeaponTypeByItemPrefab = new Dictionary { [-2147445292] = "Axe", [-2044057823] = "Axe", [-1958888844] = "Axe", [-1579575933] = "Axe", [-1391446205] = "Axe", [-1130238142] = "Axe", [-1024626758] = "Axe", [-491969324] = "Axe", [-102830349] = "Axe", [163122449] = "Axe", [198951695] = "Axe", [442700150] = "Axe", [518802008] = "Axe", [1239564213] = "Axe", [1259464735] = "Axe", [1541522788] = "Axe", [1570017693] = "Axe", [2099198078] = "Axe", [2100090213] = "Axe", [-2060572315] = "Claws", [-1777908217] = "Claws", [-1774269887] = "Claws", [-1746159915] = "Claws", [-1470260175] = "Claws", [-1333849822] = "Claws", [-1024379681] = "Claws", [-996999913] = "Claws", [-655493979] = "Claws", [-444900575] = "Claws", [-27238530] = "Claws", [1401940772] = "Claws", [1748886117] = "Claws", [-1636801169] = "Crossbow", [-1401104184] = "Crossbow", [-1277074895] = "Crossbow", [-814739263] = "Crossbow", [-517906196] = "Crossbow", [-20041991] = "Crossbow", [517296275] = "Crossbow", [572026243] = "Crossbow", [781586362] = "Crossbow", [836066667] = "Crossbow", [898159697] = "Crossbow", [935392085] = "Crossbow", [1221976097] = "Crossbow", [1389040540] = "Crossbow", [1716435762] = "Crossbow", [1957540013] = "Crossbow", [1958482379] = "Crossbow", [2061238391] = "Crossbow", [-2137269775] = "Daggers", [-1961050884] = "Daggers", [-1873605364] = "Daggers", [-1566606969] = "Daggers", [-1276458869] = "Daggers", [-1233207977] = "Daggers", [-1075670534] = "Daggers", [-816018167] = "Daggers", [-211034148] = "Daggers", [140761255] = "Daggers", [703783407] = "Daggers", [1031107636] = "Daggers", [1296724931] = "Daggers", [1719144622] = "Daggers", [-1766408331] = "FishingPole", [1302850112] = "FishingPole", [-1743584975] = "GreatSword", [-1638796801] = "GreatSword", [-1173681254] = "GreatSword", [-768054337] = "GreatSword", [-437176953] = "GreatSword", [-256643998] = "GreatSword", [82781195] = "GreatSword", [147836723] = "GreatSword", [674704033] = "GreatSword", [747911021] = "GreatSword", [820408138] = "GreatSword", [869276797] = "GreatSword", [1272855317] = "GreatSword", [1322254792] = "GreatSword", [-1993708658] = "Longbow", [-1830162796] = "Longbow", [-1003309553] = "Longbow", [-726074700] = "Longbow", [-557203874] = "Longbow", [19130904] = "Longbow", [285875674] = "Longbow", [288292636] = "Longbow", [352247730] = "Longbow", [532033005] = "Longbow", [649637190] = "Longbow", [1102277512] = "Longbow", [1177453385] = "Longbow", [1283345494] = "Longbow", [1860352606] = "Longbow", [1951565953] = "Longbow", [-2048346225] = "Mace", [-1998017941] = "Mace", [-1845443712] = "Mace", [-1810734832] = "Mace", [-1714012261] = "Mace", [-915028618] = "Mace", [-687294429] = "Mace", [-331345186] = "Mace", [-276593802] = "Mace", [-184713893] = "Mace", [-126076280] = "Mace", [160471982] = "Mace", [264593098] = "Mace", [343324920] = "Mace", [675187526] = "Mace", [1177597629] = "Mace", [1588258447] = "Mace", [1963988265] = "Mace", [1994084762] = "Mace", [-1843989041] = "Pistols", [-1502177717] = "Pistols", [-1265586439] = "Pistols", [-1038642372] = "Pistols", [-944318126] = "Pistols", [14297698] = "Pistols", [674407758] = "Pistols", [769603740] = "Pistols", [1040125618] = "Pistols", [1071656850] = "Pistols", [1333624152] = "Pistols", [1630030026] = "Pistols", [1759077469] = "Pistols", [1850870666] = "Pistols", [-2136716453] = "Reaper", [-2081286944] = "Reaper", [-2053917766] = "Reaper", [-922125625] = "Reaper", [-859437190] = "Reaper", [-576626587] = "Reaper", [-465491217] = "Reaper", [-413259500] = "Reaper", [-383870009] = "Reaper", [-152327780] = "Reaper", [-105026635] = "Reaper", [6711686] = "Reaper", [886814985] = "Reaper", [1048518929] = "Reaper", [1402953369] = "Reaper", [1522792650] = "Reaper", [1778128946] = "Reaper", [1801132968] = "Reaper", [1887724512] = "Reaper", [-2068145306] = "Slashers", [-1930402723] = "Slashers", [-1390536751] = "Slashers", [-1042299347] = "Slashers", [-588909332] = "Slashers", [-314614708] = "Slashers", [3759455] = "Slashers", [506082542] = "Slashers", [633666898] = "Slashers", [658426701] = "Slashers", [810808231] = "Slashers", [821410795] = "Slashers", [866934844] = "Slashers", [926722036] = "Slashers", [1271087499] = "Slashers", [1322545846] = "Slashers", [1499160417] = "Slashers", [1570363331] = "Slashers", [1930526079] = "Slashers", [1954207008] = "Slashers", [-1931117134] = "Spear", [-1854790299] = "Spear", [-1674680373] = "Spear", [-958110636] = "Spear", [-850142339] = "Spear", [-352704566] = "Spear", [124616797] = "Spear", [790210443] = "Spear", [912809090] = "Spear", [1065194820] = "Spear", [1244180446] = "Spear", [1307774440] = "Spear", [1370755976] = "Spear", [1717016192] = "Spear", [1853029976] = "Spear", [2001389164] = "Spear", [2038011836] = "Spear", [2142983740] = "Spear", [-2085919458] = "Sword", [-2037272000] = "Sword", [-1455388114] = "Sword", [-1421775051] = "Sword", [-1219959051] = "Sword", [-1215982687] = "Sword", [-903587404] = "Sword", [-830893351] = "Sword", [-796306296] = "Sword", [-774462329] = "Sword", [-435501075] = "Sword", [195858450] = "Sword", [220001518] = "Sword", [1048769481] = "Sword", [1564801426] = "Sword", [1637216050] = "Sword", [1908755405] = "Sword", [2106567892] = "Sword", [-1651990235] = "TwinBlades", [-1634108038] = "TwinBlades", [-1595292245] = "TwinBlades", [-1397287045] = "TwinBlades", [-1122389049] = "TwinBlades", [-699863795] = "TwinBlades", [-297349982] = "TwinBlades", [-228881628] = "TwinBlades", [152014105] = "TwinBlades", [601169005] = "TwinBlades", [1479621167] = "TwinBlades", [1579758125] = "TwinBlades", [1835208468] = "TwinBlades", [2023500574] = "TwinBlades", [-1222824286] = "Whip", [-960205578] = "Whip", [-882837429] = "Whip", [-847062445] = "Whip", [-671246832] = "Whip", [-655095317] = "Whip", [429323760] = "Whip", [567413754] = "Whip", [950358400] = "Whip", [1340494453] = "Whip", [1393113320] = "Whip", [1490846791] = "Whip", [1705984031] = "Whip", [1838862498] = "Whip" }; private static readonly HashSet ShadowMatterWeaponPrefabs = new HashSet { 2100090213, 1957540013, -1961050884, 1322254792, 1283345494, 160471982, -1265586439, -465491217, 506082542, 1307774440, -1215982687, -699863795, 567413754 }; internal static bool IsShadowMatterWeaponPrefab(int itemWeaponGuidHash) { return ShadowMatterWeaponPrefabs.Contains(itemWeaponGuidHash); } internal static bool TryGetWeaponTypeForPrefab(int itemWeaponGuidHash, out string weaponType) { return WeaponTypeByItemPrefab.TryGetValue(itemWeaponGuidHash, out weaponType); } internal static WeaponScopeResult GetCurrentScope(Entity character) { //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_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_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_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_0051: 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) if (!character.ExistsSafe() || !character.TryRead(out Equipment value)) { return new WeaponScopeResult("Unarmed", 0, IsUnarmed: true, IsCustomWeapon: false, "No valid character/equipment component."); } Entity entity = value.WeaponSlot.SlotEntity._Entity; if (!entity.ExistsSafe()) { return new WeaponScopeResult("Unarmed", 0, IsUnarmed: true, IsCustomWeapon: false, "No weapon entity equipped."); } if (!entity.TryRead(out PrefabGUID value2) || !((PrefabGUID)(ref value2)).HasValue()) { return new WeaponScopeResult("Unarmed", 0, IsUnarmed: true, IsCustomWeapon: false, "Equipped weapon has no PrefabGUID."); } int guidHash = ((PrefabGUID)(ref value2)).GuidHash; if (CustomWeaponInstanceStore.TryGetHeldInstanceWeapon(character, out CustomWeaponDef weapon, out CustomWeaponInstanceEntry instance)) { return new WeaponScopeResult($"CustomWeaponInstance:{instance.SequenceGuidHash}", guidHash, IsUnarmed: false, IsCustomWeapon: true, $"{weapon.Name} instance:{instance.SequenceGuidHash}"); } if (CustomWeaponRegistry.IsCustomWeaponItem(guidHash)) { string customWeaponName = CustomWeaponRegistry.GetCustomWeaponName(guidHash); return new WeaponScopeResult($"CustomWeapon:{guidHash}", guidHash, IsUnarmed: false, IsCustomWeapon: true, customWeaponName); } if (WeaponTypeByItemPrefab.TryGetValue(guidHash, out string value3)) { return new WeaponScopeResult(value3, guidHash, IsUnarmed: false, IsCustomWeapon: false, value3); } return new WeaponScopeResult($"Item:{guidHash}", guidHash, IsUnarmed: false, IsCustomWeapon: false, $"Unknown weapon item {guidHash}"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "HexesAndSanguineSteel"; public const string PLUGIN_NAME = "HexesAndSanguineSteel"; public const string PLUGIN_VERSION = "1.0.1"; } } namespace HexesAndSanguineSteel.Patches { [HarmonyPatch] internal static class EquipmentReapplyPatches { [HarmonyPatch(typeof(EquipItemSystem), "OnUpdate")] [HarmonyPostfix] private static void EquipItemSystemPostfix() { PlayerSpellOverrideService.QueueReapplyAllOnline("EquipItemSystem"); } [HarmonyPatch(typeof(EquipItemFromInventorySystem), "OnUpdate")] [HarmonyPostfix] private static void EquipItemFromInventorySystemPostfix() { PlayerSpellOverrideService.QueueReapplyAllOnline("EquipItemFromInventorySystem"); } [HarmonyPatch(typeof(EquipmentTransferSystem), "OnUpdate")] [HarmonyPostfix] private static void EquipmentTransferSystemPostfix() { PlayerSpellOverrideService.QueueReapplyAllOnline("EquipmentTransferSystem"); } } [HarmonyPatch(typeof(ReplaceAbilityOnSlotSystem), "OnUpdate")] internal static class ReplaceAbilityOnSlotSystemPatch { [HarmonyPrefix] private static void Prefix(ReplaceAbilityOnSlotSystem __instance) { //IL_0002: 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_0061: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //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_0012: 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_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_0073: 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_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) NativeArray val = default(NativeArray); bool flag = default(bool); try { EntityQuery _query_1482480545_ = __instance.__query_1482480545_0; val = ((EntityQuery)(ref _query_1482480545_)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); Enumerator enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { Entity current = enumerator.Current; try { if (AbilityReplacementInjectionService.TryInjectForBuff(current, out string message) && RuntimeOptimization.DebugLogging) { Plugin.LogInstance.LogInfo((object)message); } } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(55, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Ability replacement injection failed for buff entity "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(current.Index); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } logInstance.LogWarning(val2); } } } catch (Exception ex2) { ManualLogSource logInstance2 = Plugin.LogInstance; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(52, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("ReplaceAbilityOnSlotSystem prefix injection failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex2.Message); } logInstance2.LogWarning(val2); } finally { if (val.IsCreated) { val.Dispose(); } } } [HarmonyPostfix] private static void Postfix() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown try { PlayerSpellOverrideService.ProcessQueuedAfterReplaceAbilitySystem(); } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(45, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Queued spell/weapon cooldown reapply failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } logInstance.LogWarning(val); } } } [HarmonyPatch(typeof(ServerBootstrapSystem), "OnUserConnected")] internal static class ServerBootstrapSystemPatch { [HarmonyPostfix] private static void OnUserConnectedPostfix(ServerBootstrapSystem __instance, NetConnectionId netConnectionId) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //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_0027: 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_0034: 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_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_004e: 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_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_0062: 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_00a1: Unknown result type (might be due to invalid IL or missing references) try { int num = default(int); if (!__instance._NetEndPointToApprovedUserIndex.TryGetValue(netConnectionId, ref num)) { return; } Entity userEntity = ((Il2CppArrayBase)(object)__instance._ApprovedUsersLookup)[num].UserEntity; if (!userEntity.ExistsSafe()) { return; } EntityManager entityManager = Core.EntityManager; if (!((EntityManager)(ref entityManager)).HasComponent(userEntity)) { return; } entityManager = Core.EntityManager; User componentData = ((EntityManager)(ref entityManager)).GetComponentData(userEntity); Entity entityOnServer = ((NetworkedEntity)(ref componentData.LocalCharacter)).GetEntityOnServer(); if (entityOnServer.ExistsSafe()) { if (PlayerSpellOverrideService.TryApplyByPlatformId(componentData.PlatformId, entityOnServer, out string message)) { RuntimeOptimization.Debug("Applied login spell/custom weapon override for " + ((FixedString64Bytes)(ref componentData.CharacterName)).Value + ": " + message); } if (CustomWeaponRuntimeOverrideService.TryApplyForCharacter(entityOnServer, out string message2)) { RuntimeOptimization.Debug("Applied login runtime custom weapon override for " + ((FixedString64Bytes)(ref componentData.CharacterName)).Value + ": " + message2); } } } catch (Exception ex) { ManualLogSource logInstance = Plugin.LogInstance; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(38, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed applying login spell override: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex); } logInstance.LogWarning(val); } } } } namespace HexesAndSanguineSteel.Commands { [CommandGroup("csw", null)] internal static class CustomSpawnWeaponCommands { [Command("wepgive", null, ".csw wepgive ", "Gives the command sender one named custom weapon and binds that exact item instance to the weapon config.", null, true)] public static void WeaponGiveSelf(ChatCommandContext ctx, string weaponName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) string message; if (!PlayerLookup.TryFindOnlinePlayer(ctx.Event.SenderCharacterEntity, out var result)) { ctx.Reply("Could not resolve the command sender as an online player."); } else if (TryGiveInstanceWeapon(result, weaponName, out message)) { ctx.Reply("" + message + ""); } else { ctx.Reply("" + message + ""); } } [Command("upgrade", null, ".csw upgrade ", "Upgrades the command sender's held Shadow Matter weapon into a named custom weapon when the weapon type matches.", null, true)] public static void UpgradeHeldShadowMatter(ChatCommandContext ctx, string weaponName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) string message; if (!PlayerLookup.TryFindOnlinePlayer(ctx.Event.SenderCharacterEntity, out var result)) { ctx.Reply("Could not resolve the command sender as an online player."); } else if (TryUpgradeHeldShadowMatter(result, weaponName, out message)) { ctx.Reply("" + message + ""); } else { ctx.Reply("" + message + ""); } } [Command("options", null, ".csw options", "Lists custom weapon upgrade options that match the command sender's held Shadow Matter weapon type.", null, true)] public static void ListHeldShadowMatterOptions(ChatCommandContext ctx) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!PlayerLookup.TryFindOnlinePlayer(ctx.Event.SenderCharacterEntity, out var result)) { ctx.Reply("Could not resolve the command sender as an online player."); } else { ctx.Reply(DescribeHeldShadowMatterUpgradeOptions(result)); } } [Command("list", null, ".csw list", "Lists enabled custom weapon names from weapons.json.", null, true)] public static void List(ChatCommandContext ctx) { if (CustomWeaponRegistry.CurrentWeapons.Count == 0) { ctx.Reply("No enabled custom weapons are currently loaded. Try .csw reload."); return; } IEnumerable values = CustomWeaponRegistry.CurrentWeapons.Select((CustomWeaponDef w) => w.Name); ctx.Reply("Loaded custom weapons: " + string.Join(", ", values)); } [Command("identify", null, ".csw identify", "Identifies the command sender's currently equipped instance-bound or prefab custom weapon.", null, true)] public static void Identify(ChatCommandContext ctx) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_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) Entity senderCharacterEntity = ctx.Event.SenderCharacterEntity; string message; CustomWeaponDef weapon; string source; if (!senderCharacterEntity.ExistsSafe()) { ctx.Reply("Could not resolve sender character."); } else if (CustomWeaponInstanceStore.TryDescribeHeld(senderCharacterEntity, out message)) { ctx.Reply(message); } else if (CustomWeaponRegistry.TryGetCustomWeaponForCharacter(senderCharacterEntity, out weapon, out source)) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(36, 3); defaultInterpolatedStringHandler.AppendLiteral("Held custom weapon: '"); defaultInterpolatedStringHandler.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler.AppendLiteral("' source:"); defaultInterpolatedStringHandler.AppendFormatted(source); defaultInterpolatedStringHandler.AppendLiteral(" item:"); PrefabGUID itemWeapon = weapon.ItemWeapon; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref itemWeapon)).GuidHash); ctx.Reply(defaultInterpolatedStringHandler.ToStringAndClear()); } else { ctx.Reply(message); } } [Command("instances", null, ".csw instances [filter]", "Lists saved item-instance custom weapon bindings.", null, true)] public static void Instances(ChatCommandContext ctx, string filter = "") { ctx.Reply(CustomWeaponInstanceStore.DescribeInstances(filter)); } [Command("prune", null, ".csw prune", "Removes saved instance bindings whose WeaponName no longer exists in weapons.json.", null, true)] public static void Prune(ChatCommandContext ctx) { int value = CustomWeaponInstanceStore.PruneInvalidWeaponNames(); ctx.Reply($"Pruned {value} stale instance binding(s). This only removes bindings for weapon names no longer present in weapons.json."); } [Command("validate", null, ".csw validate", "Runs carrier conflict and buffer validation.", null, true)] public static void Validate(ChatCommandContext ctx) { ctx.Reply(CustomWeaponValidationService.ValidateCarriers(log: false)); } [Command("spell", null, ".csw spell ", "Sets a weapon-scoped Q/E/Dash/R/C/T ability override with cooldown.", null, true)] public static void SpellSetCd(ChatCommandContext ctx, string playerNameOrSteamId, string slotText, int abilityGroupGuid, float cooldownSeconds) { PlayerLookupResult result; string message; if (!PlayerSpellOverrideService.TryParseSlot(slotText, out var slot)) { ctx.Reply("Invalid slot. Use q, e, dash, r, c, or t."); } else if (!PlayerLookup.TryFindOnlinePlayer(playerNameOrSteamId, out result)) { ctx.Reply("Could not find online player '" + playerNameOrSteamId + "'. Use quotes for names with spaces."); } else if (PlayerSpellOverrideService.TrySetSlotAndCooldown(result, slot, abilityGroupGuid, cooldownSeconds, 0, out message)) { ctx.Reply("" + message + ""); } else { ctx.Reply("" + message + ""); } } [Command("spellclear", null, ".csw spellclear ", "Clears a weapon-scoped spell override.", null, true)] public static void SpellClear(ChatCommandContext ctx, string playerNameOrSteamId, string slotText = "all") { string message; if (!PlayerLookup.TryFindOnlinePlayer(playerNameOrSteamId, out var result)) { ctx.Reply("Could not find online player '" + playerNameOrSteamId + "'."); } else if (PlayerSpellOverrideService.TryClearSlot(result, slotText, out message)) { ctx.Reply("" + message + ""); } else { ctx.Reply("" + message + ""); } } [Command("spellshow", null, ".csw spellshow ", "Shows a player's saved weapon-scoped spell overrides.", null, true)] public static void SpellShow(ChatCommandContext ctx, string playerNameOrSteamId) { if (!PlayerLookup.TryFindOnlinePlayer(playerNameOrSteamId, out var result)) { ctx.Reply("Could not find online player '" + playerNameOrSteamId + "'."); } else { ctx.Reply(PlayerSpellOverrideService.Describe(result)); } } [Command("spellscope", null, ".csw spellscope ", "Shows the player's current weapon scope.", null, true)] public static void SpellScope(ChatCommandContext ctx, string playerNameOrSteamId) { if (!PlayerLookup.TryFindOnlinePlayer(playerNameOrSteamId, out var result)) { ctx.Reply("Could not find online player '" + playerNameOrSteamId + "'."); } else { ctx.Reply(PlayerSpellOverrideService.DescribeCurrentScope(result)); } } [Command("spellapply", null, ".csw spellapply ", "Reapplies saved spell overrides to one online player.", null, true)] public static void SpellApply(ChatCommandContext ctx, string playerNameOrSteamId) { string message; if (!PlayerLookup.TryFindOnlinePlayer(playerNameOrSteamId, out var result)) { ctx.Reply("Could not find online player '" + playerNameOrSteamId + "'."); } else if (PlayerSpellOverrideService.TryApplyForPlayer(result, out message)) { ctx.Reply("" + message + ""); } else { ctx.Reply("" + message + ""); } } [Command("reload", null, ".csw reload", "Reloads weapons.json and reapplies runtime custom weapon systems.", null, true)] public static void ReloadAll(ChatCommandContext ctx) { if (!AdminCommandRateLimiter.TryRun(".csw reload", out string message)) { ctx.Reply(message); return; } RuntimePrefabCache.Clear(); CustomWeaponRegistry.ApplyAll(); int value = CustomWeaponRuntimeOverrideService.ApplyAllOnline(); int value2 = CustomWeaponRuntimeCooldownService.ApplyAllOnline(); ctx.Reply($"Reloaded custom weapon config. Runtime custom weapons applied:{value}, cooldown updates:{value2}. A full restart is still safer for production changes."); } [Command("applyweapons", null, ".csw applyweapons", "Reapplies runtime custom weapon carriers to online players currently holding configured custom weapons.", null, true)] public static void ApplyWeapons(ChatCommandContext ctx) { if (!AdminCommandRateLimiter.TryRun(".csw applyweapons", out string message)) { ctx.Reply(message); return; } int value = CustomWeaponRuntimeOverrideService.ApplyAllOnline(); int value2 = CustomWeaponRuntimeCooldownService.ApplyAllOnline(); ctx.Reply($"Runtime custom weapons applied:{value}, cooldown updates:{value2}."); } [Command("applyspells", null, ".csw applyspells", "Reapplies all online player spell overrides, then reapplies custom weapon priority.", null, true)] public static void ApplySpells(ChatCommandContext ctx) { if (!AdminCommandRateLimiter.TryRun(".csw applyspells", out string message)) { ctx.Reply(message); return; } int value = PlayerSpellOverrideService.ApplyAllOnline(); int value2 = CustomWeaponRuntimeOverrideService.ApplyAllOnline(); ctx.Reply($"Applied spell overrides to {value} online player(s). Runtime custom weapons applied:{value2}."); } [Command("typebuffs", null, ".csw typebuffs", "Lists loaded WeaponTypeBuffs from weapons.json.", null, true)] public static void TypeBuffs(ChatCommandContext ctx) { ctx.Reply(CustomWeaponTypeBuffService.Describe()); } [Command("typebuffscope", null, ".csw typebuffscope", "Shows the command sender's current weapon type and whether it matches WeaponTypeBuffs.", null, true)] public static void TypeBuffScope(ChatCommandContext ctx) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ctx.Reply(CustomWeaponTypeBuffService.DescribeCurrentScope(ctx.Event.SenderCharacterEntity)); } [Command("applytypebuffs", null, ".csw applytypebuffs", "Reapplies runtime custom weapon/stat carriers so WeaponTypeBuffs update for online players.", null, true)] public static void ApplyTypeBuffs(ChatCommandContext ctx) { if (!AdminCommandRateLimiter.TryRun(".csw applytypebuffs", out string message)) { ctx.Reply(message); return; } int value = CustomWeaponTypeBuffService.ApplyAllOnline(forceReconcile: true); ctx.Reply($"Runtime stat carriers force-refreshed for {value} online player(s)."); } [Command("stattypes", null, ".csw stattypes [filter]", "Lists UnitStatType names accepted by weapons.json Stats[].", null, true)] public static void StatTypes(ChatCommandContext ctx, string filter = "") { IEnumerable source = Enum.GetNames(typeof(UnitStatType)); if (!string.IsNullOrWhiteSpace(filter)) { source = source.Where((string n) => n.Contains(filter, StringComparison.OrdinalIgnoreCase)); } string value = string.Join(", ", source.Take(80)); int value2 = source.Count(); if (string.IsNullOrWhiteSpace(value)) { ctx.Reply("No UnitStatType names matched that filter. Useful aliases: AttackSpeed/AS -> PrimaryAttackSpeed, AbilitySpeed/AAS -> AbilityAttackSpeed."); return; } ctx.Reply($"UnitStatTypes ({value2} shown/max 80): {value}\nAliases: AttackSpeed/AS -> PrimaryAttackSpeed, AbilitySpeed/AAS -> AbilityAttackSpeed."); } [Command("modtypes", null, ".csw modtypes", "Lists ModificationType and AttributeCapType names accepted by weapons.json Stats[].", null, true)] public static void ModTypes(ChatCommandContext ctx) { ctx.Reply("ModificationType: " + string.Join(", ", Enum.GetNames(typeof(ModificationType))) + "\nAttributeCapType: " + string.Join(", ", Enum.GetNames(typeof(AttributeCapType)))); } private static string DescribeHeldShadowMatterUpgradeOptions(PlayerLookupResult holder) { //IL_0008: 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_0052: Unknown result type (might be due to invalid IL or missing references) if (!holder.CharacterEntity.ExistsSafe()) { return "Player '" + holder.Name + "' does not have a valid character entity."; } if (!ItemInstanceUtility.TryGetHeldWeaponEntity(holder.CharacterEntity, out var itemEntity)) { return "" + holder.Name + " is not holding a weapon."; } if (!itemEntity.TryRead(out PrefabGUID value) || !((PrefabGUID)(ref value)).HasValue()) { return "Held weapon does not have a valid PrefabGUID."; } int guidHash = ((PrefabGUID)(ref value)).GuidHash; if (!WeaponScopeResolver.IsShadowMatterWeaponPrefab(guidHash)) { return $"Held weapon item:{guidHash} is not a known Shadow Matter weapon. Only Shadow Matter weapons can be upgraded with .csw upgrade."; } if (!WeaponScopeResolver.TryGetWeaponTypeForPrefab(guidHash, out string heldType)) { return $"Could not determine weapon type for held Shadow Matter item:{guidHash}."; } string[] array = (from w in CustomWeaponRegistry.CurrentWeapons.Where(delegate(CustomWeaponDef w) { //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) PrefabGUID itemWeapon = w.ItemWeapon; string weaponType; return WeaponScopeResolver.TryGetWeaponTypeForPrefab(((PrefabGUID)(ref itemWeapon)).GuidHash, out weaponType) && string.Equals(heldType, weaponType, StringComparison.OrdinalIgnoreCase); }) select w.Name).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy((string n) => n, StringComparer.OrdinalIgnoreCase).ToArray(); if (array.Length == 0) { return "Held Shadow Matter weapon type: " + heldType + ".\nNo loaded custom weapons match this weapon type. Check weapons.json and run .csw reload."; } string value2 = string.Join("\n", array.Select((string n) => " - " + n)); return $"Held Shadow Matter weapon type: {heldType}.\nMatching custom weapon upgrade names:\n{value2}\nUse: .csw upgrade \"weapon name\""; } private static bool TryUpgradeHeldShadowMatter(PlayerLookupResult holder, string weaponName, out string message) { //IL_0038: 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_0083: 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_012a: 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_0176: 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_024e: 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) message = string.Empty; if (string.IsNullOrWhiteSpace(weaponName)) { message = "Weapon name cannot be empty."; return false; } if (!CustomWeaponRegistry.TryGetCustomWeaponByName(weaponName, out var weapon)) { message = "No enabled custom weapon named '" + weaponName + "' was found. Use .csw list to see loaded names."; return false; } if (!holder.CharacterEntity.ExistsSafe()) { message = "Player '" + holder.Name + "' does not have a valid character entity."; return false; } if (!ItemInstanceUtility.TryGetHeldWeaponEntity(holder.CharacterEntity, out var itemEntity)) { message = holder.Name + " is not holding a weapon."; return false; } if (!itemEntity.TryRead(out PrefabGUID value) || !((PrefabGUID)(ref value)).HasValue()) { message = "Held weapon does not have a valid PrefabGUID."; return false; } int guidHash = ((PrefabGUID)(ref value)).GuidHash; if (!WeaponScopeResolver.IsShadowMatterWeaponPrefab(guidHash)) { message = $"Held weapon item:{guidHash} is not a known Shadow Matter weapon. Only Shadow Matter weapons can be upgraded this way."; return false; } if (!WeaponScopeResolver.TryGetWeaponTypeForPrefab(guidHash, out string weaponType)) { message = $"Could not determine weapon type for held Shadow Matter item:{guidHash}."; return false; } PrefabGUID itemWeapon = weapon.ItemWeapon; if (!WeaponScopeResolver.TryGetWeaponTypeForPrefab(((PrefabGUID)(ref itemWeapon)).GuidHash, out string weaponType2)) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(59, 2); defaultInterpolatedStringHandler.AppendLiteral("Could not determine weapon type for custom weapon '"); defaultInterpolatedStringHandler.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler.AppendLiteral("' item:"); itemWeapon = weapon.ItemWeapon; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref itemWeapon)).GuidHash); defaultInterpolatedStringHandler.AppendLiteral("."); message = defaultInterpolatedStringHandler.ToStringAndClear(); return false; } if (!string.Equals(weaponType, weaponType2, StringComparison.OrdinalIgnoreCase)) { message = $"Type mismatch. Held Shadow Matter weapon is '{weaponType}', but custom weapon '{weapon.Name}' is '{weaponType2}'."; return false; } if (ItemInstanceUtility.GetOrCreateSequenceGuid(itemEntity) == 0) { message = "Held weapon matched, but the mod could not assign/read a SequenceGUID before consuming upgrade cost."; return false; } IReadOnlyList costs = BuildEffectiveUpgradeCost(weapon); string message2 = string.Empty; if (!InventoryCostUtility.TryConsumeUpgradeCost(holder, costs, out message2)) { message = "Held weapon matched type '" + weaponType + "', but upgrade cost failed: " + message2; return false; } if (!CustomWeaponInstanceStore.TryBindHeldItem(itemEntity, weapon, holder, out string message3)) { message = "Held weapon matched type '" + weaponType + "' and cost was consumed, but instance binding failed: " + message3; return false; } RuntimeStateCache.Clear(holder.CharacterEntity); CustomWeaponRuntimeOverrideService.TryApplyForPlayer(holder, out string message4); CustomWeaponRuntimeOverrideService.QueueRuntimeRefresh("Shadow Matter upgrade " + weapon.Name); string value2 = (string.IsNullOrWhiteSpace(message2) ? string.Empty : (" " + message2)); message = $"Upgraded held Shadow Matter {weaponType} into '{weapon.Name}'.{value2} {message3} {message4}"; return true; } private static IReadOnlyList BuildEffectiveUpgradeCost(CustomWeaponDef weapon) { return CustomWeaponConfig.GlobalUpgradeCost; } private static bool TryGiveInstanceWeapon(PlayerLookupResult receiver, string weaponName, out string message) { //IL_0038: 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_008e: 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_0097: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_012d: 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_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_0150: Unknown result type (might be due to invalid IL or missing references) message = string.Empty; if (string.IsNullOrWhiteSpace(weaponName)) { message = "Weapon name cannot be empty."; return false; } if (!CustomWeaponRegistry.TryGetCustomWeaponByName(weaponName, out var weapon)) { message = "No enabled custom weapon named '" + weaponName + "' was found. Use .csw list to see loaded names."; return false; } if (!receiver.CharacterEntity.ExistsSafe()) { message = "Player '" + receiver.Name + "' does not have a valid character entity."; return false; } Entity val = default(Entity); if (!InventoryUtilities.TryGetInventoryEntity(Core.EntityManager, receiver.CharacterEntity, ref val, 0)) { message = "Could not resolve inventory entity for '" + receiver.Name + "'."; return false; } ServerGameManager serverGameManager = Core.ServerGameManager; AddItemResponse val2 = ((ServerGameManager)(ref serverGameManager)).TryAddInventoryItem(val, weapon.ItemWeapon, 1); if (!((AddItemResponse)(ref val2)).Success) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(51, 3); defaultInterpolatedStringHandler.AppendLiteral("Failed to give '"); defaultInterpolatedStringHandler.AppendFormatted(weapon.Name); defaultInterpolatedStringHandler.AppendLiteral("' item:"); PrefabGUID itemWeapon = weapon.ItemWeapon; defaultInterpolatedStringHandler.AppendFormatted(((PrefabGUID)(ref itemWeapon)).GuidHash); defaultInterpolatedStringHandler.AppendLiteral(" to "); defaultInterpolatedStringHandler.AppendFormatted(receiver.Name); defaultInterpolatedStringHandler.AppendLiteral(". Inventory may be full."); message = defaultInterpolatedStringHandler.ToStringAndClear(); return false; } Entity newEntity = val2.NewEntity; if (!newEntity.ExistsSafe()) { message = "The game reported success giving '" + weapon.Name + "', but no new item entity was returned."; return false; } if (!CustomWeaponInstanceStore.TryBindGeneratedItem(newEntity, weapon, receiver, out string message2)) { message = $"Gave '{weapon.Name}' to {receiver.Name}, but failed to bind instance: {message2}"; return false; } message = $"Gave '{weapon.Name}' to {receiver.Name}. {message2} This custom weapon follows that physical item if it is dropped/traded."; return true; } } }