Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 2.23.6
- Fixed card modifications added to a card's base ice cube card via CardInfo.SetIceCube being ignored
- Fixed PlayableCard.CanPlay not consistently accounting for temporary mod cost adjustments
- Fixed dynamic play costs not consistently updating
- Added additional methods for adding specific types of resources to the ResourceBank

# 2.23.5
- Fixed cards appearing as blank outside Act 1
- Added extension methods for FullAbility that mirror AbilityInfo extension methods
Expand Down
40 changes: 33 additions & 7 deletions InscryptionAPI/Card/AbilityManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using InscryptionAPI.Helpers;
using InscryptionAPI.Helpers.Extensions;
using InscryptionAPI.RuleBook;
using Sirenix.Utilities;
using System.Collections;
using System.Collections.ObjectModel;
using System.Reflection;
Expand Down Expand Up @@ -683,6 +684,38 @@ private static void LogAbilityInfo(Ability ability, AbilityInfo abilityInfo, Car
InscryptionAPIPlugin.Logger.LogError("Cannot find ability " + ability + " for " + info.displayedName);
}

[HarmonyPatch(typeof(IceCube), nameof(IceCube.OnDie), MethodType.Enumerator)]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> AddInherentModsToIceCube(IEnumerable<CodeInstruction> instructions) {
List<CodeInstruction> codes = new(instructions);

for (int i = 0; i < codes.Count; i++) {
if (codes[i].opcode == OpCodes.Ldloc_2) {
// this probably belongs in the community patches but this transpiler was already here, so eh
// overrides the transformer icon so it can display numbers
MethodInfo customMethod = AccessTools.Method(typeof(AbilityManager), nameof(AbilityManager.GetIceCubeInfoWithMods),
new Type[] { typeof(IceCube), typeof(string) });

// ldloc_1 <- IceCube
// ldloc_2 <- name
// call (customMethod)
codes[i + 1] = new(OpCodes.Call, customMethod);
codes.Insert(i, new(OpCodes.Ldloc_1));
break;
}
}

return codes;
}

private static CardInfo GetIceCubeInfoWithMods(IceCube instance, string cardName) {
CardInfo info = CardLoader.GetCardByName(cardName);
if (instance.Card.Info.iceCubeParams != null && instance.Card.Info.iceCubeParams.creatureWithin != null && instance.Card.Info.iceCubeParams.creatureWithin.mods != null && instance.Card.Info.iceCubeParams.creatureWithin.mods.Count > 0) {
info.Mods.AddRange(instance.Card.Info.iceCubeParams.creatureWithin.mods);
}
return info;
}

