diff --git a/CHANGELOG.md b/CHANGELOG.md index da931110..41616525 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@
View Changelog +# 2.22.2 +- Added GetEnergyConfig method to community patch's EnergyDrone class - retrieves the current Act's EnergyConfigInfo +- CommunityPatches: Added community config to move pelt price tags to the right of the card +- Experimental: Changed gemified to only reduce a single cost on a card, with priority of Energy > Bones > Gems > Blood +- Fixed positioning errors caused by having multiple custom boss challenge icons +- EnergyConfigInfo's fields can now be modified when initialising a new instance +- Updated installation guide on the ReadMe to match the wiki, added link to wiki. + # 2.22.1 - Added IShieldPreventedDamage and IShieldPreventedDamageInHand ability triggers and interfaces - Added TriggerBreakShield, wraps BreakShield in an IEnumerator for additional customisation by modders diff --git a/InscryptionAPI/Ascension/AscensionChallengePaginator.cs b/InscryptionAPI/Ascension/AscensionChallengePaginator.cs index 2d2e9f47..afbba7e0 100644 --- a/InscryptionAPI/Ascension/AscensionChallengePaginator.cs +++ b/InscryptionAPI/Ascension/AscensionChallengePaginator.cs @@ -71,29 +71,37 @@ public void AddPage(List challengeInfos) List bossChallengeInfos = challengeInfos.FindAll(x => x.challengeType.GetFullChallenge().Boss); // keep track of the number of bosses that are on this page, and account for them when determining how many icons to create - int numBosses = challengeInfos.Count(x => x.challengeType.GetFullChallenge().Boss); + int numBosses = bossChallengeInfos.Count; int numIcons = Mathf.Min(14, challengeObjectsForPages[0].Count) - numBosses; // the list index when we begin adding boss icons int bossStartingIndex = (1 + regularChallengeInfos.Count) / 2; int numBossesAdded = 0; - //Debug.Log($"NumIcons for Page: {numIcons}: {regularChallengeInfos.Count} {bossChallengeInfos.Count}"); + // 14 = regular + boss * 2 + //Debug.Log($"NumIcons for Page: {numIcons}: {regularChallengeInfos.Count} {bossChallengeInfos.Count} | {bossStartingIndex}"); for (int i = 0; i < 14; i++) { GameObject objectRef = null; - if (i % 7 < bossStartingIndex + numBosses && i % 7 >= bossStartingIndex) + int columnIndex = i % 7; + //Debug.Log($"{i} ({columnIndex}) | {bossStartingIndex + numBosses} / {bossStartingIndex}"); + + if (columnIndex >= bossStartingIndex && columnIndex < bossStartingIndex + numBosses) { + //Debug.Log($"In boss column {i}"); if (numBossesAdded < numBosses) { + //Debug.Log($"Use boss icon"); numBossesAdded++; objectRef = challengeObjectsForPages[0][14]; } else { - i += numBosses; + //Debug.Log($"Skip to end"); + i += numBosses - 1; // account for loop iteration + continue; } } @@ -117,21 +125,22 @@ public void AddPage(List challengeInfos) int infoCount = challengeInfos.Count; for (int i = 0; i < newPage.Count; i++) { - //Debug.Log($"Checking icon [{i}] info {infoIdx}"); + AscensionChallengeInfo info = challengeInfos[infoIdx]; AscensionIconInteractable interactable = newPage[i].GetComponent(); - + //Debug.Log($"Checking icon [{i}] info at {infoIdx} : {info.title}"); if (i < infoCount) { // if we're assigning boss info to an icon that isn't a boss icon - if (challengeInfos[infoIdx].GetFullChallenge().Boss && (interactable.coll2D as BoxCollider2D).size.y < 1f) + if (info.GetFullChallenge().Boss && (interactable.coll2D as BoxCollider2D).size.y < 1f) { + //Debug.Log("Boss error: y < 1"); interactable.challengeInfo = missingChallengeInfo; newPage[i].AddComponent(); infoCount++; } else { - interactable.challengeInfo = challengeInfos[infoIdx]; + interactable.challengeInfo = info; infoIdx++; } } diff --git a/InscryptionAPI/Ascension/ChallengeDisplayerPlus.cs b/InscryptionAPI/Ascension/ChallengeDisplayerPlus.cs index c8959f5e..48460dd7 100644 --- a/InscryptionAPI/Ascension/ChallengeDisplayerPlus.cs +++ b/InscryptionAPI/Ascension/ChallengeDisplayerPlus.cs @@ -26,6 +26,7 @@ public static ChallengeDisplayerPlus TryAddChallengeDisplayerPlusToDisplayer(Asc if (plus.incompatibilityText == null) { GameObject cloned = Instantiate(displayer.titleText.gameObject); + cloned.name = "PixelTextLine_INCOMPATIBLE"; cloned.transform.parent = displayer.titleText.transform.parent; float y = plus.originalTitlePos; if (displayer.descriptionText != null) @@ -47,6 +48,7 @@ public static ChallengeDisplayerPlus TryAddChallengeDisplayerPlusToDisplayer(Asc if (plus.dependencyText == null) { GameObject cloned = Instantiate(displayer.titleText.gameObject); + cloned.name = "PixelTextLine_DEPENDENCY"; cloned.transform.parent = displayer.titleText.transform.parent; float y = plus.originalTitlePos; if (displayer.descriptionText != null) diff --git a/InscryptionAPI/Card/CardExtensionsCosts.cs b/InscryptionAPI/Card/CardExtensionsCosts.cs index 06cf06e0..99e22935 100644 --- a/InscryptionAPI/Card/CardExtensionsCosts.cs +++ b/InscryptionAPI/Card/CardExtensionsCosts.cs @@ -35,8 +35,7 @@ public static int BloodCost(this PlayableCard card) if (card && card.Info) { int originalBloodCost = CostProperties.CostProperties.OriginalBloodCost(card.Info); - - if (card.IsUsingBlueGem()) + if (card.IsUsingBlueGem() && CostProperties.CostProperties.ReduceGemifiedBlood(card, originalBloodCost)) originalBloodCost--; // add adjustments from temp mods @@ -59,7 +58,7 @@ public static int BonesCost(this PlayableCard card) if (card && card.Info) { int originalBonesCost = CostProperties.CostProperties.OriginalBonesCost(card.Info); - if (card.IsUsingBlueGem()) + if (card.IsUsingBlueGem() && CostProperties.CostProperties.ReduceGemifiedBones(card, originalBonesCost)) originalBonesCost--; // add adjustments from temp mods @@ -98,7 +97,7 @@ public static List GemsCost(this PlayableCard card) } } - if (gemsCost.Count > 0 && card.IsUsingBlueGem()) + if (card.IsUsingBlueGem() && CostProperties.CostProperties.ReduceGemifiedMox(card, gemsCost)) gemsCost.RemoveAt(0); return gemsCost; diff --git a/InscryptionAPI/Card/CostProperties.cs b/InscryptionAPI/Card/CostProperties.cs index 16cbd1ce..cab30bea 100644 --- a/InscryptionAPI/Card/CostProperties.cs +++ b/InscryptionAPI/Card/CostProperties.cs @@ -78,7 +78,6 @@ public bool GemsChanged(List a, List b) [HarmonyReversePatch, HarmonyPatch(typeof(CardInfo), nameof(CardInfo.BloodCost), MethodType.Getter), MethodImpl(MethodImplOptions.NoInlining)] public static int OriginalBloodCost(CardInfo __instance) { return 0; } - /// /// ChangeCardCostGetter patches BoneCost so we can change the cost on the fly /// This reverse patch gives us access to the original method without any changes. @@ -87,7 +86,6 @@ public bool GemsChanged(List a, List b) [HarmonyReversePatch, HarmonyPatch(typeof(CardInfo), nameof(CardInfo.BonesCost), MethodType.Getter), MethodImpl(MethodImplOptions.NoInlining)] public static int OriginalBonesCost(CardInfo __instance) { return 0; } - /// /// ChangeCardCostGetter patches GemsCost so we can change the cost on the fly /// This reverse patch gives us access to the original method without any changes. @@ -96,6 +94,11 @@ public bool GemsChanged(List a, List b) [HarmonyReversePatch, HarmonyPatch(typeof(CardInfo), nameof(CardInfo.GemsCost), MethodType.Getter), MethodImpl(MethodImplOptions.NoInlining)] public static List OriginalGemsCost(CardInfo __instance) { return null; } + /// + /// Improved version of CardInfo.GemsCost that accounts for addGemCost and RemovedGemsCost(). + /// + /// For consistency's sake, it's recommended you use this method over OriginalGemsCost in most cases. + /// public static List ImprovedGemsCost(CardInfo instance) { if (instance.Mods.Exists(x => x.nullifyGemsCost)) @@ -123,6 +126,23 @@ public static List ImprovedGemsCost(CardInfo instance) /// [HarmonyReversePatch, HarmonyPatch(typeof(CardInfo), nameof(CardInfo.EnergyCost), MethodType.Getter), MethodImpl(MethodImplOptions.NoInlining)] public static int OriginalEnergyCost(CardInfo __instance) { return 0; } + + public static bool ReduceGemifiedBlood(PlayableCard card, int? bloodCost = null) + { + return (bloodCost ?? OriginalBloodCost(card.Info)) > 0 && !ReduceGemifiedMox(card) && !ReduceGemifiedBones(card) && !ReduceGemifiedMox(card); + } + public static bool ReduceGemifiedMox(PlayableCard card, List gemsCost = null) + { + return (gemsCost?.Count ?? ImprovedGemsCost(card.Info).Count) > 0 && !ReduceGemifiedBones(card) && !ReduceGemifiedEnergy(card); + } + public static bool ReduceGemifiedBones(PlayableCard card, int? bonesCost = null) + { + return (bonesCost ?? OriginalBonesCost(card.Info)) > 0 && !ReduceGemifiedEnergy(card); + } + public static bool ReduceGemifiedEnergy(PlayableCard card, int? energyCost = null) + { + return (energyCost ?? OriginalEnergyCost(card.Info)) > 0; + } } [HarmonyPatch] @@ -162,12 +182,13 @@ public static bool EnergyCost(CardInfo __instance, ref int __result) __result = card?.EnergyCost ?? CostProperties.OriginalEnergyCost(__instance); return false; } + [HarmonyPatch(typeof(PlayableCard), nameof(PlayableCard.EnergyCost), MethodType.Getter), HarmonyPrefix] public static bool DisableVanillaEnergyCost(PlayableCard __instance, ref int __result) { // patch this to follow the same pattern as the other cost methods int energyCost = CostProperties.OriginalEnergyCost(__instance.Info); - if (__instance.IsUsingBlueGem()) + if (__instance.IsUsingBlueGem() && CostProperties.ReduceGemifiedEnergy(__instance, energyCost)) energyCost--; foreach (CardModificationInfo mod in __instance.TemporaryMods) diff --git a/InscryptionAPI/InscryptionAPI.csproj b/InscryptionAPI/InscryptionAPI.csproj index 7b4c34a2..8d4a0a4f 100644 --- a/InscryptionAPI/InscryptionAPI.csproj +++ b/InscryptionAPI/InscryptionAPI.csproj @@ -10,7 +10,7 @@ full false true - 2.22.1 + 2.22.2 diff --git a/InscryptionAPI/InscryptionAPIPlugin.cs b/InscryptionAPI/InscryptionAPIPlugin.cs index 89792078..822013cd 100644 --- a/InscryptionAPI/InscryptionAPIPlugin.cs +++ b/InscryptionAPI/InscryptionAPIPlugin.cs @@ -30,7 +30,7 @@ public class InscryptionAPIPlugin : BaseUnityPlugin { public const string ModGUID = "cyantist.inscryption.api"; public const string ModName = "InscryptionAPI"; - public const string ModVer = "2.22.0"; + public const string ModVer = "2.22.2"; public static string Directory = ""; diff --git a/InscryptionCommunityPatch/InscryptionCommunityPatch.csproj b/InscryptionCommunityPatch/InscryptionCommunityPatch.csproj index 958db84b..3ba1dbb4 100644 --- a/InscryptionCommunityPatch/InscryptionCommunityPatch.csproj +++ b/InscryptionCommunityPatch/InscryptionCommunityPatch.csproj @@ -9,7 +9,7 @@ true full false - 2.21.0 + 2.22.0 diff --git a/InscryptionCommunityPatch/InscryptionCommunityPatchPlugin.cs b/InscryptionCommunityPatch/InscryptionCommunityPatchPlugin.cs index 1c9ba0df..a8dca8c4 100644 --- a/InscryptionCommunityPatch/InscryptionCommunityPatchPlugin.cs +++ b/InscryptionCommunityPatch/InscryptionCommunityPatchPlugin.cs @@ -44,6 +44,7 @@ public class PatchPlugin : BaseUnityPlugin internal static ConfigEntry configRemovePatches; internal static ConfigEntry configSmallPricetags; + internal static ConfigEntry configMovePricetags; internal static ConfigEntry configTestState; @@ -93,6 +94,7 @@ private void Awake() configMergeOnBottom = Config.Bind("Sigil Display", "Merge_On_Botom", false, "Makes it so if enabled, merged sigils will display on the bottom of the card instead of on the artwork. In extreme cases, this can cause some visual bugs."); configRemovePatches = Config.Bind("Sigil Display", "Remove_Patches", false, "Makes it so if enabled, merged sigils will not have a patch behind them anymore and will instead be glowing yellow (only works with Merge_On_Bottom)."); configSmallPricetags = Config.Bind("Act 1", "Smaller Pricetags", false, "If enabled, the price tags placed on cards while buying from the Trapper will be scaled down."); + configMovePricetags = Config.Bind("Act 1", "Move Pricetags", false, "If enabled, the price tags placed on cards while buying from the Trapper will be moved to the right."); act2StackIconType = Config.Bind("Sigil Display", "Act 2 Sigil icon type", true, "If true, stacking icons are a cream outline with a black center. If false, stacking icons are a black outline with a cream center. Act 2"); act2TutorCenterRows = Config.Bind("Act 2", "Centred Hoarder UI", true, "If true, centres displayed cards in each row during the Hoarder selection sequence."); configFullDebug = Config.Bind("General", "Full Debug", true, "If true, displays all debug logs in the console."); diff --git a/InscryptionCommunityPatch/ResourceManagers/ActOneEnergyDrone.cs b/InscryptionCommunityPatch/ResourceManagers/ActOneEnergyDrone.cs index d615be0b..dd95f551 100644 --- a/InscryptionCommunityPatch/ResourceManagers/ActOneEnergyDrone.cs +++ b/InscryptionCommunityPatch/ResourceManagers/ActOneEnergyDrone.cs @@ -11,15 +11,26 @@ namespace InscryptionCommunityPatch.ResourceManagers; [HarmonyPatch] public static class EnergyDrone { + /// + /// Class containing information on the resource energy drone. Controls whether the Energy Drone will appear in non-Act 3 acts. + /// public class EnergyConfigInfo { - public bool ConfigEnergy => PoolHasEnergy || PatchPlugin.configEnergy.Value; - public bool ConfigDrone => PoolHasEnergy || ConfigDroneMox || PatchPlugin.configDrone.Value; - public bool ConfigDroneMox => PoolHasGems || PatchPlugin.configDroneMox.Value; - public bool ConfigMox => PoolHasGems || PatchPlugin.configMox.Value; - public bool ConfigDefaultDrone => PatchPlugin.configDefaultDrone.Value; + public bool ConfigEnergy { get; set; } = PoolHasEnergy || PatchPlugin.configEnergy.Value; + public bool ConfigShowDrone { get; set; } = PoolHasEnergy || PatchPlugin.configDrone.Value; + public bool ConfigDroneMox { get; set; } = PoolHasGems || PatchPlugin.configDroneMox.Value; + public bool ConfigMox { get; set; } = PoolHasGems || PatchPlugin.configMox.Value; + public bool ConfigDefaultDrone { get; set; } = PatchPlugin.configDefaultDrone.Value; + + /// + /// Controls whether or not the Drone will appear. By default, will appear if there are obtainable Energy or Mox cards in the card pool (or the corresponding config value has been set). + /// + public bool ConfigDrone => ConfigShowDrone || ConfigDroneMox; } + /// + /// Contains the EnergyConfigInfos for each Act with default settings. If you want to directly alter an Act's drone behaviour, please modify GetEnergyConfig instead. + /// public static Dictionary ZoneConfigs = new() { { CardTemple.Nature, new() }, @@ -49,23 +60,28 @@ public static bool CurrentSceneCanHaveEnergyDrone } } - private static EnergyConfigInfo EnergyConfig + /// + /// Returns the EnergyConfigInfo object corresponding to the current Act. + /// + public static EnergyConfigInfo GetEnergyConfig() { - get - { - if (SaveManager.SaveFile.IsPart3) - return ZoneConfigs[CardTemple.Tech]; + if (SaveManager.SaveFile.IsPart3) + return ZoneConfigs[CardTemple.Tech]; - if (SaveManager.SaveFile.IsGrimora) - return ZoneConfigs[CardTemple.Undead]; + if (SaveManager.SaveFile.IsGrimora) + return ZoneConfigs[CardTemple.Undead]; - if (SaveManager.SaveFile.IsMagnificus) - return ZoneConfigs[CardTemple.Wizard]; + if (SaveManager.SaveFile.IsMagnificus) + return ZoneConfigs[CardTemple.Wizard]; - return ZoneConfigs[CardTemple.Nature]; - } + return ZoneConfigs[CardTemple.Nature]; } + /// + /// The EnergyConfigInfo for the current Act. + /// + private static EnergyConfigInfo EnergyConfig => GetEnergyConfig(); + public static bool PoolHasEnergy { get; private set; } public static bool PoolHasGems { get; private set; } diff --git a/InscryptionCommunityPatch/Sequencers/BuyPeltsSmallTags.cs b/InscryptionCommunityPatch/Sequencers/BuyPeltsSmallTags.cs index 36965ed2..3d3038b6 100644 --- a/InscryptionCommunityPatch/Sequencers/BuyPeltsSmallTags.cs +++ b/InscryptionCommunityPatch/Sequencers/BuyPeltsSmallTags.cs @@ -15,13 +15,20 @@ internal class BuyPeltsSmallTags [HarmonyPostfix, HarmonyPatch(typeof(BuyPeltsSequencer), nameof(BuyPeltsSequencer.AddPricetagToCard))] private static void ReducePricetagSize(SelectableCard card) { - if (!PatchPlugin.configSmallPricetags.Value) - return; - - Transform t = card.transform.Find("pricetag"); - if (t != null) + if (PatchPlugin.configSmallPricetags.Value || PatchPlugin.configMovePricetags.Value) { - t.localScale = new(0.75f, 1f, 0.75f); + Transform t = card.transform.Find("pricetag"); + if (t == null) + return; + + if (PatchPlugin.configSmallPricetags.Value) + { + t.localScale = new(0.75f, 1f, 0.75f); + } + if (PatchPlugin.configMovePricetags.Value) + { + t.localPosition = new(t.localPosition.x * -1, t.localPosition.y, t.localPosition.z); + } } } } \ No newline at end of file diff --git a/README.md b/README.md index 52c25cad..bd871598 100644 --- a/README.md +++ b/README.md @@ -17,28 +17,47 @@ It can currently create and modify: - Totem Tops - Consumable Items - Gramophone Tracks +- Slot Modifications - Talking Cards - Custom Costs +- Custom Rulebook Pages +- Rulebook Redirects/Hyperlinks - And much more! Additionally, a number of quality-of-life patches from the community are included with each release. -## Installation (automated) -This is the recommended way to install the API on the game. - -- Download and install [Thunderstore Mod Manager](https://www.overwolf.com/app/Thunderstore-Thunderstore_Mod_Manager) or [r2modman](https://timberborn.thunderstore.io/package/ebkr/r2modman/). -- Click the **Install with Mod Manager** button on the top of [BepInEx's](https://thunderstore.io/package/download/BepInEx/BepInExPack_Inscryption/5.4.1902/) page. -- Run the game via the mod manager. - -## Installation (manual) -To install this plugin first you need to install BepInEx as a mod loader for Inscryption. A guide to do this can be found [here](https://docs.bepinex.dev/articles/user_guide/installation/index.html#where-to-download-bepinex). Inscryption needs the 86x (32 bit) mono version. -You also need to install [MonoMod Loader Inscryption](https://inscryption.thunderstore.io/package/BepInEx/MonoMod_Loader_Inscryption/). - -- Copy the 'plugins' folder into 'BepInEx/plugins'. -- Copy the 'monomod' folder into 'BepInEx/monomod'. -(If any of these folders do not exist, just create them.) - -An example Mod utilising this plugin can be found [here](https://github.com/debugman18/InscryptionExampleMod). +### Installing with a Mod Manager (recommended) +1. Download and install [Thunderstore Mod Manager](https://www.overwolf.com/app/Thunderstore-Thunderstore_Mod_Manager) or [r2modman](https://Timberborn.thunderstore.io/package/ebkr/r2modman/). +2. Click the **Install with Mod Manager** button on the top of [BepInEx's](https://thunderstore.io/package/download/BepInEx/BepInExPack_Inscryption/5.4.1902/) page. +3. Run the game via the mod manager. + +### Installing Manually +1. Install [BepInEx](https://thunderstore.io/package/download/BepInEx/BepInExPack_Inscryption/5.4.1902/) by pressing 'Manual Download' and extract the contents into a folder. **Do not extract into the game folder!** +2. Move the contents of the 'BepInExPack_Inscryption' folder into the game folder (where the game executable is). +3. Run the game. If everything was done correctly, you will see the BepInEx console appear on your desktop. Close the game after it finishes loading. +4. Install [MonoModLoader](https://inscryption.thunderstore.io/package/BepInEx/MonoMod_Loader_Inscryption/) and extract the contents into a folder. +5. Move the contents of the 'patchers' folder into 'BepInEx/patchers' (If any of the mentioned BepInEx folders don't exist, just create them). +6. Install [Inscryption API](https://inscryption.thunderstore.io/package/API_dev/API/) and extract the contents into a folder. +7. Move the contents of the 'plugins' folder into 'BepInEx/plugins' and the contents of the 'monomod' folder into the 'BepInEx/monomod' folder. +8. Run the game again. If everything runs correctly, a message will appear in the console telling you that the API was loaded. + +### Installing on the Steam Deck +1. Download [r2modman](https://Timberborn.thunderstore.io/package/ebkr/r2modman/) on the Steam Deck’s Desktop Mode and open it from its download using its `AppImage` file. +2. Download the mods you plan on using and their dependencies.. +3. Go to the setting of the profile you are using for the mods and click `Browse Profile Folder`. +4. Copy the BepInEx folder, then go to Steam and open Inscryption's Properties menu +5. Go to `Installed Files` click `Browse` to open the folder containing Inscryption's local files; paste the BepInEx folder there. +6. Enter Gaming Mode and check 'Force the use of a specific Steam Play compatibility tool' in the Properties menu under `Compatibility`. +7. Go to the launch parameters and enter `WINEDLLOVERRIDES=“winhttp.dll=n,b” %command%`. +8. Open Inscryption. If everything was done correctly, you should see a console appear on your screen. + +### Mac & Linux +1. Follow the steps here first: [Installing BepInEx](https://docs.bepinex.dev/articles/user_guide/installation/index.html?tabs=tabid-nix) +2. Next do steps 4-8 of the Manual Installation +3. Your game should be setup for inscryption modding now + +An example mod utilising this plugin can be found [here](https://github.com/debugman18/InscryptionExampleMod), +and the modding wiki and documentation can be found [here](https://inscryptionmodding.github.io/InscryptionAPI/wiki/index.html). ## Modded Save File With this API installed, an additional 'modded save file' will be created by the game. This file will be found in the 'BepInEx' subdirectory, and contains all save data created by mods that use this API. This file will not automatically be synced to the cloud by Steam. @@ -76,7 +95,7 @@ Displays targets for attacks made with the sniper sigil in Act 1. ## Act 1 Sentry Fixes by WhistleWind Fixes a number of bugs caused by the Sentry ability being used in Act 1. -## Multi-Act Sigil Compatability Fixes by WhistleWind +## Multi-Act Sigil Compatibility Fixes by WhistleWind Fixes a number of sigils to be usable in all Acts. Sigils include: Mental Gemnastics, Tidal Lock, Hoarder, Vessel Printer, Amorphous, Handy. ## Fledgling Sigil Fixes by WhistleWind @@ -85,6 +104,9 @@ Fixes Fledgling in Act 2 to show the correct number of turns until a card evolve ## OverridePixelAbilityIcons by WhistleWind Fixes the OverrideAbilityIcon method to work in Act 2. +## Temporary Mod Fixes by WhistleWind +- Fixes issues related to using temporary mods in Act 2 or to add custom decals + # Using the API Inscryption API 2.0 tries to have you use the original game's objects as much as possible. For example, there are no more 'NewCard' and 'CustomCard' objects; instead, you are responsible to create CardInfo objects yourself and add them. @@ -97,7 +119,7 @@ For more information, please check out the wiki: https://inscryptionmodding.gith ### How can you help? Use the plugin and report bugs you find! Ping us on the [Inscryption Modding Discord](https://discord.gg/QrJEF5Denm) server in the api channel with what you find. -### But really, I want to help develop this mod +### But really, I want to help develop this mod! Great! We're more than happy to accept help. Either make a pull request to the API's [GitHub page](https://github.com/InscryptionModding/InscryptionAPI) or come join us over in the [Inscryption Modding Discord](https://discord.gg/QrJEF5Denm). ### Can I donate?