Skip to content

Commit 67d56f7

Browse files
Additional Act-specific rulebook sprites for slot modifications
1 parent 7c6d553 commit 67d56f7

3 files changed

Lines changed: 181 additions & 77 deletions

File tree

InscryptionAPI/Slots/SlotModificationExtensions.cs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,42 @@ public static ModificationType SetRulebook(this ModificationType mod, string rul
4747
}
4848
return mod;
4949
}
50+
public static ModificationType SetRulebookP03Sprite(this ModificationType mod, Texture2D spriteTexture)
51+
{
52+
Info info = AllSlotModifications.InfoByID(mod);
53+
if (info != null)
54+
{
55+
info.P03RulebookSprite = spriteTexture.ConvertTexture();
56+
}
57+
return mod;
58+
}
59+
public static ModificationType SetRulebookGrimoraSprite(this ModificationType mod, Texture2D spriteTexture)
60+
{
61+
Info info = AllSlotModifications.InfoByID(mod);
62+
if (info != null)
63+
{
64+
info.GrimoraRulebookSprite = spriteTexture.ConvertTexture();
65+
}
66+
return mod;
67+
}
68+
public static ModificationType SetRulebookMagnificusSprite(this ModificationType mod, Texture2D spriteTexture)
69+
{
70+
Info info = AllSlotModifications.InfoByID(mod);
71+
if (info != null)
72+
{
73+
info.MagnificusRulebookSprite = spriteTexture.ConvertTexture();
74+
}
75+
return mod;
76+
}
77+
public static ModificationType SetSharedRulebook(this ModificationType mod, ModificationType sharedRulebookType)
78+
{
79+
Info info = AllSlotModifications.InfoByID(mod);
80+
if (info != null)
81+
{
82+
info.SharedRulebook = sharedRulebookType;
83+
}
84+
return mod;
85+
}
5086