#region Evolve Changes
[HarmonyPatch(typeof(Evolve), nameof(Evolve.OnUpkeep), MethodType.Enumerator)]
[HarmonyTranspiler]
Expand Down Expand Up @@ -734,13 +767,6 @@ private static bool OverrideTransformIcon(ref Texture __result, AbilityIconInter
}
return true;
}
//[HarmonyPrefix, HarmonyPatch(typeof(AbilitiesUtil), nameof(AbilitiesUtil.LoadAbilityIcon))]
//private static bool OverrideEvolveAndTransformerIcon(ref Texture __result, string abilityName) {
// if (abilityName.StartsWith("Evolve") || abilityName.StartsWith("Transformer")) {
// return false;
// }
// return true;
//}
private static void OverrideEvolveDerivedIcon(Evolve evolve, int turnsLeftToEvolve)
{
if (evolve.Ability == Ability.Evolve)
Expand Down
136 changes: 60 additions & 76 deletions InscryptionAPI/Card/CostProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ public bool GemsChanged<T>(List<T> a, List<T> b)

public static ConditionalWeakTable<CardInfo, List<WeakReference<PlayableCard>>> CardInfoToCard = new();


// a table that maps a CardInfo object to a list of weak references to every PlayableCard that uses that same CardInfo
public static ConditionalWeakTable<CardInfo, List<WeakReference<PlayableCard>>> CardInfoToPlayableCardReferences = new();


/// <summary>
/// ChangeCardCostGetter patches BloodCost so we can change the cost on the fly
/// This reverse patch gives us access to the original method without any changes.
Expand Down Expand Up @@ -151,6 +156,7 @@ internal static class ChangeCardCostGetter
public static bool BloodCost(CardInfo __instance, ref int __result)
{
PlayableCard card = __instance.GetPlayableCard();
//Debug.Log($"{card != null}");
__result = Mathf.Max(0, card?.BloodCost() ?? CostProperties.OriginalBloodCost(__instance));
return false;
}
Expand Down Expand Up @@ -196,94 +202,72 @@ public static bool DisableVanillaEnergyCost(PlayableCard __instance, ref int __r
__result = Mathf.Max(0, energyCost);
return false;
}

//[HarmonyPostfix, HarmonyPatch(typeof(PlayableCard), nameof(PlayableCard.SetInfo))]
//private static void GetCardInfoReferences(PlayableCard __instance) {

// // if this is a new PlayableCard being associated with the given CardInfo
// // returns true if the CardInfo is in the table
// if (CostProperties.CardInfoToPlayableCardReferences.TryGetValue(__instance.Info, out List<WeakReference<PlayableCard>> connectedCards)) {
// PlayableCard card = null;
// for (int i = connectedCards.Count - 1; i >= 0; i--) {
// // NOTE: We store a list of cards so if we don't clear this list then it will fill up forever
// // remove PlayableCard references that no longer point to anything
// if (!connectedCards[i].TryGetTarget(out PlayableCard cardReference) || cardReference == null) {
// connectedCards.RemoveAt(i);
// }
// else if (cardReference == __instance) {
// card = cardReference;
// }
// }

// if (card == null) {
// connectedCards.Add(new WeakReference<PlayableCard>(__instance));
// if (connectedCards.Count > 1) {
// InscryptionAPIPlugin.Logger.LogWarning($"More than 1 card are using the same card info. This can cause unexpected problems with dynamic costs! {__instance.Info.displayedName}");
// }
// }
// }
// else {
// // add CardInfo to table with reference to this PlayableCard
// CostProperties.CardInfoToPlayableCardReferences.Add(__instance.Info, new() { new(__instance) });
// }
//}
}

/*[HarmonyPatch(typeof(DiskCardGame.Card), nameof(DiskCardGame.Card.Info), MethodType.Setter)]
internal static class Card_SetInfo
[HarmonyPatch(typeof(PlayableCard), nameof(PlayableCard.SetInfo))]
internal static class AddRefreshBehaviourToCard
{
public static void Postfix(DiskCardGame.Card __instance)
private static void Postfix(PlayableCard __instance)
{
//return;
if (__instance is not PlayableCard playableCard)
return;

CardInfo info = playableCard.Info;

if (CostProperties.CardInfoToCard.TryGetValue(info, out List<WeakReference<PlayableCard>> cardList))
{
// add the refresh component if it doesn't exist, then set the Card to the calling instance
CostProperties.RefreshCostMonoBehaviour refreshCostDisplay = __instance.GetComponent<CostProperties.RefreshCostMonoBehaviour>() ?? __instance.gameObject.AddComponent<CostProperties.RefreshCostMonoBehaviour>();
refreshCostDisplay.playableCard = __instance;

// if this is a new PlayableCard being associated with the given CardInfo
// returns true if the CardInfo is in the table
if (CostProperties.CardInfoToCard.TryGetValue(__instance.Info, out List<WeakReference<PlayableCard>> cardList)) {
PlayableCard card = null;
for (int i = cardList.Count - 1; i >= 0; i--)
{
for (int i = cardList.Count - 1; i >= 0; i--) {
// NOTE: We store a list of cards so if we don't clear this list then it will fill up forever
// remove PlayableCard references that no longer point to anything
if (!cardList[i].TryGetTarget(out PlayableCard innerCard) || innerCard == null)
{
// NOTE: We store a list of cards so if we don't clear this list then it will fill up forever
cardList.RemoveAt(i);
}
else if(innerCard == playableCard)
{

else if (innerCard == __instance)
card = innerCard;
}
}

if (card == null)
{
cardList.Add(new WeakReference<PlayableCard>(playableCard));
if (cardList.Count > 1)
{
InscryptionAPIPlugin.Logger.LogWarning($"More than 1 card are using the same card info. This can cause unexpected problems with dynamic costs! {info.displayedName}");
}
}
}
else
{
Debug.Log($"New-un");
CostProperties.CardInfoToCard.Add(info, new List<WeakReference<PlayableCard>>()
{
new WeakReference<PlayableCard>(playableCard)
});
}
}
}*/

