From 53d5525094b1ab604529b72089b6aa1232880cf7 Mon Sep 17 00:00:00 2001 From: Abbysssal <55982389+Abbysssal@users.noreply.github.com> Date: Fri, 9 Jul 2021 22:15:45 +0700 Subject: [PATCH] v3.0.0-rc.1 --- .../Properties/Resources.Designer.cs | 10 ++ RogueLibsCore.Test/Properties/Resources.resx | 3 + RogueLibsCore.Test/Resources/Hug.bin | Bin 0 -> 3340 bytes RogueLibsCore.Test/Resources/Hug.png | Bin 0 -> 3340 bytes RogueLibsCore.Test/RogueLibsCore.Test.csproj | 2 + RogueLibsCore.Test/TestPlugin.cs | 1 + RogueLibsCore.Test/Tests/GiantAbility.cs | 28 ++--- RogueLibsCore.Test/Tests/Hug.cs | 102 +++++++++++++++++ RogueLibsCore.Test/Tests/Smoker.cs | 7 +- RogueLibsCore/Hooks/Items/CustomAbility.cs | 28 ++++- RogueLibsCore/Hooks/Traits/CustomTrait.cs | 5 +- RogueLibsCore/Patches/Patches_Abilities.cs | 104 ++++++++++++++++-- RogueLibsCore/Patches/Patches_Misc.cs | 10 ++ RogueLibsCore/Patches/Patches_Sprites.cs | 7 ++ .../Patches/Patches_TraitsStatusEffects.cs | 11 +- 15 files changed, 277 insertions(+), 41 deletions(-) create mode 100644 RogueLibsCore.Test/Resources/Hug.bin create mode 100644 RogueLibsCore.Test/Resources/Hug.png create mode 100644 RogueLibsCore.Test/Tests/Hug.cs diff --git a/RogueLibsCore.Test/Properties/Resources.Designer.cs b/RogueLibsCore.Test/Properties/Resources.Designer.cs index e8ae3c608..9364e9341 100644 --- a/RogueLibsCore.Test/Properties/Resources.Designer.cs +++ b/RogueLibsCore.Test/Properties/Resources.Designer.cs @@ -90,6 +90,16 @@ internal static byte[] Duplicator { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] Hug { + get { + object obj = ResourceManager.GetObject("Hug", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/RogueLibsCore.Test/Properties/Resources.resx b/RogueLibsCore.Test/Properties/Resources.resx index a9b7aa03b..5a7203744 100644 --- a/RogueLibsCore.Test/Properties/Resources.resx +++ b/RogueLibsCore.Test/Properties/Resources.resx @@ -127,6 +127,9 @@ ..\Resources\Duplicator.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\Hug.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\LootBox.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/RogueLibsCore.Test/Resources/Hug.bin b/RogueLibsCore.Test/Resources/Hug.bin new file mode 100644 index 0000000000000000000000000000000000000000..eae615ece4c601f930c3f6d7b7a8e8d33e3add8d GIT binary patch literal 3340 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 WE8dA{^lQ!l0000Resources.resx + @@ -85,6 +86,7 @@ + diff --git a/RogueLibsCore.Test/TestPlugin.cs b/RogueLibsCore.Test/TestPlugin.cs index 744badc98..5b36514ca 100644 --- a/RogueLibsCore.Test/TestPlugin.cs +++ b/RogueLibsCore.Test/TestPlugin.cs @@ -30,6 +30,7 @@ public void Awake() NuclearBriefcase.Test(); GiantAbility.Test(); + Hug.Test(); Smoker.Test(); } diff --git a/RogueLibsCore.Test/Tests/GiantAbility.cs b/RogueLibsCore.Test/Tests/GiantAbility.cs index 367d6f210..f2b7eda6d 100644 --- a/RogueLibsCore.Test/Tests/GiantAbility.cs +++ b/RogueLibsCore.Test/Tests/GiantAbility.cs @@ -7,37 +7,27 @@ namespace RogueLibsCore.Test { - public class GiantAbility : CustomAbility, IDoUpdate + public class GiantAbility : CustomAbility, IAbilityRechargeable { public static void Test() - { - RogueLibs.CreateCustomAbility() + => RogueLibs.CreateCustomAbility() .WithName(new CustomNameInfo("Giant")) .WithDescription(new CustomNameInfo("Transform into a giant and crush your enemies!")) .WithSprite(Properties.Resources.Batteries) .WithUnlock(new AbilityUnlock { UnlockCost = 15, CharacterCreationCost = 10, }); - } - - public override void SetupDetails() { } - public override string GetCountString() => recharge != 0f ? recharge.ToString() : base.GetCountString(); public override void OnAdded() { } - public override void OnHeld(OnAbilityHeldArgs e) { } - public override void OnReleased(OnAbilityReleasedArgs e) { } - public override void OnUpdated(OnAbilityUpdatedArgs e) { } - public override PlayfieldObject FindTarget() => null; - private float recharge; - public void Update() => recharge = Mathf.Max(recharge - Time.deltaTime, 0f); + public void OnRecharge(OnAbilityRechargingArgs e) => e.UpdateDelay = 1f; public override void OnPressed() { - if (recharge > 0f) return; - - Owner.statusEffects.AddStatusEffect("Giant", 15); - Owner.statusEffects.AddStatusEffect("Enraged", 15); - - recharge = 30f; + if (Count == 0) + { + Owner.statusEffects.AddStatusEffect("Giant", 10); + Owner.statusEffects.AddStatusEffect("Enraged", 10); + Count = 20; + } } } } diff --git a/RogueLibsCore.Test/Tests/Hug.cs b/RogueLibsCore.Test/Tests/Hug.cs new file mode 100644 index 000000000..466b5525c --- /dev/null +++ b/RogueLibsCore.Test/Tests/Hug.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using static UnityEngine.GraphicsBuffer; + +namespace RogueLibsCore.Test +{ + public class Hug : CustomAbility, IAbilityTargetable + { + public static void Test() + { + RogueLibs.CreateCustomAbility() + .WithName(new CustomNameInfo("Hug")) + .WithDescription(new CustomNameInfo("Sneak up behind people. And HUG THEM!!")) + .WithSprite(Properties.Resources.Hug) + .WithUnlock(new AbilityUnlock { UnlockCost = 5, CharacterCreationCost = 5, }); + RogueLibs.CreateCustomName("HugNegative1", "Dialogue", new CustomNameInfo("Huh? What are you doing?")); + RogueLibs.CreateCustomName("HugNegative2", "Dialogue", new CustomNameInfo("Excuse me?!")); + RogueLibs.CreateCustomName("HugNegative3", "Dialogue", new CustomNameInfo("Stop it!")); + RogueLibs.CreateCustomName("HugPositive1", "Dialogue", new CustomNameInfo("Oh.. Thanks.")); + RogueLibs.CreateCustomName("HugPositive2", "Dialogue", new CustomNameInfo("Um.. Okay..")); + RogueLibs.CreateCustomName("HugPositive3", "Dialogue", new CustomNameInfo("?..")); + RogueLibs.CreateCustomName("HugForgive1", "Dialogue", new CustomNameInfo("Oh.. Okay, I forgive you.")); + RogueLibs.CreateCustomName("HugForgive2", "Dialogue", new CustomNameInfo("Alright, I forgive you.")); + RogueLibs.CreateCustomName("HugForgive3", "Dialogue", new CustomNameInfo("Okay... Don't worry about that..")); + } + + public override void OnAdded() { } + public PlayfieldObject FindTarget() + { + Agent closest = null; + float distance = float.MaxValue; + foreach (Agent agent in Owner.interactionHelper.TriggerList + .Where(go => go.CompareTag("AgentSprite")).Select(go => go.GetComponent().agent)) + { + if (!huggedList.Contains(agent) && !agent.dead && !agent.ghost && !Owner.ghost && !agent.hologram && agent.go.activeSelf && !agent.mechFilled && !agent.mechEmpty) + { + float dist = Vector2.Distance(Owner.curPosition, agent.curPosition); + if (dist < distance) + { + closest = agent; + distance = dist; + } + } + } + return closest; + } + private readonly List huggedList = new List(); + public override void OnPressed() + { + if (CurrentTarget is null) + { + gc.audioHandler.Play(Owner, "CantDo"); +} + else + { + Agent target = (Agent)CurrentTarget; + int rnd = new System.Random().Next(3) + 1; + + relStatus code = target.relationships.GetRelCode(Owner); + if (code == relStatus.Friendly || code == relStatus.Submissive) + { + target.SayDialogue("HugPositive" + rnd); + target.relationships.SetRel(Owner, "Loyal"); + } + else if (code == relStatus.Loyal) + { + target.SayDialogue("HugPositive" + rnd); + target.relationships.SetRel(Owner, "Aligned"); + } + else if (code == relStatus.Aligned) + { + target.SayDialogue("HugPositive" + rnd); + } + else if (code == relStatus.Neutral) + { + target.SayDialogue("HugNegative" + rnd); + target.relationships.SetRel(Owner, "Annoyed"); + target.relationships.SetStrikes(Owner, 2); + target.statusEffects.annoyeders.Add(Owner); + gc.audioHandler.Play(target, "AgentAnnoyed"); + return; + } + else if (code == relStatus.Annoyed) + { + target.SayDialogue("HugForgive" + rnd); + target.relationships.SetRel(Owner, "Neutral"); + } + else if (code == relStatus.Hostile) + { + return; + } + target.relationships.SetStrikes(Owner, 0); + gc.audioHandler.Play(target, "AgentOK"); + huggedList.Add(target); + } + } + } +} diff --git a/RogueLibsCore.Test/Tests/Smoker.cs b/RogueLibsCore.Test/Tests/Smoker.cs index 8a78dfda5..8c357d17f 100644 --- a/RogueLibsCore.Test/Tests/Smoker.cs +++ b/RogueLibsCore.Test/Tests/Smoker.cs @@ -3,10 +3,11 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using static UnityEngine.GraphicsBuffer; namespace RogueLibsCore.Test { - public class Smoker : CustomTrait + public class Smoker : CustomTrait, ITraitUpdateable { public static void Test() { @@ -22,7 +23,6 @@ public static void Test() public override void OnAdded() { - RogueFramework.LogDebug(""); Owner.SetEndurance(Owner.enduranceStatMod - 1); Owner.SetSpeed(Owner.speedStatMod - 1); } @@ -31,7 +31,7 @@ public override void OnRemoved() Owner.SetEndurance(Owner.enduranceStatMod + 1); Owner.SetSpeed(Owner.speedStatMod + 1); } - public override void OnUpdated(TraitUpdatedArgs e) + public void OnUpdated(TraitUpdatedArgs e) { e.UpdateDelay = 5f; @@ -40,6 +40,7 @@ public override void OnUpdated(TraitUpdatedArgs e) { rnd = new Random().Next(3) + 1; Owner.SayDialogue($"Smoker_Cough{rnd}"); + gc.audioHandler.Play(Owner, "AgentAnnoyed"); Noise noise = gc.spawnerMain.SpawnNoise(Owner.tr.position, 1f, Owner, "Attract", Owner); noise.distraction = true; diff --git a/RogueLibsCore/Hooks/Items/CustomAbility.cs b/RogueLibsCore/Hooks/Items/CustomAbility.cs index f8d5e6aae..2139b4a8d 100644 --- a/RogueLibsCore/Hooks/Items/CustomAbility.cs +++ b/RogueLibsCore/Hooks/Items/CustomAbility.cs @@ -8,15 +8,23 @@ namespace RogueLibsCore { public abstract class CustomAbility : CustomItem { + public override void SetupDetails() + { + Item.stackable = true; + Item.initCount = 0; + Item.lowCountThreshold = 100; + } + public abstract void OnAdded(); public abstract void OnPressed(); - public abstract void OnHeld(OnAbilityHeldArgs e); - public abstract void OnReleased(OnAbilityReleasedArgs e); - public abstract void OnUpdated(OnAbilityUpdatedArgs e); internal float lastHeld; public PlayfieldObject CurrentTarget { get; internal set; } - public abstract PlayfieldObject FindTarget(); + } + public interface IAbilityChargeable + { + void OnHeld(OnAbilityHeldArgs e); + void OnReleased(OnAbilityReleasedArgs e); } public class OnAbilityHeldArgs : EventArgs { @@ -28,8 +36,16 @@ public class OnAbilityReleasedArgs : EventArgs public OnAbilityReleasedArgs(float heldTime) => HeldTime = heldTime; public float HeldTime { get; } } - public class OnAbilityUpdatedArgs : EventArgs + public class OnAbilityRechargingArgs : EventArgs + { + public float UpdateDelay { get; set; } + } + public interface IAbilityRechargeable + { + void OnRecharge(OnAbilityRechargingArgs e); + } + public interface IAbilityTargetable { - public float NextDelay { get; set; } + PlayfieldObject FindTarget(); } } diff --git a/RogueLibsCore/Hooks/Traits/CustomTrait.cs b/RogueLibsCore/Hooks/Traits/CustomTrait.cs index e62883f70..d6dd0515f 100644 --- a/RogueLibsCore/Hooks/Traits/CustomTrait.cs +++ b/RogueLibsCore/Hooks/Traits/CustomTrait.cs @@ -21,7 +21,10 @@ public abstract class CustomTrait : HookBase public abstract void OnAdded(); public abstract void OnRemoved(); - public abstract void OnUpdated(TraitUpdatedArgs e); + } + public interface ITraitUpdateable + { + void OnUpdated(TraitUpdatedArgs e); } public class TraitUpdatedArgs : EventArgs { diff --git a/RogueLibsCore/Patches/Patches_Abilities.cs b/RogueLibsCore/Patches/Patches_Abilities.cs index 6c53e44c3..2f3ab9f66 100644 --- a/RogueLibsCore/Patches/Patches_Abilities.cs +++ b/RogueLibsCore/Patches/Patches_Abilities.cs @@ -21,6 +21,11 @@ public void PatchAbilities() Patcher.Postfix(typeof(StatusEffects), nameof(StatusEffects.HeldSpecialAbility)); Patcher.Postfix(typeof(StatusEffects), nameof(StatusEffects.ReleasedSpecialAbility)); + Patcher.Prefix(typeof(StatusEffects), "RechargeSpecialAbility2"); + Patcher.Prefix(typeof(StatusEffects), "SpecialAbilityInterfaceCheck2"); + + Patcher.Postfix(typeof(SpecialAbilityIndicator), nameof(SpecialAbilityIndicator.ShowIndicator), + new Type[3] { typeof(PlayfieldObject), typeof(string), typeof(string) }); } public static void StatusEffects_GiveSpecialAbility(StatusEffects __instance) @@ -36,8 +41,10 @@ public static void StatusEffects_GiveSpecialAbility(StatusEffects __instance) try { custom.OnAdded(); } catch (Exception e) { RogueFramework.LogError(e, "CustomAbility.OnAdded", custom, __instance.agent); } - __instance.SpecialAbilityInterfaceCheck(); - __instance.RechargeSpecialAbility(custom.ItemInfo.Name); + if (custom is IAbilityTargetable) + __instance.SpecialAbilityInterfaceCheck(); + if (custom is IAbilityRechargeable) + __instance.RechargeSpecialAbility(custom.ItemInfo.Name); } public static void StatusEffects_PressedSpecialAbility(StatusEffects __instance) @@ -50,11 +57,13 @@ public static void StatusEffects_PressedSpecialAbility(StatusEffects __instance) try { custom.OnPressed(); } catch (Exception e) { RogueFramework.LogError(e, "CustomAbility.OnPressed", custom, __instance.agent); } + if (custom.Count > 0) + __instance.agent.inventory.buffDisplay.specialAbilitySlot.MakeNotUsable(); } public static void StatusEffects_HeldSpecialAbility(StatusEffects __instance) { CustomAbility custom = __instance.agent.GetAbility(); - if (custom is null) return; + if (!(custom is IAbilityChargeable chargeable)) return; ref float held = ref GameController.gameController.playerControl.pressedSpecialAbilityTime[__instance.agent.isPlayer - 1]; float prevHeld = held; @@ -63,17 +72,18 @@ public static void StatusEffects_HeldSpecialAbility(StatusEffects __instance) RogueFramework.LogDebug($"Holding ability {custom} for {prevHeld}s ({__instance.agent.specialAbility}, {__instance.agent.agentName})."); OnAbilityHeldArgs args = new OnAbilityHeldArgs { HeldTime = prevHeld }; - try { custom.OnHeld(args); } + try { chargeable.OnHeld(args); } catch (Exception e) { RogueFramework.LogError(e, "CustomAbility.OnHeld", custom, __instance.agent); } held = args.HeldTime; custom.lastHeld = prevHeld; - __instance.ReleasedSpecialAbility(); + if (held == 0f) + __instance.ReleasedSpecialAbility(); } public static void StatusEffects_ReleasedSpecialAbility(StatusEffects __instance) { CustomAbility custom = __instance.agent.GetAbility(); - if (custom is null) return; + if (!(custom is IAbilityChargeable chargeable)) return; float prevHeld = custom.lastHeld; if (prevHeld is 0f) return; @@ -82,8 +92,88 @@ public static void StatusEffects_ReleasedSpecialAbility(StatusEffects __instance RogueFramework.LogDebug($"Releasing ability {custom} - {prevHeld}s ({__instance.agent.specialAbility}, {__instance.agent.agentName})."); custom.lastHeld = 0f; - try { custom.OnReleased(new OnAbilityReleasedArgs(prevHeld)); } + try { chargeable.OnReleased(new OnAbilityReleasedArgs(prevHeld)); } catch (Exception e) { RogueFramework.LogError(e, "CustomAbility.OnReleased", custom, __instance.agent); } } + + public static bool StatusEffects_RechargeSpecialAbility2(StatusEffects __instance, ref IEnumerator __result) + { + CustomAbility custom = __instance.agent.inventory.equippedSpecialAbility.GetHook(); + if (!(custom is IAbilityRechargeable)) return true; + if (RogueFramework.IsDebugEnabled(DebugFlags.Abilities)) + RogueFramework.LogDebug($"Starting {custom} recharge coroutine ({custom.Item.invItemName}, {__instance.agent.agentName})."); + __result = AbilityRechargeEnumerator(__instance, custom); + return false; + } + public static IEnumerator AbilityRechargeEnumerator(StatusEffects __instance, CustomAbility ability) + { + __instance.startedRechargeSpecialAbility = true; + __instance.rechargesSpecialAbility = true; + float countSpeed = 1f; + while (__instance.agent.inventory.equippedSpecialAbility == ability.Item) + { + InvItem item = __instance.agent.inventory.equippedSpecialAbility; + if (item.invItemCount > 0) + { + OnAbilityRechargingArgs args = new OnAbilityRechargingArgs() { UpdateDelay = countSpeed }; + ((IAbilityRechargeable)ability).OnRecharge(args); + countSpeed = args.UpdateDelay; + + yield return countSpeed > 0 ? new WaitForSeconds(countSpeed) : null; + + if (__instance.agent.inventory.equippedSpecialAbility != ability.Item) break; + if (item.invItemCount > 0 && __instance.CanRecharge() && --item.invItemCount == 0) + { + __instance.CreateBuffText("Recharged", __instance.agent.objectNetID); + GameController.gameController.audioHandler.Play(__instance.agent, "Recharge"); + if (!(ability is IAbilityTargetable)) + __instance.agent.inventory.buffDisplay?.specialAbilitySlot.MakeUsable(); + } + } + else yield return null; + } + __instance.startedRechargeSpecialAbility = false; + __instance.rechargesSpecialAbility = false; + } + + public static bool StatusEffects_SpecialAbilityInterfaceCheck2(StatusEffects __instance, ref IEnumerator __result) + { + CustomAbility custom = __instance.agent.inventory.equippedSpecialAbility.GetHook(); + if (!(custom is IAbilityTargetable)) return true; + if (RogueFramework.IsDebugEnabled(DebugFlags.Abilities)) + RogueFramework.LogDebug($"Starting {custom} indicator coroutine ({custom.Item.invItemName}, {__instance.agent.agentName})."); + __result = AbilityIndicatorEnumerator(__instance, custom); + return false; + } + public static IEnumerator AbilityIndicatorEnumerator(StatusEffects __instance, CustomAbility ability) + { + __instance.startedSpecialAbilityInterfaceCheck = true; + while (__instance.agent.inventory.equippedSpecialAbility == ability.Item) + { + InvItem item = __instance.agent.inventory.equippedSpecialAbility; + + ability.CurrentTarget = ((IAbilityTargetable)ability).FindTarget(); + + if (GameController.gameController.loadComplete && __instance.agent.specialAbilityIndicator != null && !__instance.agent.disappearedArcade && __instance.agent.inventory.buffDisplay.specialAbilitySlot != null && !__instance.agent.ghost) + { + if ((item.invItemCount == 0 || !(ability is IAbilityRechargeable)) && __instance.CanShowSpecialAbilityIndicator() + && ability.CurrentTarget != null) + { + __instance.agent.specialAbilityIndicator.ShowIndicator(ability.CurrentTarget, ability.Item.invItemName); + __instance.agent.inventory.buffDisplay.specialAbilitySlot.MakeUsable(); + } + else + { + __instance.agent.specialAbilityIndicator.Revert(); + } + } + yield return new WaitForSeconds(0.1f); + } + __instance.startedSpecialAbilityInterfaceCheck = false; + } + + public static void SpecialAbilityIndicator_ShowIndicator(SpecialAbilityIndicator __instance, string specialAbilityType) + => __instance.image.sprite = GameController.gameController.gameResources.itemDic + .TryGetValue(specialAbilityType, out Sprite sprite) ? sprite : null; } } diff --git a/RogueLibsCore/Patches/Patches_Misc.cs b/RogueLibsCore/Patches/Patches_Misc.cs index ccc5daff7..fcfbccb15 100644 --- a/RogueLibsCore/Patches/Patches_Misc.cs +++ b/RogueLibsCore/Patches/Patches_Misc.cs @@ -24,6 +24,9 @@ public void PatchMisc() Patcher.Postfix(typeof(Updater), "Update"); // IDoFixedUpdate.FixedUpdate Patcher.Postfix(typeof(Updater), nameof(Updater.FixedUpdate)); + + // remove 99 nuggets limit + Patcher.Prefix(typeof(Unlocks), nameof(Unlocks.AddNuggets)); } public static void NameDB_RealAwake(NameDB __instance) @@ -145,5 +148,12 @@ public static void Updater_FixedUpdate() try { obj.FixedUpdate(); } catch (Exception e) { RogueFramework.LogError(e, "IDoFixedUpdate.FixedUpdate", obj, item); } } + + public static bool Unlocks_AddNuggets(int numNuggets) + { + GameController.gameController.sessionDataBig.nuggets += numNuggets; + GameController.gameController.unlocks.SaveUnlockData(true); + return false; + } } } diff --git a/RogueLibsCore/Patches/Patches_Sprites.cs b/RogueLibsCore/Patches/Patches_Sprites.cs index 81c4f6c0b..240336a82 100644 --- a/RogueLibsCore/Patches/Patches_Sprites.cs +++ b/RogueLibsCore/Patches/Patches_Sprites.cs @@ -31,6 +31,9 @@ public void PatchSprites() Patcher.Postfix(typeof(Item), nameof(Item.DestroyMe2)); Patcher.Postfix(typeof(Item), nameof(Item.FakeStart)); Patcher.Postfix(typeof(Melee), nameof(Melee.MeleeLateUpdate)); + + // Nugget slot image + Patcher.Postfix(typeof(NuggetSlot), nameof(NuggetSlot.UpdateNuggetText)); } public static void GameController_Awake(GameController __instance) @@ -200,5 +203,9 @@ public static void Melee_MeleeLateUpdate(Melee __instance) RogueSprite sprite = (RogueSprite)hb.heldItem2?.CurrentSprite?.__RogueLibsCustom; if (sprite != null) hb.heldItem2Renderer.sharedMaterial = sprite.Material; } + + public static void NuggetSlot_UpdateNuggetText(Image ___itemImage) + => ___itemImage.sprite = GameController.gameController.gameResources.itemDic + .TryGetValue("Nugget", out Sprite sprite) ? sprite : null; } } diff --git a/RogueLibsCore/Patches/Patches_TraitsStatusEffects.cs b/RogueLibsCore/Patches/Patches_TraitsStatusEffects.cs index f453decb8..3420f28a4 100644 --- a/RogueLibsCore/Patches/Patches_TraitsStatusEffects.cs +++ b/RogueLibsCore/Patches/Patches_TraitsStatusEffects.cs @@ -120,7 +120,7 @@ public static IEnumerable StatusEffects_AddTrait(IEnumerable factory in RogueFramework.TraitFactories) if (factory.TryCreate(trait, out IHook hook)) @@ -133,10 +133,11 @@ public static void SetupTraitHook(Trait trait, StatusEffects parent) } trait.AddHook(hook); hook.Initialize(); - any = true; + if (hook is CustomTrait && hook is ITraitUpdateable) + updateable = true; } - if (any && parent.agent.name != "DummyAgent" && !parent.agent.name.Contains("Backup")) + if (updateable && parent.agent.name != "DummyAgent" && !parent.agent.name.Contains("Backup")) { parent.StartCoroutine(parent.UpdateTrait(trait)); trait.requiresUpdates = true; @@ -265,7 +266,7 @@ public static IEnumerator StatusEffectUpdateEnumerator(StatusEffects __instance, public static bool StatusEffects_UpdateTrait(StatusEffects __instance, Trait myTrait, ref IEnumerator __result) { CustomTrait custom = myTrait.GetHook(); - if (custom is null) return true; + if (!(custom is ITraitUpdateable)) return true; if (RogueFramework.IsDebugEnabled(DebugFlags.Effects)) RogueFramework.LogDebug($"Starting {custom} update coroutine ({myTrait.traitName}, {myTrait.GetStatusEffects().agent.agentName})."); __result = TraitUpdateEnumerator(__instance, custom); @@ -284,7 +285,7 @@ public static IEnumerator TraitUpdateEnumerator(StatusEffects __instance, Custom if (GameController.gameController.loadComplete && !GameController.gameController.mainGUI.questNotification.gameIsOver && !__instance.agent.disappearedArcade) { TraitUpdatedArgs e = new TraitUpdatedArgs { UpdateDelay = countSpeed }; - customTrait.OnUpdated(e); + ((ITraitUpdateable)customTrait).OnUpdated(e); countSpeed = e.UpdateDelay; } yield return countSpeed > 0 ? new WaitForSeconds(countSpeed) : null;