5187
/// <summary>
5288
/// Assigns a new slot modification to a slot.
@@ -60,18 +96,18 @@ public static IEnumerator SetSlotModification(this CardSlot slot, ModificationTy
6096

6197
Info defn = AllModificationInfos.InfoByID(modType);
6298
SlotModificationInteractable interactable = slot.GetComponent<SlotModificationInteractable>();
63-
if (defn.RulebookName != null)
99+
if (defn == null || modType == ModificationType.NoModification || (defn.SharedRulebook == ModificationType.NoModification && string.IsNullOrEmpty(defn.RulebookName)))
64100
{
65-
interactable ??= slot.gameObject.AddComponent<SlotModificationInteractable>();
66-
interactable.AssignSlotModification(modType, slot);
101+
interactable?.SetEnabled(false);
67102
}
68103
else
69104
{
70-
interactable?.SetEnabled(false);
105+
interactable ??= slot.gameObject.AddComponent<SlotModificationInteractable>();
106+
interactable.AssignSlotModification(defn.SharedRulebook != ModificationType.NoModification ? defn.SharedRulebook : modType, slot);
71107
}
72108

73109
// Set the ability behaviour
74-
var oldSlotModification = slot.GetComponent<SlotModificationBehaviour>();
110+
SlotModificationBehaviour oldSlotModification = slot.GetComponent<SlotModificationBehaviour>();
75111
if (oldSlotModification != null)
76112
{
77113
yield return oldSlotModification.Cleanup(modType);

InscryptionAPI/Slots/SlotModificationInteractable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ public void AssignSlotModification(SlotModificationManager.ModificationType modT
2222
public override void OnAlternateSelectStarted()
2323
{
2424
//InscryptionAPIPlugin.Logger.LogDebug($"Open to slot mod page: [{ModType}] on slot [{slot}]");
25-
RuleBookController.Instance.OpenToItemPage(SlotModificationManager.SLOT_PAGEID + (int)ModType, true);
25+
RuleBookController.Instance.OpenToItemPage(SlotModificationManager.SLOT_PAGEID + (int)ModType, false);
2626
}
2727
}

InscryptionAPI/Slots/SlotModificationManager.cs

Lines changed: 139 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -23,34 +23,6 @@ namespace InscryptionAPI.Slots;
2323
[HarmonyPatch]
2424
public class SlotModificationManager : MonoBehaviour
2525
{
26-
private static SlotModificationManager m_instance;
27-
28-
/// <summary>
29-
/// Singleton instance for the SlotModificationManager.
30-
/// </summary>
31-
public static SlotModificationManager Instance
32-
{
33-
get
34-
{
35-
if (m_instance != null)
36-
return m_instance;
37-
38-
Instantiate();
39-
return m_instance;
40-
}
41-
set => m_instance = value;
42-
}
43-
44-
private static void Instantiate()
45-
{
46-
if (m_instance != null)
47-
return;
48-
49-
GameObject slotModManager = new("SlotModificationManager");
50-
slotModManager.transform.SetParent(BoardManager.Instance.gameObject.transform);
51-
m_instance = slotModManager.AddComponent<SlotModificationManager>();
52-
}
53-
5426
/// <summary>
5527
/// Unique identifiers for slot modifications.
5628
/// </summary>
@@ -59,18 +31,6 @@ public enum ModificationType
5931
NoModification = 0
6032
}
6133

62-
/// <summary>
63-
/// Used to determine what Acts a modification's rulebook entry should appear in.
64-
/// Values correspond to specific AbilityMetaCategory values.
65-
/// </summary>
66-
public enum ModificationMetaCategory
67-
{
68-
Part1Rulebook = 0,
69-
Part3Rulebook = 2,
70-
GrimoraRulebook = 5,
71-
MagnificusRulebook = 6
72-
}
73-
7434
/// <summary>
7535
/// Contains information about a slot modification.
7636
/// </summary>
@@ -95,11 +55,26 @@ public class Info
9555
public string RulebookDescription { get; set; }
9656

9757
/// <summary>
98-
/// If this slot modification can appear in the rulebook, this will be the sprite displayed.
99-
/// Texture should have the dimensions 154 x 226; if the sprite is null then the rulebook entry will use the first entry in Texture as a sprite.
58+
/// The sprite to use for the rulebook entry. If this is null, the API will use the first slot value in the Texture dictionary.
10059
/// </summary>
10160
public Sprite RulebookSprite { get; set; }
61+
/// <summary>
62+
/// Set using SetRulebookP03Sprite if you want your slot to have a different rulebook sprite in Act 3 than in other acts.
63+
/// </summary>
64+
public Sprite P03RulebookSprite { get; set; } = null;
65+
/// <summary>
66+
/// Set using SetRulebookGrimoraSprite if you want your slot to have a different rulebook sprite in Grimora's Act than in other acts.
67+
/// </summary>
68+
public Sprite GrimoraRulebookSprite { get; set; } = null;
69+
/// <summary>
70+
/// Set using SetRulebookMagnificusSprite if you want your slot to have a different rulebook sprite in Magnificus's Act than in other acts.
71+
/// </summary>
72+
public Sprite MagnificusRulebookSprite { get; set; } = null;
10273

74+
/// <summary>
75+
/// The slot modification whose rulebook entry is also used by this slot modification.
76+
/// </summary>
77+
public ModificationType SharedRulebook { get; set; } = ModificationType.NoModification;
10378
public List<ModificationMetaCategory> MetaCategories = new();
10479

10580
/// <summary>
@@ -161,7 +136,11 @@ public Info Clone()
161136
this.MetaCategories
162137
)
163138
{
164-
RulebookDescriptionRedirects = new(this.RulebookDescriptionRedirects)
139+
RulebookDescriptionRedirects = new(this.RulebookDescriptionRedirects),
140+
SharedRulebook = this.SharedRulebook,
141+
P03RulebookSprite = this.P03RulebookSprite,
142+
GrimoraRulebookSprite = this.GrimoraRulebookSprite,
143+
MagnificusRulebookSprite = this.MagnificusRulebookSprite
165144
};
166145
}
167146
}
@@ -386,9 +365,9 @@ private static PixelBoardSpriteSetter.BoardThemeSpriteSet GetSpriteSetFromTextur
386365
/// </summary>
387366
/// <param name="texture"></param>
388367
/// <remarks>This expects a texture with 8 slot textures in it, arranged in either 2 or 4 rows of 5. Each slot texture is 44x58.
389-
/// The first row contains all of the the normal slot sprites and the second row contains all of the hover sprites.
368+
/// The first/bottom-most row contains all of the the normal slot sprites and the second row contains all of the hover sprites.
390369
/// If you want the opponent sprites to be different, you have to provide 4 rows; the third row contains normal opponent slot sprites and the fourth row contains hovered opponent slot sprites.
391-
/// Each row must go in this order: nature, undead, tech, wizard, finale.
370+
/// Each row must go in this order from left to right: Nature, Undead, Tech, Wizard, Finale.
392371
public static Dictionary<PixelBoardSpriteSetter.BoardTheme, PixelBoardSpriteSetter.BoardThemeSpriteSet> BuildAct2SpriteSetFromSpriteSheetTexture(Texture2D texture)
393372
{
394373
Dictionary<PixelBoardSpriteSetter.BoardTheme, PixelBoardSpriteSetter.BoardThemeSpriteSet> retval = new();
@@ -480,6 +459,45 @@ public static void ResetDefaultSlotTexture(CardTemple temple)
480459
ConditionallyResetAllSlotTextures();
481460
}
482461

