using System; using System.Collections; 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 CustomGameplayModifiers; using CustomGameplayModifiers.Artifacts; using CustomGameplayModifiers.CustomAddressables; using CustomGameplayModifiers.Framework; using CustomGameplayModifiers.Framework.EventType; using CustomGameplayModifiers.Framework.Observers; using CustomGameplayModifiers.ItemModules; using HarmonyLib; using Il2Cpp; using Il2CppAI; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppKeepsake; using Il2CppKeepsake.CharacterCustomization; using Il2CppKeepsake.Common.Collision; using Il2CppKeepsake.Common.DependencyManagement; using Il2CppKeepsake.Common.Unity; using Il2CppKeepsake.GeneratedItems.Cosmetics; using Il2CppKeepsake.HyperSpace.GameplayFeatures.AI.OnFoot; using Il2CppKeepsake.HyperSpace.Online.Steam; using Il2CppKeepsake.HyperSpace.System.Modifiers.ItemModule; using Il2CppKeepsake.InteriorObjects.Vendor; using Il2CppKeepsake.MetaProgression; using Il2CppKeepsake.Modifiers; using Il2CppKeepsake.Modifiers.Traits; using Il2CppKeepsake.Pickupables.GenericWeapon; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Collections.ObjectModel; using Il2CppSystem.Threading; using Il2CppTMPro; using Il2CppUniRx; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.Localization; using UnityEngine.Localization.Tables; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.UI; using UnityEngine.VFX; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Core), "CustomGameplayModifiers", "1.0.0", "domipiggie", null)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("CustomGameplayModifiers")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+1a0d9b156f1d4c25b42db65fb214e60af360908f")] [assembly: AssemblyProduct("CustomGameplayModifiers")] [assembly: AssemblyTitle("CustomGameplayModifiers")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] 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; } } } namespace CustomGameplayModifiers { public class Core : MelonMod { public override void OnInitializeMelon() { ItemAssetRegistry.Initialize(); ModLogger.Initialize(); MelonCoroutines.Start(LocalizationInjector.FindTableRoutine()); MelonCoroutines.Start(RegisterAddressablesRoutine()); ModLogger.Msg("Initialized."); } public override void OnLateInitializeMelon() { MelonCoroutines.Start(InitRoutine()); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { SceneEventsService.OnSceneLoaded(buildIndex, sceneName); } private IEnumerator InitRoutine() { yield return ArtifactMeshCache.LoadRoutine(); while (PersistentScriptableLibrary.m_ModuleSchoolAssets == null) { yield return (object)new WaitForSeconds(0.2f); } ModLogger.Msg("PersistentScriptableLibrary ready — initializing caches and building modifiers."); yield return BuildPipeline.Run(); } private IEnumerator RegisterAddressablesRoutine() { WaitForSeconds wait = new WaitForSeconds(0.1f); while (Addressables.ResourceManager == null) { yield return wait; } CustomAddressablesRegisterer.TryRegister(); } } } namespace CustomGameplayModifiers.PlayerTraits { public abstract class CustomPlayerTrait : CustomModifier { public override void ConfigureScriptable(PlayerTraitScriptable scriptable) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) base.ConfigureScriptable(scriptable); scriptable.m_CurrentBranch = KeepsakeSteamManager.SteamBlackboardData.m_Branch.Value; } } public abstract class PlayerTraitInstance : ModifierInstance { public PlayerTrait LiveTrait => (PlayerTrait)base.LiveModifier; public PlayerTraitScriptable TraitScriptable => (PlayerTraitScriptable)base.Scriptable; } } namespace CustomGameplayModifiers.Patches { [HarmonyPatch(typeof(OnFootDamageHandler), "OnReceivedDamage")] internal static class Patch_OnFootDamageHandler_OnReceivedDamage { private static void Postfix(OnFootDamageHandler __instance, ReceivedDamage receivedDamage) { if (__instance.m_DamageComponent.m_HealthComponent.IsDead) { GameEventBus.Publish(new OnFootKilledEvent(__instance.m_Controller, receivedDamage)); } } } [HarmonyPatch(typeof(FlyingDroneDamageHandler), "OnReceivedDamage")] internal static class Patch_FlyingDroneDamageHandler_OnReceivedDamage { private static void Postfix(FlyingDroneDamageHandler __instance, ReceivedDamage receivedDamage) { if (__instance.m_DamageComponent.m_HealthComponent.IsDead) { GameEventBus.Publish(new OnFootKilledEvent((AI_Controller_OnFoot)(object)__instance.m_Controller, receivedDamage)); } } } [HarmonyPatch(typeof(PickupableItemFirstPerson_GenericWeapon), "OnReload")] internal static class Patch_PickupableItemFirstPerson_OnReload { private static void Prefix(PickupableItemFirstPerson_GenericWeapon __instance) { GameEventBus.Publish(new WeaponReloadedEvent(__instance)); } } [HarmonyPatch(typeof(PickupableItemFirstPerson_GenericWeapon), "Shoot")] internal static class Patch_DoShootAsync { private static void Postfix(PickupableItemFirstPerson_GenericWeapon __instance) { GameEventBus.Publish(new WeaponFiredEvent(__instance)); } } [HarmonyPatch(typeof(PlayerPickupableItemHandler), "Handle_ItemHeldPersistentChanged")] internal static class Patch_PlayerPickupableItemHandler { private static void Postfix(PlayerPickupableItemHandler __instance, PersistentPickupable persistentItem) { HeldItemTracker.OnItemHeldChanged(__instance.m_PlayerController, persistentItem); } } [HarmonyPatch(typeof(PlayerShip_IndividualTurretController), "Fire")] internal static class Patch_TurretController { private static void Postfix(SpaceShip_Cannon_Base cannon, VisualEffectAsset muzzleFlashFx, bool isFiredByBuddyBot) { GameEventBus.Publish(new ShipCannonFiredEvent(cannon, muzzleFlashFx, isFiredByBuddyBot)); } } [HarmonyPatch(typeof(ItemModule), "InitializeForPreview")] internal static class Patch_ItemModule { private static void Postfix(ItemModule __instance) { ICustomModifier definition = ModifierRegistry.GetDefinition(((GameplayModifier)__instance).m_Template.AssetGUID); if (definition != null && definition.CreateInstance() is ItemModuleInstance itemModuleInstance) { itemModuleInstance.Scriptable = ((GameplayModifier)__instance).m_Template; itemModuleInstance.LiveModifier = (GameplayModifier)(object)__instance; itemModuleInstance.IsPreview = true; itemModuleInstance.OnPreviewActivated(); } } } [HarmonyPatch(typeof(AI_Capability_Ship_Health), "DamageRecieved")] internal static class Patch_AIShipDamageRecieved { private static void Postfix(AI_Capability_Ship_Health __instance, ReceivedDamage receivedDamage) { GameEventBus.Publish(new AIShipDamagedEvent(__instance, receivedDamage)); } } [HarmonyPatch(typeof(GameplayModifierManager))] internal static class GameplayModifierManagerPatches { private static readonly List _subs = new List(); private static readonly List _observerCleanup = new List(); [HarmonyPostfix] [HarmonyPatch("Awake")] public static void Awake(GameplayModifierManager __instance) { foreach (IDisposable sub in _subs) { if (sub != null) { sub.Dispose(); } } _subs.Clear(); foreach (Action item7 in _observerCleanup) { item7?.Invoke(); } _observerCleanup.Clear(); foreach (KeyValuePair item8 in ModifierRegistry.All) { item8.Deconstruct(out var key, out var _); string guid = key; GameplayModifierScriptable val = ((Il2CppObjectBase)CustomAssetRegistry.GetModule(guid)).TryCast(); if (!((Object)(object)val == (Object)null)) { ModifierInjector.InjectIntoManager(val); } } ItemModuleAddObserver itemModuleAddObserver = new ItemModuleAddObserver(); _observerCleanup.Add(delegate { itemModuleAddObserver.OnNextAction = null; }); itemModuleAddObserver.OnNextAction = delegate(CollectionAddEvent addEvent) { MelonCoroutines.Start(Link(addEvent, "ItemModule")); }; IDisposable item = __instance.m_BlackboardData.m_ActiveItemModules.ObserveAdd().Subscribe(new IObserver>(((Il2CppObjectBase)itemModuleAddObserver).Pointer)); _subs.Add(item); ItemModuleRemoveObserver itemModuleRemoveObserver = new ItemModuleRemoveObserver(); _observerCleanup.Add(delegate { itemModuleRemoveObserver.OnNextAction = null; }); itemModuleRemoveObserver.OnNextAction = delegate(CollectionRemoveEvent removeEvent) { MelonCoroutines.Start(Unlink(removeEvent)); }; IDisposable item2 = __instance.m_BlackboardData.m_ActiveItemModules.ObserveRemove().Subscribe(new IObserver>(((Il2CppObjectBase)itemModuleRemoveObserver).Pointer)); _subs.Add(item2); ArtifactAddObserver artifactAddObserver = new ArtifactAddObserver(); _observerCleanup.Add(delegate { artifactAddObserver.OnNextAction = null; }); artifactAddObserver.OnNextAction = delegate(CollectionAddEvent addEvent) { MelonCoroutines.Start(Link(addEvent, "Artifact")); }; IDisposable item3 = __instance.m_BlackboardData.m_ActiveArtifacts.ObserveAdd().Subscribe(new IObserver>(((Il2CppObjectBase)artifactAddObserver).Pointer)); _subs.Add(item3); ArtifactRemoveObserver artifactRemoveObserver = new ArtifactRemoveObserver(); _observerCleanup.Add(delegate { artifactRemoveObserver.OnNextAction = null; }); artifactRemoveObserver.OnNextAction = delegate(CollectionRemoveEvent removeEvent) { MelonCoroutines.Start(Unlink(removeEvent)); }; IDisposable item4 = __instance.m_BlackboardData.m_ActiveArtifacts.ObserveRemove().Subscribe(new IObserver>(((Il2CppObjectBase)artifactRemoveObserver).Pointer)); _subs.Add(item4); PlayerTraitAddObserver playerTraitAddObserver = new PlayerTraitAddObserver(); _observerCleanup.Add(delegate { playerTraitAddObserver.OnNextAction = null; }); playerTraitAddObserver.OnNextAction = delegate(CollectionAddEvent addEvent) { MelonCoroutines.Start(Link(addEvent, "PlayerTrait")); }; IDisposable item5 = __instance.m_BlackboardData.m_ActiveLocalPlayerTraits.ObserveAdd().Subscribe(new IObserver>(((Il2CppObjectBase)playerTraitAddObserver).Pointer)); _subs.Add(item5); PlayerTraitRemoveObserver playerTraitRemoveObserver = new PlayerTraitRemoveObserver(); _observerCleanup.Add(delegate { playerTraitRemoveObserver.OnNextAction = null; }); playerTraitRemoveObserver.OnNextAction = delegate(CollectionRemoveEvent removeEvent) { MelonCoroutines.Start(Unlink(removeEvent)); }; IDisposable item6 = __instance.m_BlackboardData.m_ActiveLocalPlayerTraits.ObserveRemove().Subscribe(new IObserver>(((Il2CppObjectBase)playerTraitRemoveObserver).Pointer)); _subs.Add(item6); } private static IEnumerator Link(CollectionAddEvent? addEvent, string typeName) where T : GameplayModifier { yield return (object)new WaitUntil(Func.op_Implicit((Func)delegate { CollectionAddEvent? obj = addEvent; object obj2; if (obj == null) { obj2 = null; } else { object obj3 = obj.Value; if (obj3 == null) { obj2 = null; } else { GameplayModifierScriptable template = ((GameplayModifier)obj3).m_Template; obj2 = ((template != null) ? template.AssetGUID : null); } } return obj2 != null; })); if (ModifierRegistry.IsCustom(((GameplayModifier)addEvent.Value).m_Template.AssetGUID)) { GameplayModifier module = (GameplayModifier)(object)addEvent.Value; ModifierRegistry.NotifyActivated(module.m_Template.AssetGUID, ((Il2CppObjectBase)module).Pointer, module.m_Template, module, () => ModifierRegistry.GetDefinition(module.m_Template.AssetGUID).CreateInstance()); Melon.Logger.Msg("[Patch] " + typeName + " activated: " + module.m_Template.AssetGUID); } } private static IEnumerator Unlink(CollectionRemoveEvent? removeEvent) where T : GameplayModifier { yield return (object)new WaitUntil(Func.op_Implicit((Func)delegate { CollectionRemoveEvent? obj = removeEvent; object obj2; if (obj == null) { obj2 = null; } else { object obj3 = obj.Value; if (obj3 == null) { obj2 = null; } else { GameplayModifierScriptable template = ((GameplayModifier)obj3).m_Template; obj2 = ((template != null) ? template.AssetGUID : null); } } return obj2 != null; })); if (ModifierRegistry.IsCustom(((GameplayModifier)removeEvent.Value).m_Template.AssetGUID)) { GameplayModifier module = (GameplayModifier)(object)removeEvent.Value; ModifierRegistry.NotifyRemoved(module.m_Template.m_AssetGUID, ((Il2CppObjectBase)module).Pointer); } } } [HarmonyPatch(typeof(GUI_LoadoutTab))] internal static class GUI_LoadoutTabPatches { [HarmonyPostfix] [HarmonyPatch("SafeStart")] public static void SafeStart(GUI_LoadoutTab __instance) { foreach (KeyValuePair item in ModifierRegistry.All) { item.Deconstruct(out var key, out var _); string guid = key; PlayerTraitScriptable val = ((Il2CppObjectBase)CustomAssetRegistry.GetModule(guid)).TryCast(); if (!((Object)(object)val == (Object)null)) { LoadoutGUIInjector.InjectIntoLoadoutGUI(__instance, val); } } } } } namespace CustomGameplayModifiers.ItemModules { public abstract class CustomItemModule : CustomModifier { public abstract IReadOnlyList SchoolGuids { get; } public override void ConfigureScriptable(ItemModuleScriptable scriptable) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) base.ConfigureScriptable(scriptable); scriptable.m_CurrentBranch = KeepsakeSteamManager.SteamBlackboardData.m_Branch.Value; scriptable.m_AllowedItems = new List(); scriptable.m_ForbiddenItems = new List(); scriptable.m_LinkedStatusEffects = new List(); scriptable.m_TweakableValues_Common = new List(); scriptable.m_TweakableValues_Epic = new List(); scriptable.m_TweakableValues_Legendary = new List(); scriptable.m_TweakableValues_Rare = new List(); } } public abstract class ItemModuleInstance : ModifierInstance { public ItemModule LiveModule => (ItemModule)base.LiveModifier; public ItemModuleScriptable ModuleScriptable => (ItemModuleScriptable)base.Scriptable; public PersistentPickupable Item => LiveModule.Item; public PlayerController LocalPlayer => PlayerHandler.GetPlayerHandler.localPlayerController; public bool IsHeldByLocalPlayer => (Object)(object)LocalPlayer != (Object)null && LocalPlayer.Inventory.m_ItemHeldPersistentObject.HasValue && (Object)(object)LocalPlayer.Inventory.m_ItemHeldPersistentObject.Value == (Object)(object)Item; public bool IsPreview { get; internal set; } public float GetTweakable(int index) { return ((GameplayModifier)LiveModule).TweakableGetter(index); } public virtual void OnPreviewActivated() { ((GameplayModifier)LiveModule).GetStatModificationAdd = Func.op_Implicit(StatModificationAdd); } } } namespace CustomGameplayModifiers.Framework { public abstract class CustomItemModuleSchool { public abstract string Guid { get; } public abstract void ConfigureSchool(ItemModuleSchool school); internal ItemModuleSchool CreateSchool() { ItemModuleSchool val = ScriptableObject.CreateInstance(); val.m_AssetGUID = Guid; ConfigureSchool(val); return val; } } public abstract class CustomModifier : ICustomModifier where TScriptable : GameplayModifierScriptable where TInstance : ModifierInstance { public abstract string Guid { get; } public abstract string Name { get; } public abstract string Description { get; } public virtual void ConfigureScriptable(TScriptable scriptable) { //IL_001a: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown ((GameplayModifierScriptable)scriptable).m_Curves = new List(); ((GameplayModifierScriptable)scriptable).m_DependencyHandle = default(Handle); ((GameplayModifierScriptable)scriptable).m_Effects = new List(); ((GameplayModifierScriptable)scriptable).m_TweakableValues = new List(); ((GameplayModifierScriptable)scriptable).m_LocalizedName = new LocalizedString { TableReference = TableReference.op_Implicit("STC_Main"), TableEntryReference = TableEntryReference.op_Implicit(Guid + "-NAME") }; ((GameplayModifierScriptable)scriptable).m_Description = new LocalizedString { TableReference = TableReference.op_Implicit("STC_Main"), TableEntryReference = TableEntryReference.op_Implicit(Guid + "-DESC") }; } public abstract TInstance CreateInstance(); void ICustomModifier.ConfigureScriptable(GameplayModifierScriptable scriptable) { ConfigureScriptable((TScriptable)(object)scriptable); } GameplayModifierScriptable ICustomModifier.CreateScriptable() { return (GameplayModifierScriptable)(object)ScriptableObject.CreateInstance(); } ModifierInstance ICustomModifier.CreateInstance() { return CreateInstance(); } } public interface ICustomModifier { string Guid { get; } string Name { get; } string Description { get; } void ConfigureScriptable(GameplayModifierScriptable scriptable); GameplayModifierScriptable CreateScriptable(); ModifierInstance CreateInstance(); } public abstract class ModifierInstance { public GameplayModifierScriptable Scriptable { get; internal set; } = null; public GameplayModifier LiveModifier { get; internal set; } = null; public virtual Func StatModificationAdd => (ModifierStat _, GameObject _) => 0f; public virtual void OnActivated() { } public virtual void OnRemoved(bool destroyed = false) { } } internal static class BuildPipeline { private static ModifierBuilder _builder = new ModifierBuilder(); private static bool _isBuilt; private static HashSet? _knownSchoolGuids; public static bool IsBuilt => _isBuilt; public static IEnumerator Run() { yield return _builder.BuildAllSchools(); yield return _builder.BuildAllModifiers(); ModifierInjector.InjectAllIntoScriptableLib(); _knownSchoolGuids = new HashSet(); Enumerator enumerator = PersistentScriptableLibrary.m_ModuleSchoolAssets.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair kvp = enumerator.Current; _knownSchoolGuids.Add(kvp.Key); } _isBuilt = true; } internal static void ReconcileSchools() { if (_knownSchoolGuids == null) { return; } Dictionary moduleSchoolAssets = PersistentScriptableLibrary.m_ModuleSchoolAssets; if (moduleSchoolAssets == null) { return; } Enumerator enumerator = moduleSchoolAssets.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair current = enumerator.Current; if (_knownSchoolGuids.Add(current.Key)) { ModifierBuilder.LinkExistingModulesToSchool(current.Value, current.Key); } } } internal static IEnumerator BuildLateModifier(string guid) { yield return _builder.BuildOne(guid); ModifierInjector.InjectScriptableLibFor(guid); } internal static IEnumerator BuildLateSchool(string guid) { yield return _builder.BuildOneSchool(guid); } } internal static class LoadoutGUIInjector { public static void InjectIntoLoadoutGUI(GUI_LoadoutTab loadoutTab, PlayerTraitScriptable scriptable) { GameObject gameObject = ((Component)((IEnumerable)loadoutTab.m_TraitSlots).ElementAt(0)).gameObject; GameObject val = Object.Instantiate(gameObject, loadoutTab.m_AvailableTraitsParent); ((Object)val).name = "Trait_" + ((GameplayModifierScriptable)scriptable).DisplayName; VAssist_PlayerTrait component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } GUI_TraitSlot component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.DestroyImmediate((Object)(object)component2); } val.SetActive(false); VAssist_PlayerTrait val2 = val.AddComponent(); val2.SetTrait(scriptable); GUI_TraitSlot val3 = val.AddComponent(); val3.m_Trait = scriptable; val3.m_IconImage = ((Component)val.transform.Find("IconImage")).GetComponent(); val3.m_CostBox = ((Component)val.transform.Find("PointCostBox")).gameObject; val3.m_CostText = (TMP_Text)(object)((Component)val3.m_CostBox.transform.Find("PointCostText")).GetComponent(); val3.m_VAssist = val2; val.SetActive(true); } } public static class ModBundleLoader { private const string TexturesFolder = "textures/"; private const string ArtifactsFolder = "artifacts/"; public static bool LoadBundle(string bundlePath, string modId) { //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown if (!File.Exists(bundlePath)) { ModLogger.Error("AssetBundle not found at " + bundlePath); return false; } byte[] array = File.ReadAllBytes(bundlePath); AssetBundle val = AssetBundle.LoadFromMemory(Il2CppStructArray.op_Implicit(array)); if ((Object)(object)val == (Object)null) { ModLogger.Error("Failed to load AssetBundle from memory."); return false; } string[] array2 = Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)val.GetAllAssetNames()); string[] array3 = array2; foreach (string text in array3) { string text2 = text.ToLowerInvariant(); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); if (text2.Contains("textures/")) { Texture2D val2 = val.LoadAsset(text); if (!((Object)(object)val2 == (Object)null)) { ((Object)val2).hideFlags = (HideFlags)32; Object.DontDestroyOnLoad((Object)(object)val2); if (AssetRegistry.Register(modId, fileNameWithoutExtension, val2)) { ModLogger.Msg($"Loaded texture '{modId}:{fileNameWithoutExtension}'"); } } } else if (text2.Contains("artifacts/")) { GameObject val3 = val.LoadAsset(text); if (!((Object)(object)val3 == (Object)null)) { MultilayerCollision val4 = val3.AddComponent(); val4.m_CreateForAllChildren = false; val4.m_ExistingCollidersToIgnore = new Il2CppReferenceArray((Collider[])(object)new Collider[0]); val4.m_Layer = new SingleUnityLayer(); val4.m_Mode = (Mode)1; ((Object)val3).hideFlags = (HideFlags)32; Object.DontDestroyOnLoad((Object)(object)val3); if (AssetRegistry.Register(modId, fileNameWithoutExtension, val3)) { ModLogger.Msg($"Loaded mesh '{modId}:{fileNameWithoutExtension}'"); } } } else { ModLogger.Warning($"Asset '{text}' is not under '{"textures/"}' or '{"artifacts/"}' — skipped."); } } val.Unload(false); return true; } } internal class ModifierBuilder { public IEnumerator BuildAllModifiers() { foreach (var (guid, _) in ModifierRegistry.All) { yield return BuildOne(guid); } } public IEnumerator BuildAllSchools() { foreach (var (guid, _) in SchoolRegistry.All) { yield return BuildOneSchool(guid); } } public IEnumerator BuildOneSchool(string guid) { if ((Object)(object)CustomAssetRegistry.GetModule(guid) != (Object)null) { yield break; } CustomItemModuleSchool schoolDef = SchoolRegistry.GetDefinition(guid); if (schoolDef != null) { Melon.Logger.Msg("[ModifierBuilder] Building school " + guid); ItemModuleSchool school = schoolDef.CreateSchool(); Object.DontDestroyOnLoad((Object)(object)school); ((Object)school).hideFlags = (HideFlags)32; CustomAssetLocator.Register(guid); CustomAssetRegistry.Register(guid, (Il2CppObjectBase)(object)school); if (!PersistentScriptableLibrary.m_ModuleSchoolAssets.ContainsKey(guid)) { PersistentScriptableLibrary.m_ModuleSchoolAssets.Add(guid, school); PersistentScriptableLibrary.m_ModuleSchools.Add(school); } LinkExistingModulesToSchool(school, guid); Melon.Logger.Msg("[ModifierBuilder] School " + guid + " ready."); } } public IEnumerator BuildOne(string guid) { if ((Object)(object)CustomAssetRegistry.GetModule(guid) != (Object)null) { yield break; } ICustomModifier def = ModifierRegistry.GetDefinition(guid); if (def != null) { Melon.Logger.Msg("[ModifierBuilder] Building " + guid); GameplayModifierScriptable scriptable = def.CreateScriptable(); Object.DontDestroyOnLoad((Object)(object)scriptable); scriptable.m_AssetGUID = guid; ((Object)scriptable).hideFlags = (HideFlags)32; ModifierRegistry.NotifyScriptableCreated(guid, scriptable); CustomAssetLocator.Register(guid); CustomAssetRegistry.Register(guid, (Il2CppObjectBase)(object)scriptable); ModifierInjector.InjectIntoManager(scriptable); if ((Object)(object)((Il2CppObjectBase)scriptable).TryCast() != (Object)null) { yield return VendorItemBuilder.RegisterVendorItem(guid); } Melon.Logger.Msg("[ModifierBuilder] " + guid + " ready."); } } internal static void LinkExistingModulesToSchool(ItemModuleSchool school, string schoolGuid) { ItemModuleScriptable scriptable = default(ItemModuleScriptable); foreach (var (text2, customModifier2) in ModifierRegistry.All) { if (customModifier2 is CustomItemModule customItemModule && customItemModule.SchoolGuids.Contains(schoolGuid) && PersistentScriptableLibrary.m_ItemModuleByGuid.TryGetValue(text2, ref scriptable)) { ModifierInjector.AddModuleToSchool(scriptable, schoolGuid); } } } } internal static class ModifierInjector { public static void InjectIntoManager(GameplayModifierScriptable scriptable) { GameplayModifierManager val = WeakStaticMonoBehaviourReference.op_Implicit(GameplayModifierManager.m_Instance); if (!((Object)(object)val == (Object)null)) { string assetGUID = scriptable.m_AssetGUID; if (!val.m_ModifierAssetMap.ContainsKey(assetGUID)) { val.m_ModifierScriptables.Add(scriptable); val.m_ModifierAssetMap.Add(assetGUID, scriptable); } PlayerTraitScriptable val2 = ((Il2CppObjectBase)scriptable).TryCast(); if ((Object)(object)val2 != (Object)null) { IReadOnlyReactiveCollection unlockedTraits = MetaProgressionManager.UnlockedTraits; ((Collection)(object)((Il2CppObjectBase)unlockedTraits).TryCast>())?.Add(val2); } } } public static void InjectIntoScriptableLib(ItemModuleScriptable scriptable, IReadOnlyList schoolGuids) { ModLogger.Msg("Injecting into persistent lib: " + ((GameplayModifierScriptable)scriptable).DisplayName); if (!PersistentScriptableLibrary.m_ItemModuleByGuid.ContainsKey(((GameplayModifierScriptable)scriptable).m_AssetGUID)) { PersistentScriptableLibrary.m_ItemModuleByGuid.Add(((GameplayModifierScriptable)scriptable).m_AssetGUID, scriptable); } if (!IsInIl2CppList(PersistentScriptableLibrary.m_ItemModules, ((GameplayModifierScriptable)scriptable).m_AssetGUID)) { PersistentScriptableLibrary.m_ItemModules.Add(scriptable); } foreach (string schoolGuid in schoolGuids) { AddModuleToSchool(scriptable, schoolGuid); } } public static void AddModuleToSchool(ItemModuleScriptable scriptable, string schoolGuid) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown ItemModuleSchool val = default(ItemModuleSchool); if (!PersistentScriptableLibrary.m_ModuleSchoolAssets.TryGetValue(schoolGuid, ref val)) { return; } for (int i = 0; i < val.m_SchoolEntries.Count; i++) { if (((GameplayModifierScriptable)val.m_SchoolEntries[i].m_ItemModule).m_AssetGUID == ((GameplayModifierScriptable)scriptable).m_AssetGUID) { return; } } ModuleSchoolEntry val2 = new ModuleSchoolEntry(); val2.m_ItemModule = scriptable; val2.m_Weight = scriptable.m_Weight; val.m_SchoolEntries.Add(val2); } public static void InjectScriptableLibFor(string guid) { if (!(ModifierRegistry.GetDefinition(guid) is CustomItemModule customItemModule)) { return; } ScriptableObject? module = CustomAssetRegistry.GetModule(guid); ItemModuleScriptable val = ((module != null) ? ((Il2CppObjectBase)module).TryCast() : null); if ((Object)(object)val == (Object)null) { return; } if (!PersistentScriptableLibrary.m_ItemModuleByGuid.ContainsKey(guid)) { PersistentScriptableLibrary.m_ItemModuleByGuid.Add(guid, val); } if (!IsInIl2CppList(PersistentScriptableLibrary.m_ItemModules, guid)) { PersistentScriptableLibrary.m_ItemModules.Add(val); } foreach (string schoolGuid in customItemModule.SchoolGuids) { AddModuleToSchool(val, schoolGuid); } } public static void InjectAllIntoScriptableLib() { foreach (KeyValuePair item in ModifierRegistry.All) { item.Deconstruct(out var key, out var _); string guid = key; ScriptableObject module = CustomAssetRegistry.GetModule(guid); ItemModuleScriptable val = ((Il2CppObjectBase)module).TryCast(); if (!((Object)(object)val == (Object)null) && ModifierRegistry.GetDefinition(guid) is CustomItemModule customItemModule) { InjectIntoScriptableLib(val, customItemModule.SchoolGuids); } } } private static bool IsInIl2CppList(List list, string guid) where T : Object { for (int i = 0; i < list.Count; i++) { GameplayModifierScriptable val = ((Il2CppObjectBase)(object)list[i]).TryCast(); if ((Object)(object)val != (Object)null && val.m_AssetGUID == guid) { return true; } } return false; } } internal static class VendorItemBuilder { private static readonly List _vendorArtifacts = new List(); private static Currency? cachedCurrency; public static IEnumerator RegisterVendorItem(string guid) { if ((Object)(object)cachedCurrency == (Object)null) { AsyncOperationHandle handle = Addressables.LoadAssetAsync(Object.op_Implicit("00e70cd5fa09dc64aa3e64b4d8ee4011")); yield return handle; if ((int)handle.Status == 1) { cachedCurrency = handle.Result; } } ArtifactSoldByVendor artifactDef = (ArtifactSoldByVendor)ModifierRegistry.GetDefinition(guid); if (artifactDef != null) { VendorItem vendorItem = ScriptableObject.CreateInstance(); vendorItem.m_Item = CustomAssetRegistry.GetModule(guid); vendorItem.m_AssetGuid = artifactDef.VendorItemGuid; vendorItem.m_BaseCost_Currency = artifactDef.CreditBaseCost; vendorItem.m_BaseCost_Materia = artifactDef.MateriaBaseCost; vendorItem.m_CanSpawnCondition = new VentureCondition(); vendorItem.m_CanSpawnCondition.m_RequiredStatus = (VentureStatus)0; vendorItem.m_CanSpawnCondition.m_Venture = null; vendorItem.m_Currency = cachedCurrency; vendorItem.m_CurrencyReward = new ItemCurrencyValue(); vendorItem.m_CurrencyReward.m_Amount = 0f; vendorItem.m_CurrencyReward.m_Currency = null; CustomAssetLocator.Register(vendorItem.m_AssetGuid); CustomAssetRegistry.Register(vendorItem.m_AssetGuid, (Il2CppObjectBase)(object)vendorItem); _vendorArtifacts.Add(artifactDef); } } public static void AddItemsToVendor(Vendor vendor) { VendorItemList randomItemList = vendor.m_RandomItemList; List val = ((randomItemList != null) ? randomItemList.m_PotentialItems : null); if (val == null) { return; } HashSet hashSet = new HashSet(StringComparer.Ordinal); Enumerator enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { PotentialItem current = enumerator.Current; if ((Object)(object)((current != null) ? current.m_Item : null) != (Object)null) { hashSet.Add(current.m_Item.m_AssetGuid); } } foreach (ArtifactSoldByVendor vendorArtifact in _vendorArtifacts) { string vendorItemGuid = vendorArtifact.VendorItemGuid; if (!hashSet.Contains(vendorItemGuid)) { ScriptableObject? module = CustomAssetRegistry.GetModule(vendorItemGuid); VendorItem val2 = ((module != null) ? ((Il2CppObjectBase)module).TryCast() : null); if (!((Object)(object)val2 == (Object)null)) { PotentialItem val3 = Activator.CreateInstance(); val3.m_AllowMultiple = vendorArtifact.VendorAllowMultiple; val3.m_PickChanceWeight = vendorArtifact.VendorPickChanceWeight; val3.m_Item = val2; val.Add(val3); hashSet.Add(vendorItemGuid); } } } } } public static class ModLogger { private const string CategoryName = "CustomGameplayModifiers"; private static MelonPreferences_Category _category; private static MelonPreferences_Entry _verboseLogging; public static void Initialize() { _category = MelonPreferences.CreateCategory("CustomGameplayModifiers", "Custom Gameplay Modifiers"); _verboseLogging = _category.CreateEntry("VerboseLogging", false, "Verbose Logging", "When enabled, all log messages are shown. When disabled, only errors are printed.", false, false, (ValueValidator)null, (string)null); } public static void Msg(string text) { if (_verboseLogging.Value) { MelonLogger.Msg(text); } } public static void Warning(string text) { if (_verboseLogging.Value) { MelonLogger.Warning(text); } } public static void Error(string text) { MelonLogger.Error(text); } } public static class AssetRegistry where T : Object { private static readonly TypedAssetRegistry s_Registry = new TypedAssetRegistry(); public static T? Get(string ns, string key) { return s_Registry.Get(ns, key); } internal static bool Register(string ns, string key, T obj) { return s_Registry.Register(ns, key, obj); } internal static void RegisterVanilla(string key, T obj) { s_Registry.RegisterVanilla(key, obj); } } public enum ComponentSubtype { Engine, Aux, Reactor, Sensor, ShieldGenerator, PilotCannon, MultiTurret, SpecialWeapon, SpecialWeaponNoProjectile } public static class ItemAssetRegistry { private sealed record WeaponData(string Guid, string Name, bool IsMelee); private sealed record ComponentData(string Guid, string Name, ComponentSubtype Subtype); private static readonly WeaponData[] WeaponEntries = new WeaponData[13] { new WeaponData("046383b13f53ad144805f5dca98b4b86", "MeleeWeapon_Chainblade", IsMelee: true), new WeaponData("a52219e07db611248800766fe8d53744", "MeleeWeapon_Wrench", IsMelee: true), new WeaponData("f077b42a85cfb7f4bb0d55729c4fc5c0", "MeleeWeapon_Crowbar", IsMelee: true), new WeaponData("46f7dd81eea325d4295083369d7b9a9d", "MeleeWeapon_AtiranBlackbelt", IsMelee: true), new WeaponData("b5b14acbf52842b4f90002bd4e9d1391", "Pickupable_SemiRifle_MK0", IsMelee: false), new WeaponData("11d2d7e9f079ed4499c9591d8d68c7a7", "Pickupable_Shotgun_MK0", IsMelee: false), new WeaponData("2cbd789d647fa9a4d96f462001a99c91", "Pickupable_MarksmanRifle_Mk0", IsMelee: false), new WeaponData("ea1f1e6ac3c88fe469708ce10b5e451a", "Pickupable_SMG_MK0", IsMelee: false), new WeaponData("b90b477e483f6cc4aa9a48f33e4400e3", "Pickupable_PDW_MK0", IsMelee: false), new WeaponData("55b2b5f6d20d4eb4ab9ef216e5237928", "Pickupable_LMG_MK0", IsMelee: false), new WeaponData("dd2afc39b34322c4381b6a3ed3e5988a", "Pickupable_AssaultRifle_MK0", IsMelee: false), new WeaponData("5b78767341d912a489d26a3136ab62c7", "Pickupable_MiningLaser_MK0", IsMelee: false), new WeaponData("d0261db8215008e48abfefbf7485acfd", "Pickupable_Revolver_MK0", IsMelee: false) }; private static readonly ComponentData[] ComponentEntries = new ComponentData[31] { new ComponentData("f1302af5a63e825478b7fb9f953401aa", "Component_Engine_1_1", ComponentSubtype.Engine), new ComponentData("4524f4ac1fa8cb34dbff50f8c5c14927", "Component_Engine_2_1", ComponentSubtype.Engine), new ComponentData("fb2bbc3f13c228a44ba53f020e1df249", "Component_Engine_3_1", ComponentSubtype.Engine), new ComponentData("dde01f5723d9b0047abb3d223f5541cd", "Component_Engine_4_1", ComponentSubtype.Engine), new ComponentData("2c60b00a88d34b546865a36738fabc2a", "Component_Aux_1_1", ComponentSubtype.Aux), new ComponentData("8cbe912f6e885134680a52935cca96a5", "Component_Aux_2_1", ComponentSubtype.Aux), new ComponentData("4bfcb457279ce824e8fd7989760d9252", "Component_Aux_3_1", ComponentSubtype.Aux), new ComponentData("65e495611fd9233419832053f8ce55bd", "Component_Reactor_1_1", ComponentSubtype.Reactor), new ComponentData("85b241f7f2fa6654e9c522519358d1bc", "Component_Reactor_2_1", ComponentSubtype.Reactor), new ComponentData("f400f9acd1731b64a87b69ce40517971", "Component_Reactor_3_1", ComponentSubtype.Reactor), new ComponentData("95c51a0f21d28ba459a43bbf3dbc0790", "Component_Reactor_4_1", ComponentSubtype.Reactor), new ComponentData("3ee2f96ed55e8de4898d4f922eba8f66", "Component_Sensor_1_1", ComponentSubtype.Sensor), new ComponentData("d4b4eb9b7856fce4e9c1bb3a78c9807e", "Component_Sensor_2_1", ComponentSubtype.Sensor), new ComponentData("eac8acd058989964ab7a07cf7de03fa5", "Component_Sensor_3_1", ComponentSubtype.Sensor), new ComponentData("352d8b4d1f0f38249b5a88c19a11caf3", "Component_ShieldGenerator_1_1", ComponentSubtype.ShieldGenerator), new ComponentData("7a2d7e2dbbb33f742a1c885667377425", "Component_ShieldGenerator_2_1", ComponentSubtype.ShieldGenerator), new ComponentData("554d65de54698714c9f5d2f73bc33261", "Component_ShieldGenerator_3_1", ComponentSubtype.ShieldGenerator), new ComponentData("c7e0f6d13e18db440b37a42470f42744", "Component_PilotCannon_1_1", ComponentSubtype.PilotCannon), new ComponentData("c3346b9a547672948a2fe02ea2bb5de5", "Component_PilotCannon_2_1", ComponentSubtype.PilotCannon), new ComponentData("8c32f9e4ff293894582ceb6b831c40af", "Component_PilotCannon_3_1", ComponentSubtype.PilotCannon), new ComponentData("d151b8914ed56d74985d345a118f9a5e", "Component_PilotCannon_4_1", ComponentSubtype.PilotCannon), new ComponentData("558ac570efdfbe64390ab32c39d45ff3", "Component_MultiTurret_1_1", ComponentSubtype.MultiTurret), new ComponentData("5e4082467be3c344698f724e74c6660a", "Component_MultiTurret_2_1", ComponentSubtype.MultiTurret), new ComponentData("b98c1f15ee8b58343acf4f62ddaa93ab", "Component_MultiTurret_3_1", ComponentSubtype.MultiTurret), new ComponentData("e2b646f5b39d9994a929c62d32635793", "Component_MultiTurret_4_1", ComponentSubtype.MultiTurret), new ComponentData("889c471a3fab57d44b28f2592be5d7f8", "Component_SpecialWeapon_HeavyCannon", ComponentSubtype.SpecialWeapon), new ComponentData("15bebeb1e9273af4fb7f4213452a6c58", "Component_SpecialWeapon_MissileTurret_1", ComponentSubtype.SpecialWeapon), new ComponentData("d593e671947518544ab6dcd2deef3e2e", "Component_SpecialWeapon_Railgun_1", ComponentSubtype.SpecialWeapon), new ComponentData("3290a7dbea83de5488cca77e44cae0a8", "Component_SpecialWeapon_Minigun", ComponentSubtype.SpecialWeapon), new ComponentData("e1d2c08495890004e9ebb0ca7fe7c5a1", "Component_SpecialWeapon_Shield_1", ComponentSubtype.SpecialWeaponNoProjectile), new ComponentData("10b36cf783993154cbcf8679744cd900", "Component_SpecialWeapon_TargetingModule_1", ComponentSubtype.SpecialWeaponNoProjectile) }; private static List? _allWeaponRefs; private static Dictionary? _weaponByGuid; private static Dictionary? _weaponByName; private static List? _allComponentRefs; private static Dictionary? _componentByGuid; private static Dictionary? _componentByName; private static bool _initialized; internal static void Initialize() { if (!_initialized) { _initialized = true; BuildWeaponCache(); BuildComponentCache(); } } private static void BuildCache(T[] entries, Func getGuid, Func getName, out List allRefs, out Dictionary byGuid, out Dictionary byName) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown allRefs = new List(entries.Length); byGuid = new Dictionary(entries.Length); byName = new Dictionary(entries.Length); foreach (T arg in entries) { AssetReference val = new AssetReference(getGuid(arg)); allRefs.Add(val); byGuid[getGuid(arg)] = val; byName[getName(arg)] = val; } } private static void BuildWeaponCache() { BuildCache(WeaponEntries, (WeaponData w) => w.Guid, (WeaponData w) => w.Name, out _allWeaponRefs, out _weaponByGuid, out _weaponByName); } private static void BuildComponentCache() { BuildCache(ComponentEntries, (ComponentData c) => c.Guid, (ComponentData c) => c.Name, out _allComponentRefs, out _componentByGuid, out _componentByName); } public static IEnumerable GetAllWeapons() { return _allWeaponRefs; } public static IEnumerable GetAllMeleeWeapons() { return from w in WeaponEntries where w.IsMelee select _weaponByGuid.GetValueOrDefault(w.Guid) into r where r != null select r; } public static IEnumerable GetAllPrimaryWeapons() { return from w in WeaponEntries where !w.IsMelee select _weaponByGuid.GetValueOrDefault(w.Guid) into r where r != null select r; } public static AssetReference? GetWeaponByGuid(string guid) { if (string.IsNullOrEmpty(guid) || _weaponByGuid == null) { return null; } _weaponByGuid.TryGetValue(guid, out AssetReference value); return value; } public static AssetReference? GetWeaponByName(string name) { if (string.IsNullOrEmpty(name) || _weaponByName == null) { return null; } _weaponByName.TryGetValue(name, out AssetReference value); return value; } public static IEnumerable GetAllComponents() { return _allComponentRefs; } public static IEnumerable GetAllComponentsBySubtype(ComponentSubtype subtype) { return from c in ComponentEntries where c.Subtype == subtype select _componentByGuid.GetValueOrDefault(c.Guid) into r where r != null select r; } public static AssetReference? GetComponentByGuid(string guid) { if (string.IsNullOrEmpty(guid) || _componentByGuid == null) { return null; } _componentByGuid.TryGetValue(guid, out AssetReference value); return value; } public static AssetReference? GetComponentByName(string name) { if (string.IsNullOrEmpty(name) || _componentByName == null) { return null; } _componentByName.TryGetValue(name, out AssetReference value); return value; } } public static class ModifierRegistry { private static readonly Dictionary _definitions = new Dictionary(); private static readonly Dictionary> _instances = new Dictionary>(); internal static IReadOnlyDictionary All => _definitions; public static void Register(ICustomModifier modifier) { if (_definitions.ContainsKey(modifier.Guid)) { throw new InvalidOperationException("A modifier with GUID '" + modifier.Guid + "' is already registered."); } _definitions[modifier.Guid] = modifier; LocalizationInjector.AddOrUpdate(modifier.Guid + "-NAME", modifier.Name); LocalizationInjector.AddOrUpdate(modifier.Guid + "-DESC", modifier.Description); ModLogger.Msg("[ModifierRegistry] Registered: " + modifier.Guid); if (BuildPipeline.IsBuilt) { ModLogger.Msg("[ModifierRegistry] Late registration — triggering incremental build."); MelonCoroutines.Start(BuildPipeline.BuildLateModifier(modifier.Guid)); } } internal static ICustomModifier? GetDefinition(string guid) { ICustomModifier value; return _definitions.TryGetValue(guid, out value) ? value : null; } internal static bool IsCustom(string guid) { return _definitions.ContainsKey(guid); } internal static IEnumerable GetInstances(string guid) { if (!_instances.TryGetValue(guid, out Dictionary map)) { yield break; } foreach (ModifierInstance value in map.Values) { yield return value; } } internal static IEnumerable AllInstances() { foreach (Dictionary map in _instances.Values) { foreach (ModifierInstance value in map.Values) { yield return value; } } } internal static ModifierInstance? GetInstance(string guid, IntPtr stablePtr) { if (_instances.TryGetValue(guid, out Dictionary value) && value.TryGetValue(stablePtr, out var value2)) { return value2; } return null; } internal static void ClearAllInstances() { foreach (Dictionary value in _instances.Values) { foreach (ModifierInstance value2 in value.Values) { try { value2.OnRemoved(destroyed: true); } catch (NullReferenceException ex) { ModLogger.Error(ex.Message); ModLogger.Error("Possibly caused by trying to access a LiveModifier while the parameter \"destroyed\" is true"); ModLogger.Error(ex.StackTrace ?? "null"); } } } _instances.Clear(); } internal static void NotifyScriptableCreated(string guid, GameplayModifierScriptable scriptable) { GetDefinition(guid)?.ConfigureScriptable(scriptable); } internal static ModifierInstance? NotifyActivated(string guid, IntPtr stablePtr, GameplayModifierScriptable scriptable, GameplayModifier liveModifier, Func createInstance) { if (!_definitions.ContainsKey(guid)) { return null; } if (!_instances.TryGetValue(guid, out Dictionary value)) { value = (_instances[guid] = new Dictionary()); } if (value.TryGetValue(stablePtr, out var value2)) { value2.LiveModifier = liveModifier; return value2; } ModifierInstance modifierInstance = createInstance(); modifierInstance.Scriptable = scriptable; modifierInstance.LiveModifier = liveModifier; value[stablePtr] = modifierInstance; modifierInstance.OnActivated(); return modifierInstance; } internal static void NotifyRemoved(string guid, IntPtr stablePtr) { if (_instances.TryGetValue(guid, out Dictionary value) && value.TryGetValue(stablePtr, out var value2)) { value2.OnRemoved(); value.Remove(stablePtr); } } } public static class SchoolRegistry { private static readonly Dictionary _definitions = new Dictionary(); internal static IReadOnlyDictionary All => _definitions; public static void Register(CustomItemModuleSchool school) { if (_definitions.ContainsKey(school.Guid)) { throw new InvalidOperationException("A school with GUID '" + school.Guid + "' is already registered."); } _definitions[school.Guid] = school; ModLogger.Msg("[SchoolRegistry] Registered: " + school.Guid); if (BuildPipeline.IsBuilt) { ModLogger.Msg("[SchoolRegistry] Late registration — triggering incremental build."); MelonCoroutines.Start(BuildPipeline.BuildLateSchool(school.Guid)); } } internal static CustomItemModuleSchool? GetDefinition(string guid) { CustomItemModuleSchool value; return _definitions.TryGetValue(guid, out value) ? value : null; } } internal class TypedAssetRegistry where T : Object { private const string VanillaNamespace = "vanilla"; private readonly Dictionary> _namespaces = new Dictionary>(); public T? Get(string ns, string key) { if (_namespaces.TryGetValue(ns, out Dictionary value) && value.TryGetValue(key, out var value2)) { return value2; } return default(T); } public bool Register(string ns, string key, T obj) { if (string.Equals(ns, "vanilla", StringComparison.OrdinalIgnoreCase)) { ModLogger.Error($"Refusing to register '{key}' under reserved namespace '{"vanilla"}'."); return false; } if ((Object)(object)obj == (Object)null) { ModLogger.Error($"Refusing to register null object for '{ns}:{key}'."); return false; } if (!_namespaces.TryGetValue(ns, out Dictionary value)) { value = new Dictionary(); _namespaces[ns] = value; } if (value.ContainsKey(key)) { ModLogger.Warning($"Overwriting existing key '{key}' in namespace '{ns}'."); } value[key] = obj; return true; } internal void RegisterVanilla(string key, T obj) { if (!_namespaces.TryGetValue("vanilla", out Dictionary value)) { value = new Dictionary(); _namespaces["vanilla"] = value; } value[key] = obj; } } public static class GameEventBus { private static readonly Dictionary _handlers = new Dictionary(); public static void Subscribe(Action handler) { Type typeFromHandle = typeof(T); _handlers[typeFromHandle] = (_handlers.TryGetValue(typeFromHandle, out Delegate value) ? Delegate.Combine(value, handler) : handler); } public static void Unsubscribe(Action handler) { Type typeFromHandle = typeof(T); if (_handlers.TryGetValue(typeFromHandle, out Delegate value)) { Delegate obj = Delegate.Remove(value, handler); if ((object)obj == null) { _handlers.Remove(typeFromHandle); } else { _handlers[typeFromHandle] = obj; } } } public static void Publish(T evt) { if (_handlers.TryGetValue(typeof(T), out Delegate value) && (object)value != null) { ((Action)value)(evt); } } internal static void ClearSubscriptions() { _handlers.Clear(); } } internal static class HeldItemTracker { private static readonly Dictionary _lastHeldByClientId = new Dictionary(); public static void OnItemHeldChanged(PlayerController player, PersistentPickupable? current) { if (!((Object)(object)player == (Object)null)) { _lastHeldByClientId.TryGetValue(player.ClientId, out PersistentPickupable value); if (!object.Equals(value, current)) { _lastHeldByClientId[player.ClientId] = current; GameEventBus.Publish(new ItemHeldChangedEvent(player, value, current)); } } } } internal static class LocalizationInjector { private static StringTable? s_StringTable; private static readonly Dictionary s_PendingEntries = new Dictionary(); private static readonly object s_Lock = new object(); public static bool IsReady { get { lock (s_Lock) { return (Object)(object)s_StringTable != (Object)null; } } } public static IEnumerator FindTableRoutine() { int attempts = 0; while (attempts < 300) { bool found; lock (s_Lock) { found = (Object)(object)s_StringTable != (Object)null; } if (found) { yield break; } attempts++; Il2CppArrayBase tables = Resources.FindObjectsOfTypeAll(); foreach (StringTable table in tables) { if (((LocalizationTable)table).TableCollectionName == "STC_Main") { lock (s_Lock) { s_StringTable = table; } ModLogger.Msg("STC_Main found, flushing pending entries."); FlushPending(); yield break; } } yield return (object)new WaitForSeconds(0.5f); } lock (s_Lock) { if ((Object)(object)s_StringTable == (Object)null) { ModLogger.Error("STC_Main was never found after max attempts."); } } } private static void FlushPending() { lock (s_Lock) { foreach (KeyValuePair s_PendingEntry in s_PendingEntries) { WriteEntry(s_PendingEntry.Key, s_PendingEntry.Value); } s_PendingEntries.Clear(); } } public static void AddOrUpdate(string key, string value) { lock (s_Lock) { if ((Object)(object)s_StringTable == (Object)null) { s_PendingEntries[key] = value; } else { WriteEntry(key, value); } } } private static void WriteEntry(string key, string value) { StringTableEntry entry = ((DetailedLocalizationTable)(object)s_StringTable).GetEntry(key); if (entry != null) { entry.Value = value; } else { ((DetailedLocalizationTable)(object)s_StringTable).AddEntry(key, value); } } } internal static class SceneEventsService { private static GameplayModifierManager? _lastKnownManager; public static void OnSceneLoaded(int buildIndex, string sceneName) { HandleManagerChange(sceneName); InjectVendors(); BuildPipeline.ReconcileSchools(); RefreshArtifactCabinets(); } private static void HandleManagerChange(string sceneName) { GameplayModifierManager instance = GameplayModifierManager.Instance; if (instance != _lastKnownManager) { ModLogger.Msg("GameplayModifierManager instance changed on scene '" + sceneName + "' — clearing modifier registry."); ModifierRegistry.ClearAllInstances(); GameEventBus.ClearSubscriptions(); _lastKnownManager = instance; } } private static void InjectVendors() { Vendor[] array = Il2CppArrayBase.op_Implicit(Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0)); Vendor[] array2 = array; foreach (Vendor val in array2) { VendorItemList randomItemList = val.m_RandomItemList; if (((randomItemList != null) ? randomItemList.m_AssetGuid : null) == "f21d418892b193b458716f7c6576ac21") { ModLogger.Msg(((Object)val).name); VendorItemBuilder.AddItemsToVendor(val); } } } private static void RefreshArtifactCabinets() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown ArtifactCabinet[] array = Il2CppArrayBase.op_Implicit(Object.FindObjectsOfType()); ArtifactCabinet[] array2 = array; foreach (ArtifactCabinet val in array2) { if (val.Artifact != null) { val.m_ArtifactVisualsInstalled.DestroyCurrentVisuals(); val.m_ArtifactVisualsInstalled.SpawnVisualsAsync(val.Artifact, new CancellationToken(), false); } } } } } namespace CustomGameplayModifiers.Framework.Observers { [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver>) })] public class ArtifactAddObserver : Object { public Action>? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public ArtifactAddObserver(IntPtr ptr) : base(ptr) { } public ArtifactAddObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(CollectionAddEvent value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver>) })] public class ArtifactRemoveObserver : Object { public Action>? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public ArtifactRemoveObserver(IntPtr ptr) : base(ptr) { } public ArtifactRemoveObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(CollectionRemoveEvent value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver) })] public class FloatObserver : Object { public Action? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public FloatObserver(IntPtr ptr) : base(ptr) { } public FloatObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(float value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver) })] public class IntObserver : Object { public Action? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public IntObserver(IntPtr ptr) : base(ptr) { } public IntObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(int value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver>) })] public class ItemModuleAddObserver : Object { public Action>? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public ItemModuleAddObserver(IntPtr ptr) : base(ptr) { } public ItemModuleAddObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(CollectionAddEvent value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver>) })] public class ItemModuleRemoveObserver : Object { public Action>? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public ItemModuleRemoveObserver(IntPtr ptr) : base(ptr) { } public ItemModuleRemoveObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(CollectionRemoveEvent value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver>) })] public class PlayerTraitAddObserver : Object { public Action>? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public PlayerTraitAddObserver(IntPtr ptr) : base(ptr) { } public PlayerTraitAddObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(CollectionAddEvent value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IObserver>) })] public class PlayerTraitRemoveObserver : Object { public Action>? OnNextAction; public Action? OnErrorAction; public Action? OnCompletedAction; public PlayerTraitRemoveObserver(IntPtr ptr) : base(ptr) { } public PlayerTraitRemoveObserver() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void OnNext(CollectionRemoveEvent value) { OnNextAction?.Invoke(value); } public void OnError(Exception error) { OnErrorAction?.Invoke(error); } public void OnCompleted() { OnCompletedAction?.Invoke(); } } } namespace CustomGameplayModifiers.Framework.EventType { public readonly struct AIShipDamagedEvent { public readonly AI_Capability_Ship_Health ShipHealth; public readonly ReceivedDamage ReceivedDamage; public AIShipDamagedEvent(AI_Capability_Ship_Health shipHealth, ReceivedDamage dmg) { ShipHealth = shipHealth; ReceivedDamage = dmg; } } public readonly struct ItemHeldChangedEvent { public readonly PlayerController Player; public readonly PersistentPickupable? PreviousItem; public readonly PersistentPickupable? NewItem; public ItemHeldChangedEvent(PlayerController player, PersistentPickupable? previous, PersistentPickupable? current) { Player = player; PreviousItem = previous; NewItem = current; } } public readonly struct OnFootKilledEvent { public readonly AI_Controller_OnFoot AiController; public readonly ReceivedDamage ReceivedDamage; public OnFootKilledEvent(AI_Controller_OnFoot ai, ReceivedDamage dmg) { AiController = ai; ReceivedDamage = dmg; } } public struct ShipCannonFiredEvent { public readonly SpaceShip_Cannon_Base Cannon; public readonly VisualEffectAsset MuzzleFlashFx; public readonly bool IsFiredByBuddyBot; public ShipCannonFiredEvent(SpaceShip_Cannon_Base cannon, VisualEffectAsset muzzleFlashFx, bool isFiredByBuddyBot) { Cannon = cannon; MuzzleFlashFx = muzzleFlashFx; IsFiredByBuddyBot = isFiredByBuddyBot; } } public readonly struct WeaponFiredEvent { public readonly PickupableItemFirstPerson_GenericWeapon Weapon; public WeaponFiredEvent(PickupableItemFirstPerson_GenericWeapon weapon) { Weapon = weapon; } } public readonly struct WeaponReloadedEvent { public readonly PickupableItemFirstPerson_GenericWeapon Weapon; public WeaponReloadedEvent(PickupableItemFirstPerson_GenericWeapon weapon) { Weapon = weapon; } } } namespace CustomGameplayModifiers.CustomAddressables { internal static class CustomAddressablesRegisterer { private static bool _registered; public static void TryRegister() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (!_registered && Addressables.ResourceManager != null) { CustomAssetLocator customAssetLocator = new CustomAssetLocator(); Addressables.AddResourceLocator(new IResourceLocator(((Il2CppObjectBase)customAssetLocator).Pointer), (string)null, (IResourceLocation)null); CustomAssetProvider customAssetProvider = new CustomAssetProvider(); Addressables.ResourceManager.ResourceProviders.Insert(0, new IResourceProvider(((Il2CppObjectBase)customAssetProvider).Pointer)); _registered = true; Melon.Logger.Msg("Addressables registration complete."); } } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IResourceLocator) })] public class CustomAssetLocator : Object { private static readonly Dictionary _locations = new Dictionary(); public string LocatorId => "CustomGameplayModifiers.CustomAssetLocator"; public List Keys => new List(); public CustomAssetLocator(IntPtr ptr) : base(ptr) { } public CustomAssetLocator() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public bool Locate(Object? key, Type resourceType, out List? locations) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown string text = ((key != null) ? key.ToString() : null); if (text != null && _locations.TryGetValue(text, out ResourceLocationBase value)) { locations = new List(); locations.Add(new IResourceLocation(((Il2CppObjectBase)value).Pointer)); return true; } locations = null; return false; } public static void Register(string guid) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown _locations[guid] = new ResourceLocationBase(guid, guid, "CustomGameplayModifiers.CustomAssetProvider", Il2CppType.From(typeof(ScriptableObject)), (Il2CppReferenceArray)null); } } [RegisterTypeInIl2CppWithInterfaces(new Type[] { typeof(IResourceProvider) })] public class CustomAssetProvider : Object { public string ProviderId => "CustomGameplayModifiers.CustomAssetProvider"; public int OperationCacheCount => 0; public CustomAssetProvider(IntPtr ptr) : base(ptr) { } public CustomAssetProvider() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public bool CanProvide(IResourceLocation location, Type resourceType) { return true; } public void Provide(ProvideHandle provideHandle) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown string primaryKey = provideHandle.Location.PrimaryKey; ScriptableObject module = CustomAssetRegistry.GetModule(primaryKey); if ((Object)(object)module != (Object)null) { ModLogger.Msg("Provider serving asset for key: " + primaryKey); provideHandle.Complete(((Il2CppObjectBase)module).Cast(), true, (Exception)null); } else { provideHandle.Complete((Object)null, false, new Exception("[ModCustomAssetProvider] Key not found: " + primaryKey)); } } public bool Release(IResourceLocation location, Object asset) { return true; } public void Initialize(string id, string data) { } } internal static class CustomAssetRegistry { private static readonly Dictionary _registry = new Dictionary(); public static int Count => _registry.Count; public static void Register(string guid, Il2CppObjectBase obj) { _registry[guid] = obj.Pointer; } public static ScriptableObject? GetModule(string guid) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if (_registry.TryGetValue(guid, out var value) && value != IntPtr.Zero) { return new ScriptableObject(value); } return null; } } } namespace CustomGameplayModifiers.Artifacts { public class ArtifactInstance : ModifierInstance { public Artifact LiveArtifact => (Artifact)base.LiveModifier; public ArtifactScriptable ArtifactScriptable => (ArtifactScriptable)base.Scriptable; } internal static class ArtifactMeshCache { public const string FrameCommonKey = "frame-common"; public const string FrameRareKey = "frame-rare"; public const string FrameLegendaryKey = "frame-legendary"; public const string UtilityDiscKey = "disc-utility"; public const string AttackDiscKey = "disc-attack"; public const string DefenseDiscKey = "disc-defense"; public static bool Ready { get; private set; } public static IEnumerator LoadRoutine() { (string Guid, string Key)[] assets = new(string, string)[6] { ("b6a641b7d560fd644aa1afd7240c03e7", "frame-common"), ("bfe2c7b6abac8ad45a1a6be2bbeb1f26", "frame-rare"), ("24ec8675fabb83d47be7a8209231f16d", "frame-legendary"), ("2dfcb45d376119241870ddd52ec02bf7", "disc-utility"), ("c2a52f9486b7e8e4da678f775711ef10", "disc-attack"), ("b6362c804adb0404fad7190da2b284d5", "disc-defense") }; (string Guid, string Key)[] array = assets; for (int i = 0; i < array.Length; i++) { var (guid, key) = array[i]; yield return LoadAsset(guid, key); if ((Object)(object)AssetRegistry.Get("vanilla", key) == (Object)null) { yield break; } } Ready = true; ModLogger.Msg("[ArtifactMeshCache] Loaded vanilla meshes."); } private static IEnumerator LoadAsset(string address, string key) { AsyncOperationHandle handle = Addressables.LoadAssetAsync(Object.op_Implicit(address)); yield return handle; if ((int)handle.Status == 1) { AssetRegistry.RegisterVanilla(key, handle.Result); Addressables.Release(handle); } } } public abstract class ArtifactSoldByVendor : CustomArtifact { public abstract string VendorItemGuid { get; } public abstract int MateriaBaseCost { get; } public abstract int CreditBaseCost { get; } public abstract int VendorPickChanceWeight { get; } public abstract bool VendorAllowMultiple { get; } } public abstract class CustomArtifact : CustomModifier { public override void ConfigureScriptable(ArtifactScriptable scriptable) { base.ConfigureScriptable(scriptable); scriptable.m_TweakableValues_Common = new List(); scriptable.m_TweakableValues_Legendary = new List(); scriptable.m_TweakableValues_Rare = new List(); } } }