-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #306 from divisionbyz0rro/slot-modification-manager
Slot Modification Manager
- Loading branch information
Showing
10 changed files
with
952 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using GBC; | ||
|
||
namespace InscryptionAPI.Encounters; | ||
|
||
public class CachedGCBNPCDescriptor | ||
{ | ||
public string ID { get; set; } | ||
public CardTemple BossTemple { get; set; } | ||
public bool IsBoss { get; set; } | ||
public PixelBoardSpriteSetter.BoardTheme BattleBackgroundTheme { get; set; } | ||
public DialogueSpeaker DialogueSpeaker { get; set; } | ||
|
||
public CachedGCBNPCDescriptor(CardBattleNPC npc) | ||
{ | ||
ID = npc.ID; | ||
BossTemple = npc.BossTemple; | ||
IsBoss = npc.IsBoss; | ||
BattleBackgroundTheme = npc.BattleBackgroundTheme; | ||
DialogueSpeaker = npc.DialogueSpeaker; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using GBC; | ||
using InscryptionAPI.Encounters; | ||
using UnityEngine.SceneManagement; | ||
|
||
namespace InscryptionAPI.Saves; | ||
|
||
public static class SaveFileExtensions | ||
{ | ||
/// <summary> | ||
/// Gets the player's current location as a CardTemple | ||
/// </summary> | ||
/// <returns>The temple of the player's current location OR null if the player is in an ambiguous location</returns> | ||
public static CardTemple? GetSceneAsCardTemple(this SaveFile save) | ||
{ | ||
// Easy stuff | ||
if (save.IsGrimora) | ||
return CardTemple.Undead; | ||
if (save.IsMagnificus) | ||
return CardTemple.Wizard; | ||
if (save.IsPart1) | ||
return CardTemple.Nature; | ||
if (save.IsPart3) | ||
return CardTemple.Tech; | ||
|
||
// Now the hard part; if this is Act 2 | ||
if (save.IsPart2) | ||
{ | ||
// If there is an active battle, we should be able to get it from the NPC | ||
var npc = GBCEncounterManager.Instance.GetTriggeringNPC(); | ||
if (npc != null) | ||
{ | ||
// Translate the theme to a card temlpe | ||
if (npc.BattleBackgroundTheme == PixelBoardSpriteSetter.BoardTheme.Nature) | ||
return CardTemple.Nature; | ||
if (npc.BattleBackgroundTheme == PixelBoardSpriteSetter.BoardTheme.Tech) | ||
return CardTemple.Tech; | ||
if (npc.BattleBackgroundTheme == PixelBoardSpriteSetter.BoardTheme.P03) | ||
return CardTemple.Tech; | ||
if (npc.BattleBackgroundTheme == PixelBoardSpriteSetter.BoardTheme.Undead) | ||
return CardTemple.Undead; | ||
if (npc.BattleBackgroundTheme == PixelBoardSpriteSetter.BoardTheme.Wizard) | ||
return CardTemple.Wizard; | ||
|
||
// A bit of an arbitrary choice here for "finale" | ||
// P03 takes over so... | ||
if (npc.BattleBackgroundTheme == PixelBoardSpriteSetter.BoardTheme.Finale) | ||
return CardTemple.Tech; | ||
} | ||
|
||
// Okay, let's try to figure it out from the scene name | ||
string sceneName = SceneManager.GetActiveScene().name.ToLowerInvariant(); | ||
if (sceneName.Contains("nature")) | ||
return CardTemple.Nature; | ||
if (sceneName.Contains("tech")) | ||
return CardTemple.Tech; | ||
if (sceneName.Contains("wizard")) | ||
return CardTemple.Wizard; | ||
if (sceneName.Contains("undead")) | ||
return CardTemple.Undead; | ||
} | ||
|
||
// And now we're at the point where there's no way to figure it out. | ||
// You're either in a neutral area of the Act 2 map | ||
// Or you're not in a game scene at all. | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System.Collections; | ||
using DiskCardGame; | ||
|
||
namespace InscryptionAPI.Slots; | ||
|
||
/// <summary> | ||
/// Base class for all slot modification behaviors | ||
/// </summary> | ||
public abstract class SlotModificationBehaviour : TriggerReceiver | ||
{ | ||
/// <summary> | ||
/// The slot that the behaviour is applied to. | ||
/// </summary> | ||
public CardSlot Slot => gameObject.GetComponent<CardSlot>(); | ||
|
||
/// <summary> | ||
/// Use to setup any additional custom slot visualizations when created. | ||
/// </summary> | ||
public virtual IEnumerator Setup() | ||
{ | ||
yield break; | ||
} | ||
|
||
/// <summary> | ||
/// Use to clean up any additional custom slot visualizations before being removed | ||
/// </summary> | ||
public virtual IEnumerator Cleanup(SlotModificationManager.ModificationType replacement) | ||
{ | ||
yield break; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
using System.Collections; | ||
using DiskCardGame; | ||
using GBC; | ||
using HarmonyLib; | ||
using InscryptionAPI.Encounters; | ||
using InscryptionAPI.Helpers.Extensions; | ||
using InscryptionAPI.Saves; | ||
using UnityEngine; | ||
using UnityEngine.UIElements; | ||
|
||
namespace InscryptionAPI.Slots; | ||
|
||
[HarmonyPatch] | ||
/// <summary> | ||
/// Contains extension methods to simplify slot modification management | ||
/// </summary> | ||
public static class SlotModificationExtensions | ||
{ | ||
/// <summary> | ||
/// Assigns a new slot modification to a slot. | ||
/// </summary> | ||
/// <param name="slot">The slot to assign the modification to</param> | ||
/// <param name="modType">The modification type to assign</param> | ||
public static IEnumerator SetSlotModification(this CardSlot slot, SlotModificationManager.ModificationType modType) | ||
{ | ||
if (slot == null) | ||
yield break; | ||
|
||
SlotModificationManager.Info defn = SlotModificationManager.AllSlotModifications.FirstOrDefault(m => m.ModificationType == modType); | ||
|
||
// Set the ability behaviour | ||
var oldSlotModification = slot.GetComponent<SlotModificationBehaviour>(); | ||
if (oldSlotModification != null) | ||
{ | ||
yield return oldSlotModification.Cleanup(modType); | ||
CustomCoroutine.WaitOnConditionThenExecute(() => GlobalTriggerHandler.Instance.StackSize == 0, () => GameObject.Destroy(oldSlotModification)); | ||
SlotModificationManager.Instance.SlotReceivers.Remove(slot); | ||
} | ||
|
||
if (defn != null && defn.SlotBehaviour != null) | ||
{ | ||
SlotModificationBehaviour newBehaviour = slot.gameObject.AddComponent(defn.SlotBehaviour) as SlotModificationBehaviour; | ||
|
||
SlotModificationManager.Instance.SlotReceivers[slot] = new(modType, newBehaviour); | ||
yield return newBehaviour.Setup(); | ||
} | ||
|
||
// Set the texture and/or sprite | ||
CardTemple temple = SaveManager.SaveFile.GetSceneAsCardTemple() ?? CardTemple.Nature; | ||
|
||
if (defn == null) | ||
{ | ||
slot.ResetSlotTexture(); | ||
} | ||
else if (slot is PixelCardSlot pcs) | ||
{ | ||
pcs.SetSlotSprite(defn); | ||
} | ||
else | ||
{ | ||
if (defn.Texture == null || !defn.Texture.ContainsKey(temple)) | ||
slot.ResetSlotTexture(); | ||
else | ||
slot.SetTexture(defn.Texture[temple]); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Gets the current modification of a slot | ||
/// </summary> | ||
public static SlotModificationManager.ModificationType GetSlotModification(this CardSlot slot) | ||
{ | ||
return slot == null | ||
? SlotModificationManager.ModificationType.NoModification | ||
: SlotModificationManager.Instance.SlotReceivers.ContainsKey(slot) | ||
? SlotModificationManager.Instance.SlotReceivers[slot].Item1 | ||
: SlotModificationManager.ModificationType.NoModification; | ||
} | ||
|
||
private static void SetSlotSprite(this PixelCardSlot slot, SlotModificationManager.Info defn) | ||
{ | ||
if (defn == null) | ||
{ | ||
InscryptionAPIPlugin.Logger.LogDebug($"Resetting slot {slot.Index} to default because mod info was null"); | ||
slot.ResetSlotSprite(); | ||
return; | ||
} | ||
|
||
if (defn.PixelBoardSlotSprites == null) | ||
{ | ||
InscryptionAPIPlugin.Logger.LogDebug($"Resetting slot {slot.Index} to default because mod info did not contain pixel slot info"); | ||
slot.ResetSlotSprite(); | ||
return; | ||
} | ||
|
||
var triggeringNPC = GBCEncounterManager.Instance?.GetTriggeringNPC(); | ||
if (triggeringNPC == null) | ||
{ | ||
InscryptionAPIPlugin.Logger.LogDebug($"Doing nothing to slot {slot.Index} because the triggering NPC was null"); | ||
return; | ||
} | ||
|
||
if (!defn.PixelBoardSlotSprites.ContainsKey(triggeringNPC.BattleBackgroundTheme)) | ||
{ | ||
InscryptionAPIPlugin.Logger.LogDebug($"Resetting slot {slot.Index} to default because pixel slot info did not contain a definition for {triggeringNPC.BattleBackgroundTheme}"); | ||
slot.ResetSlotSprite(); | ||
return; | ||
} | ||
|
||
var spriteSet = defn.PixelBoardSlotSprites[triggeringNPC.BattleBackgroundTheme]; | ||
if (spriteSet == null) | ||
{ | ||
InscryptionAPIPlugin.Logger.LogDebug($"Resetting slot {slot.Index} to default because pixel slot info had a null definition for {triggeringNPC.BattleBackgroundTheme}"); | ||
slot.ResetSlotSprite(); | ||
return; | ||
} | ||
|
||
var specificSprites = spriteSet.specificSlotSprites.Find(s => s.playerSlot == slot.IsPlayerSlot && s.index == slot.Index); | ||
|
||
if (specificSprites == null) | ||
slot.SetSprites(spriteSet.slotDefault, spriteSet.slotHighlight, slot.IsPlayerSlot && spriteSet.flipPlayerSlotSpriteY, false); | ||
else | ||
slot.SetSprites(specificSprites.slotDefault, specificSprites.slotHighlight, slot.IsPlayerSlot && spriteSet.flipPlayerSlotSpriteY, false); | ||
} | ||
|
||
private static void ResetSlotSprite(this PixelCardSlot slot) | ||
{ | ||
var triggeringNPC = GBCEncounterManager.Instance?.GetTriggeringNPC(); | ||
if (triggeringNPC == null) | ||
return; | ||
|
||
var spriteSet = PixelBoardSpriteSetter.Instance.themeSpriteSets.Find(s => s.id == triggeringNPC.BattleBackgroundTheme); | ||
if (spriteSet == null) | ||
return; | ||
|
||
var specificSprites = spriteSet.specificSlotSprites.Find(s => s.playerSlot == slot.IsPlayerSlot && s.index == slot.Index); | ||
|
||
if (specificSprites != null) | ||
slot.SetSprites(specificSprites.slotDefault, specificSprites.slotHighlight, slot.IsPlayerSlot && spriteSet.flipPlayerSlotSpriteY, false); | ||
else | ||
slot.SetSprites(spriteSet.slotDefault, spriteSet.slotHighlight, slot.IsPlayerSlot && spriteSet.flipPlayerSlotSpriteY, false); | ||
} | ||
|
||
/// <summary> | ||
/// Resets a slot's texture back to the default texture for that slot based on the current act. | ||
/// </summary> | ||
public static void ResetSlotTexture(this CardSlot slot) | ||
{ | ||
if (slot is PixelCardSlot pcs) | ||
{ | ||
pcs.ResetSlotSprite(); | ||
return; | ||
} | ||
|
||
CardTemple temple = SaveManager.SaveFile.GetSceneAsCardTemple() ?? CardTemple.Nature; | ||
|
||
Dictionary<CardTemple, List<Texture>> lookup = slot.IsOpponentSlot() ? SlotModificationManager.OpponentOverrideSlots : SlotModificationManager.PlayerOverrideSlots; | ||
var newTexture = SlotModificationManager.DefaultSlotTextures[temple]; | ||
if (lookup.ContainsKey(temple)) | ||
{ | ||
// Get the texture overrides | ||
var textureChoices = lookup[temple]; | ||
int idx = slot.Index; | ||
if (idx >= textureChoices.Count) | ||
{ | ||
// Try to guess what the best index would be | ||
int slotCount = BoardManager.Instance.PlayerSlotsCopy.Count; | ||
if (slot.Index == slotCount - 1) // the last slot | ||
idx = textureChoices.Count - 1; | ||
else // Use the next to last slot | ||
idx = textureChoices.Count - 2; | ||
} | ||
if (idx < 0) | ||
idx = 0; | ||
|
||
if (textureChoices[idx] != null) | ||
newTexture = textureChoices[idx]; | ||
} | ||
|
||
slot.SetTexture(newTexture); | ||
} | ||
} |
Oops, something went wrong.