462+
/// <summary>
463+
/// Used to determine what Acts a modification's rulebook entry should appear in.
464+
/// Values correspond to specific AbilityMetaCategory values.
465+
/// </summary>
466+
public enum ModificationMetaCategory
467+
{
468+
Part1Rulebook = 0,
469+
Part3Rulebook = 2,
470+
GrimoraRulebook = 5,
471+
MagnificusRulebook = 6
472+
}
473+
474+
private static SlotModificationManager m_instance;
475+
476+
/// <summary>
477+
/// Singleton instance for the SlotModificationManager.
478+
/// </summary>
479+
public static SlotModificationManager Instance
480+
{
481+
get
482+
{
483+
if (m_instance != null)
484+
return m_instance;
485+
486+
Instantiate();
487+
return m_instance;
488+
}
489+
set => m_instance = value;
490+
}
491+
492+
private static void Instantiate()
493+
{
494+
if (m_instance != null)
495+
return;
496+
497+
GameObject slotModManager = new("SlotModificationManager");
498+
slotModManager.transform.SetParent(BoardManager.Instance.gameObject.transform);
499+
m_instance = slotModManager.AddComponent<SlotModificationManager>();
500+
}
483501
#region Patches
484502
[HarmonyPatch(typeof(TurnManager), nameof(TurnManager.CleanupPhase))]
485503
[HarmonyPostfix]
@@ -514,7 +532,7 @@ private static IEnumerator CleanUpModifiedSlots(IEnumerator sequence)
514532
{
515533
Component comp = BoardManager.Instance.gameObject.GetComponent(defn.SlotBehaviour);
516534
if (!comp.SafeIsUnityNull())
517-
UnityEngine.Object.Destroy(comp);
535+
UnityObject.Destroy(comp);
518536
}
519537

