Decompiled source of HexesAndSanguineSteel v1.0.3
HexesAndSanguineSteel.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
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<Exception>(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<CustomWeaponDef> _currentDefinitions = Array.Empty<CustomWeaponDef>(); private static IReadOnlyList<WeaponTypeBuffDef> _currentTypeBuffDefinitions = Array.Empty<WeaponTypeBuffDef>(); private static IReadOnlyList<CustomWeaponCostDef> _globalUpgradeCost = Array.Empty<CustomWeaponCostDef>(); 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<WeaponTypeBuffDef> WeaponTypeBuffs => _currentTypeBuffDefinitions; internal static IReadOnlyList<CustomWeaponCostDef> 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<string>(ConfigPath); } logInstance.LogInfo(val); } } internal static IReadOnlyList<CustomWeaponDef> 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<string>(ConfigPath); } logInstance.LogInfo(val); return _currentDefinitions; } try { WeaponConfigFile weaponConfigFile = JsonSerializer.Deserialize<WeaponConfigFile>(File.ReadAllText(ConfigPath), JsonOptions); if (weaponConfigFile == null) { weaponConfigFile = WeaponConfigFile.CreateDefault(); Save(weaponConfigFile); } WeaponConfigFile weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.Weapons == null) { List<WeaponConfigEntry> list = (weaponConfigFile2.Weapons = new List<WeaponConfigEntry>()); } weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.WeaponTypeBuffs == null) { List<WeaponTypeBuffConfigEntry> list3 = (weaponConfigFile2.WeaponTypeBuffs = new List<WeaponTypeBuffConfigEntry>()); } weaponConfigFile2 = weaponConfigFile; if (weaponConfigFile2.GlobalUpgradeCost == null) { List<WeaponUpgradeCostConfigEntry> list5 = (weaponConfigFile2.GlobalUpgradeCost = new List<WeaponUpgradeCostConfigEntry>()); } 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<WeaponTypeBuffConfigEntry> list3 = (weaponConfigFile2.WeaponTypeBuffs = new List<WeaponTypeBuffConfigEntry>()); } 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<WeaponUpgradeCostConfigEntry> list5 = (weaponConfigFile2.GlobalUpgradeCost = new List<WeaponUpgradeCostConfigEntry>()); } 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<WeaponUpgradeCostConfigEntry> list5 = (weaponConfigFile2.GlobalUpgradeCost = new List<WeaponUpgradeCostConfigEntry>()); } 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<WeaponStatConfigEntry> list10 = (weaponConfigEntry.Stats = new List<WeaponStatConfigEntry>()); } weaponConfigEntry = weapon; if (weaponConfigEntry.OnHitEffects == null) { List<WeaponOnHitEffectConfigEntry> list12 = (weaponConfigEntry.OnHitEffects = new List<WeaponOnHitEffectConfigEntry>()); } 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<string>(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<string>(text); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' and wrote defaults. Error: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(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<string>(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<WeaponUpgradeCostConfigEntry> GlobalUpgradeCost { get; set; } = new List<WeaponUpgradeCostConfigEntry>(); public List<WeaponConfigEntry> Weapons { get; set; } = new List<WeaponConfigEntry>(); public List<WeaponTypeBuffConfigEntry> WeaponTypeBuffs { get; set; } = new List<WeaponTypeBuffConfigEntry>(); public static WeaponConfigFile CreateDefault() { return new WeaponConfigFile { ConfigVersion = 16, DefaultCustomWeaponCarrierBuff = -1721561549, DefaultCustomWeaponStatCarrierBuff = -1122472005, GlobalUpgradeCost = new List<WeaponUpgradeCostConfigEntry>(), WeaponTypeBuffs = new List<WeaponTypeBuffConfigEntry>(1) { new WeaponTypeBuffConfigEntry { Enabled = false, WeaponType = "Mace", ApplyToCustomWeapons = true, Stats = new List<WeaponStatConfigEntry>(1) { new WeaponStatConfigEntry { StatType = "AttackSpeed", ModificationType = "AddToBase", AttributeCapType = "SoftCapped", Value = 0.1f } } } }, Weapons = new List<WeaponConfigEntry>(1) { new WeaponConfigEntry { Enabled = true, Name = "Crimson Thorns", ItemWeapon = 1307774440, EquipBuff = 673013659, WeaponLevel = 100f, PhysicalPower = 0f, SpellPower = 0f, Stats = new List<WeaponStatConfigEntry>(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<WeaponOnHitEffectConfigEntry>(), 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<CustomWeaponDef> ToDefinitions() { List<CustomWeaponDef> list = new List<CustomWeaponDef>(); foreach (WeaponConfigEntry weapon in Weapons) { if (weapon.Enabled) { list.Add(weapon.ToDefinition(DefaultCustomWeaponCarrierBuff, DefaultCustomWeaponStatCarrierBuff)); } } return list; } public IReadOnlyList<CustomWeaponCostDef> ToGlobalUpgradeCost() { if (GlobalUpgradeCost == null) { List<WeaponUpgradeCostConfigEntry> list = (GlobalUpgradeCost = new List<WeaponUpgradeCostConfigEntry>()); } return WeaponConfigEntry.BuildUpgradeCost("GlobalUpgradeCost", GlobalUpgradeCost); } public IReadOnlyList<WeaponTypeBuffDef> ToWeaponTypeBuffDefinitions() { List<WeaponTypeBuffDef> list = new List<WeaponTypeBuffDef>(); foreach (WeaponTypeBuffConfigEntry weaponTypeBuff in WeaponTypeBuffs) { if (weaponTypeBuff.Enabled) { WeaponTypeBuffConfigEntry weaponTypeBuffConfigEntry = weaponTypeBuff; if (weaponTypeBuffConfigEntry.Stats == null) { List<WeaponStatConfigEntry> list2 = (weaponTypeBuffConfigEntry.Stats = new List<WeaponStatConfigEntry>()); } 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<WeaponStatConfigEntry> Stats { get; set; } = new List<WeaponStatConfigEntry>(); public List<WeaponOnHitEffectConfigEntry> OnHitEffects { get; set; } = new List<WeaponOnHitEffectConfigEntry>(); [JsonIgnore] public List<WeaponUpgradeCostConfigEntry> UpgradeCost { get; set; } = new List<WeaponUpgradeCostConfigEntry>(); 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<CustomWeaponCostDef>(), 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<CustomWeaponStatDef> BuildStats(string weaponName, List<WeaponStatConfigEntry> 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<CustomWeaponStatDef> list = new List<CustomWeaponStatDef>(); foreach (WeaponStatConfigEntry stat in stats) { ModificationType result2; AttributeCapType result3; if (!Enum.TryParse<UnitStatType>(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<ModificationType>(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<AttributeCapType>(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<CustomWeaponOnHitEffectDef> BuildOnHitEffects(string weaponName, List<WeaponOnHitEffectConfigEntry> effects) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) List<CustomWeaponOnHitEffectDef> list = new List<CustomWeaponOnHitEffectDef>(); if (effects == null) { effects = new List<WeaponOnHitEffectConfigEntry>(); } 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<CustomWeaponCostDef> BuildUpgradeCost(string weaponName, List<WeaponUpgradeCostConfigEntry> 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<CustomWeaponCostDef> list = new List<CustomWeaponCostDef>(); if (costs == null) { costs = new List<WeaponUpgradeCostConfigEntry>(); } 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<string>(weaponName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": upgrade cost '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(cost.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' has non-positive Amount "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(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<string>(weaponName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": upgrade cost '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(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<WeaponStatConfigEntry> Stats { get; set; } = new List<WeaponStatConfigEntry>(); } internal static class StatConfigBuilder { private static readonly Dictionary<string, string> UnitStatAliases = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["AS"] = "PrimaryAttackSpeed", ["AttackSpeed"] = "PrimaryAttackSpeed", ["PrimaryAttackSpeed"] = "PrimaryAttackSpeed", ["AAS"] = "AbilityAttackSpeed", ["AbilitySpeed"] = "AbilityAttackSpeed", ["AbilityAttackSpeed"] = "AbilityAttackSpeed", ["MS"] = "MovementSpeed", ["MoveSpeed"] = "MovementSpeed", ["MovementSpeed"] = "MovementSpeed" }; private static readonly Dictionary<string, string> AttributeCapAliases = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["UnCapped"] = "Uncapped", ["Uncapped"] = "Uncapped", ["NoCap"] = "Uncapped", ["NoCaps"] = "Uncapped", ["IgnoreCap"] = "Uncapped", ["IgnoreCaps"] = "Uncapped", ["None"] = "Uncapped" }; internal static IReadOnlyList<CustomWeaponStatDef> BuildStats(string ownerName, List<WeaponStatConfigEntry> 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<CustomWeaponStatDef> list = new List<CustomWeaponStatDef>(); 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<ModificationType>(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<UnitStatType>(resolvedName, ignoreCase: true, out value)) { return true; } if (UnitStatAliases.TryGetValue(resolvedName, out string value2) && Enum.TryParse<UnitStatType>(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<AttributeCapType>(resolvedName, ignoreCase: true, out value)) { return true; } if (AttributeCapAliases.TryGetValue(resolvedName, out string value2) && Enum.TryParse<AttributeCapType>(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<string, PlayerSpellOverrideEntry> Players { get; set; } = new Dictionary<string, PlayerSpellOverrideEntry>(); } 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<string, PlayerSpellScopeEntry> WeaponScopes { get; set; } = new Dictionary<string, 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; } } 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<string>(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<string>(ConfigPath); } logInstance.LogInfo(val); return _cache; } try { _cache = JsonSerializer.Deserialize<PlayerSpellOverrideFile>(File.ReadAllText(ConfigPath), JsonOptions) ?? new PlayerSpellOverrideFile(); PlayerSpellOverrideFile cache = _cache; if (cache.Players == null) { Dictionary<string, PlayerSpellOverrideEntry> dictionary = (cache.Players = new Dictionary<string, PlayerSpellOverrideEntry>()); } foreach (PlayerSpellOverrideEntry value in _cache.Players.Values) { if (value.WeaponScopes == null) { Dictionary<string, PlayerSpellScopeEntry> dictionary3 = (value.WeaponScopes = new Dictionary<string, PlayerSpellScopeEntry>()); } } 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<int>(673013659); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" because it conflicts with the default custom spear equip buff. New default carrier: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(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<string>(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<Exception>(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<string>(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<ServerScriptMapper>().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<CustomWeaponStatDef> 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<CustomWeaponCostDef> UpgradeCost, WeaponPowerDef Power, IReadOnlyList<CustomWeaponStatDef> Stats, IReadOnlyList<CustomWeaponOnHitEffectDef> OnHitEffects, AbilitySlotDef Attack, AbilitySlotDef Primary, AbilitySlotDef Secondary, AbilitySlotDef Dash, AbilitySlotDef Ultimate, AbilitySlotDef SpellSlot1, AbilitySlotDef SpellSlot2); internal static class CustomWeaponRegistry { private static readonly Dictionary<int, CustomWeaponDef> _customWeaponsByItem = new Dictionary<int, CustomWeaponDef>(); private static readonly Dictionary<int, string> _customWeaponNamesByItem = new Dictionary<int, string>(); private static readonly Dictionary<string, CustomWeaponDef> _customWeaponsByName = new Dictionary<string, CustomWeaponDef>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<int> _reservedRuntimeCarrierBuffs = new HashSet<int>(); private static readonly HashSet<int> _reservedRuntimeStatCarrierBuffs = new HashSet<int>(); internal static IReadOnlyList<CustomWeaponDef> CurrentWeapons { get; private set; } = Array.Empty<CustomWeaponDef>(); internal static IReadOnlyCollection<int> ReservedRuntimeCarrierBuffs => _reservedRuntimeCarrierBuffs; internal static IReadOnlyCollection<int> 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<CustomWeaponDef> readOnlyList = (CurrentWeapons = CustomWeaponConfig.LoadOrCreate()); _customWeaponsByItem.Clear(); _customWeaponNamesByItem.Clear(); _customWeaponsByName.Clear(); _reservedRuntimeCarrierBuffs.Clear(); _reservedRuntimeStatCarrierBuffs.Clear(); Dictionary<int, int> 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<int, CustomWeaponDef> g) => g.Key, (IGrouping<int, CustomWeaponDef> 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<int, CustomWeaponDef> customWeaponsByItem = _customWeaponsByItem; val = item.ItemWeapon; customWeaponsByItem[((PrefabGUID)(ref val)).GuidHash] = item; Dictionary<int, string> 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<int> reservedRuntimeCarrierBuffs = _reservedRuntimeCarrierBuffs; val = item.CarrierBuff; reservedRuntimeCarrierBuffs.Add(((PrefabGUID)(ref val)).GuidHash); } val = item.StatCarrierBuff; if (((PrefabGUID)(ref val)).HasValue()) { HashSet<int> 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<string>(item2.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("': "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(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<WeaponLevelSource>((EntityExtensions.WithRefHandler<WeaponLevelSource>)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<ReplaceAbilityOnSlotBuff>(out DynamicBuffer<ReplaceAbilityOnSlotBuff> _)) { 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<ModifyUnitStatBuff_DOTS>(out DynamicBuffer<ModifyUnitStatBuff_DOTS> _)) { 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<string>("Hexes and Sanguine Steel"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("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<DestroyTag>()) { return false; } if (!buffEntity.TryGetBuffer<ReplaceAbilityOnSlotBuff>(out DynamicBuffer<ReplaceAbilityOnSlotBuff> buffer)) { return false; } if (!buffEntity.TryRead<EntityOwner>(out EntityOwner value) || !value.Owner.ExistsSafe() || value.Owner.Has<DestroyTag>()) { return false; } Entity owner = value.Owner; if (!owner.Has<PlayerCharacter>()) { 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<string, PlayerSpellScopeEntry> dictionary = (playerSpellOverrideEntry.WeaponScopes = new Dictionary<string, PlayerSpellScopeEntry>()); } 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<PrefabGUID>(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 "<destroyed>"; } if (buffEntity.TryRead<PrefabGUID>(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<ReplaceAbilityOnSlotBuff> 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<ReplaceAbilityOnSlotBuff> 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<ReplaceAbilityOnSlotBuff> 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<ReplaceAbilityOnSlotBuff> 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<Entity> val = default(NativeArray<Entity>); NativeArray<DamageTakenEvent> val2 = default(NativeArray<DamageTakenEvent>); try { EntityQuery damageTakenEventQuery = __instance._DamageTakenEventQuery; val = ((EntityQuery)(ref damageTakenEventQuery)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); damageTakenEventQuery = __instance._DamageTakenEventQuery; val2 = ((EntityQuery)(ref damageTakenEventQuery)).ToComponentDataArray<DamageTakenEvent>(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<Health>()) { continue; } Entity val4 = ResolveOwner(val3.Source); if (!val4.ExistsSafe() || !val4.Has<PlayerCharacter>() || !CustomWeaponRegistry.TryGetCustomWeaponForCharacter(val4, out CustomWeaponDef weapon, out string _) || weapon.OnHitEffects.Count == 0) { continue; } bool flag = entity.Has<PlayerCharacter>(); 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<Exception>(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<PlayerCharacter>()) { return source; } if (source.TryRead<EntityOwner>(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 = WeaponScopeReso