[HarmonyPatch(typeof(PlayableCard), nameof(PlayableCard.SetInfo))]
internal static class AddRefreshBehaviourToCard
{
private static void Postfix(PlayableCard __instance)
{
// add the refresh component if it doesn't exist, then set the Card to the calling instance
if (__instance.GetComponent<CostProperties.RefreshCostMonoBehaviour>() == null)
{
__instance.gameObject.AddComponent<CostProperties.RefreshCostMonoBehaviour>().playableCard = __instance;
if (CostProperties.CardInfoToCard.TryGetValue(__instance.Info, out List<WeakReference<PlayableCard>> cardList))
{
PlayableCard card = null;
for (int i = cardList.Count - 1; i >= 0; i--)
{
// NOTE: We store a list of cards so if we don't clear this list then it will fill up forever
if (!cardList[i].TryGetTarget(out PlayableCard innerCard) || innerCard == null)
cardList.RemoveAt(i);

else if (innerCard == __instance)
card = innerCard;
}

if (card == null)
{
cardList.Add(new WeakReference<PlayableCard>(__instance));
if (cardList.Count > 1)
{
InscryptionAPIPlugin.Logger.LogWarning($"More than 1 card are using the same card info. This can cause unexpected problems with dynamic costs! {__instance.Info.displayedName}");
}
if (card == null) {
cardList.Add(new WeakReference<PlayableCard>(__instance));
if (cardList.Count > 1) {
InscryptionAPIPlugin.Logger.LogWarning($"More than 1 card are using the same CardInfo. This can cause unexpected problems with dynamic costs! {__instance.Info.displayedName}");
}
}
else
{
CostProperties.CardInfoToCard.Add(__instance.Info, new List<WeakReference<PlayableCard>>()
{
new WeakReference<PlayableCard>(__instance)
});
}

}
else {
// add CardInfo to table with reference to this PlayableCard
CostProperties.CardInfoToCard.Add(__instance.Info, new() { new (__instance) });
}
}
}
Expand Down
23 changes: 11 additions & 12 deletions InscryptionAPI/Costs/CardCostManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,18 +324,17 @@ public static FullCardCost SetFoundAtChoiceNodes(this FullCardCost fullCardCost,

#region Patches
[HarmonyPostfix, HarmonyPatch(typeof(PlayableCard), nameof(PlayableCard.CanPlay))]
private static void CanPlayCustomCosts(ref bool __result, ref PlayableCard __instance)
{
if (!__result)
return;

foreach (CustomCardCost cost in __instance.GetCustomCardCosts())
{
FullCardCost fullCost = AllCustomCosts.CostByBehaviour(cost.GetType());
if (!cost.CostSatisfied(__instance.GetCustomCost(fullCost), __instance))
{
__result = false;
return;
private static void CanPlayCustomCosts(ref bool __result, ref PlayableCard __instance) {
if (__instance.BloodCost() <= Singleton<BoardManager>.Instance.AvailableSacrificeValue && __instance.BonesCost() <= Singleton<ResourcesManager>.Instance.PlayerBones && __instance.EnergyCost <= Singleton<ResourcesManager>.Instance.PlayerEnergy && __instance.GemsCostRequirementMet()) {
if (Singleton<BoardManager>.Instance.SacrificesCreateRoomForCard(__instance, Singleton<BoardManager>.Instance.PlayerSlotsCopy)) {
foreach (CustomCardCost cost in __instance.GetCustomCardCosts()) {
FullCardCost fullCost = AllCustomCosts.CostByBehaviour(cost.GetType());
if (!cost.CostSatisfied(__instance.GetCustomCost(fullCost), __instance)) {
__result = false;
return;
}
}
__result = true;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion InscryptionAPI/InscryptionAPI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<DebugType>full</DebugType>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<Version>2.23.5</Version>
<Version>2.23.6</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion InscryptionAPI/InscryptionAPIPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class InscryptionAPIPlugin : BaseUnityPlugin
{
public const string ModGUID = "cyantist.inscryption.api";
public const string ModName = "InscryptionAPI";
public const string ModVer = "2.23.5";
public const string ModVer = "2.23.6";

public static string Directory = "";

Expand Down
Loading
Loading