520538
yield return sequence;
@@ -524,31 +542,26 @@ private static IEnumerator CleanUpModifiedSlots(IEnumerator sequence)
524542
[HarmonyPostfix, HarmonyPriority(Priority.LowerThanNormal)] // make sure custom item pages have been added first
525543
private static void AddSlotModificationsToRuleBook(AbilityMetaCategory metaCategory, RuleBookInfo __instance, ref List<RuleBookPageInfo> __result)
526544
{
527-
//InscryptionAPIPlugin.Logger.LogInfo($"In rulebook patch: I see {AllModificationInfos.Count}");
528-
if (AllModificationInfos.Count > 0)
529-
{
530-
List<Info> infos = AllModificationInfos.Where(x => RuleBookManager.SlotModShouldBeAdded(x, (ModificationMetaCategory)metaCategory)).ToList();
531-
if (infos.Count == 0)
532-
return;
545+
if (AllModificationInfos.Count == 0)
546+
return;
533547

534-
foreach (PageRangeInfo pageRangeInfo in __instance.pageRanges)
535-
{
536-
if (pageRangeInfo.type == PageRangeType.Items)
537-
{
538-
int curPageNum = 1;
539-
int insertPosition = __result.FindLastIndex(rbi => rbi.pagePrefab == pageRangeInfo.rangePrefab) + 1;
540-
foreach (Info slot in infos)
541-
{
542-
RuleBookPageInfo info = new();
543-
info.pagePrefab = pageRangeInfo.rangePrefab;
544-
info.headerText = string.Format(Localization.Translate("APPENDIX XII, SUBSECTION I - SLOT EFFECTS {0}"), curPageNum);
545-
info.pageId = SLOT_PAGEID + (int)slot.ModificationType;
546-
__result.Insert(insertPosition, info);
547-
curPageNum++;
548-
insertPosition++;
549-
}
550-
}
551-
}
548+
List<Info> infos = AllModificationInfos.Where(x => RuleBookManager.SlotModShouldBeAdded(x, (ModificationMetaCategory)metaCategory)).ToList();
549+
infos.RemoveAll(x => x.SharedRulebook != ModificationType.NoModification);
550+
if (infos.Count == 0)
551+
return;
552+
553+
int curPageNum = 1;
554+
GameObject itemPrefab = __instance.pageRanges.Find(x => x.type == PageRangeType.Items).rangePrefab;
555+
int insertPosition = __result.FindLastIndex(rbi => itemPrefab) + 1;
556+
foreach (Info slot in infos)
557+
{
558+
RuleBookPageInfo info = new();
559+
info.pagePrefab = SaveManager.SaveFile.IsPart1 ? itemPrefab : __instance.pageRanges.Find(x => x.type == PageRangeType.Abilities).rangePrefab;
560+
info.headerText = string.Format(Localization.Translate("APPENDIX XII, SUBSECTION I - SLOT EFFECTS {0}"), curPageNum);
561+
info.pageId = SLOT_PAGEID + (int)slot.ModificationType;
562+
__result.Insert(insertPosition, info);
563+
curPageNum++;
564+
insertPosition++;
552565
}
553566
}
554567

@@ -557,6 +570,11 @@ private static void AddSlotModificationsToRuleBook(AbilityMetaCategory metaCateg
557570
[HarmonyPrefix, HarmonyPatch(typeof(ItemPage), nameof(ItemPage.FillPage))]
558571
private static bool OverrideWithSlotInfo(ItemPage __instance, string headerText, params object[] otherArgs)
559572
{
573+
if (!SaveManager.SaveFile.IsPart1)
574+
return true;
575+
576+
// Slot modification pages use ItemPage format in Act 1
577+
__instance.iconRenderer.transform.localScale = Vector3.one;
560578
if (otherArgs[0] is string pageId && pageId.StartsWith(SLOT_PAGEID))
561579
{
562580
string modString = pageId.Replace(SLOT_PAGEID, "");
@@ -569,8 +587,58 @@ private static bool OverrideWithSlotInfo(ItemPage __instance, string headerText,
569587
Info info = AllModificationInfos.InfoByID((ModificationType)modType);
570588
__instance.nameTextMesh.text = Localization.Translate(info.RulebookName);
571589
__instance.descriptionTextMesh.text = Localization.Translate(info.RulebookDescription);
572-
__instance.iconRenderer.sprite = info.RulebookSprite ?? info.Texture.Values.First().ConvertTexture();
590+
__instance.iconRenderer.sprite = info.RulebookSprite;
573591
__instance.iconRenderer.transform.localScale = new(0.8f, 0.8f, 0.8f);
592+
InscryptionAPIPlugin.Logger.LogDebug($"Create rulebook page for slot modification [{info.ModificationType}] ({info.RulebookName}).");
593+
return false;
594+
}
595+
}
596+
return true;
597+
}
598+
[HarmonyPrefix, HarmonyPatch(typeof(AbilityPage), nameof(AbilityPage.FillPage))]
599+
private static bool OverrideWithSlotInfo(AbilityPage __instance, string headerText, params object[] otherArgs)
600+
{
601+
if (SaveManager.SaveFile.IsPart1)
602+
return true;
603+
604+
__instance.mainAbilityGroup.iconRenderer.transform.localScale = Vector3.one;
605+
Transform slotRendererObj = __instance.mainAbilityGroup.transform.Find("SlotRenderer");
606+
slotRendererObj?.gameObject.SetActive(false);
607+
__instance.mainAbilityGroup.iconRenderer.transform.parent.gameObject.SetActive(true);
608+
609+
if (otherArgs.Length > 0 && otherArgs.Last() is string pageId && pageId.StartsWith(SLOT_PAGEID))
610+
{
611+
string modString = pageId.Replace(SLOT_PAGEID, "");
612+
if (int.TryParse(modString, out int modType))
613+
{
614+
if (__instance.headerTextMesh != null)
615+
{
616+
__instance.headerTextMesh.text = headerText;
617+
}
618+
Info info = AllModificationInfos.InfoByID((ModificationType)modType);
619+
__instance.mainAbilityGroup.nameTextMesh.text = Localization.Translate(info.RulebookName);
620+
__instance.mainAbilityGroup.descriptionTextMesh.text = Localization.Translate(info.RulebookDescription);
621+
__instance.mainAbilityGroup.iconRenderer.transform.parent.gameObject.SetActive(false);
622+
if (SaveManager.SaveFile.IsPart3)
623+
{
624+
if (slotRendererObj == null)
625+
{
626+
slotRendererObj = Instantiate(__instance.mainAbilityGroup.iconRenderer.transform.parent, __instance.mainAbilityGroup.transform);
627+
slotRendererObj.name = "SlotRenderer";
628+
slotRendererObj.localPosition += new Vector3(0.1f, -0.1f, 0f);
629+
slotRendererObj.localScale = new(0.6f, 0.6f, 0.6f);
630+
Destroy(slotRendererObj.Find("Icon").gameObject);
631+
}
632+
slotRendererObj.gameObject.SetActive(true);
633+
__instance.mainAbilityGroup.iconRenderer.transform.parent.gameObject.SetActive(false);
634+
slotRendererObj.GetComponent<SpriteRenderer>().sprite = info.P03RulebookSprite ?? info.RulebookSprite;
635+
}
636+
else
637+
{
638+
Debug.Log("Help");
639+
}
640+
641+
__instance.mainAbilityGroup.iconRenderer.transform.localScale = new(0.8f, 0.8f, 0.8f);
574642
//InscryptionAPIPlugin.Logger.LogDebug($"Create rulebook page for slot modification [{info.ModificationType}] ({info.RulebookName}).");
575643
return false;
576644
}

0 commit comments

Comments
 (0)