diff --git a/CardLoaderMod.csproj b/ExampleMod.csproj similarity index 88% rename from CardLoaderMod.csproj rename to ExampleMod.csproj index 8adce66..a00105e 100644 --- a/CardLoaderMod.csproj +++ b/ExampleMod.csproj @@ -2,9 +2,9 @@ netstandard2.0 - CardLoaderMod - Loads a custom card, and modifies the wolf - 1.0.0 + ExampleMod + An example mod for Inscryption API + 1.6.0 true 9.0 diff --git a/Plugin.cs b/Plugin.cs index 83e76e2..70a8c06 100644 --- a/Plugin.cs +++ b/Plugin.cs @@ -1,13 +1,8 @@ using BepInEx; -using BepInEx.Logging; -using System; using System.Collections; using System.Collections.Generic; -using System.Reflection; -using System.Linq; using System.IO; using DiskCardGame; -using HarmonyLib; using UnityEngine; using APIPlugin; @@ -17,9 +12,9 @@ namespace CardLoaderMod [BepInDependency("cyantist.inscryption.api", BepInDependency.DependencyFlags.HardDependency)] public class Plugin : BaseUnityPlugin { - private const string PluginGuid = "cyantist.inscryption.customcardexample"; - private const string PluginName = "CustomCardModExample"; - private const string PluginVersion = "1.0.0.0"; + private const string PluginGuid = "cyantist.inscryption.examplemod"; + private const string PluginName = "ExampleMod"; + private const string PluginVersion = "1.6.0.0"; private void Awake() { @@ -28,92 +23,334 @@ private void Awake() AddBears(); AddAbility(); ChangeWolf(); + AddRegion(); } private void AddBears() { - List metaCategories = new List(); - metaCategories.Add(CardMetaCategory.ChoiceNode); - metaCategories.Add(CardMetaCategory.Rare); + // metaCategories determine the card pools + List metaCategories = new List + { + CardMetaCategory.ChoiceNode, + CardMetaCategory.Rare + }; - List appearanceBehaviour = new List(); - appearanceBehaviour.Add(CardAppearanceBehaviour.Appearance.RareCardBackground); + List appearanceBehaviour = new List + { + CardAppearanceBehaviour.Appearance.RareCardBackground, + CardAppearanceBehaviour.Appearance.AnimatedPortrait // Optional. If not provided for a talking card, it will be added automatically + }; - byte[] imgBytes = System.IO.File.ReadAllBytes(Path.Combine(this.Info.Location.Replace("CardLoaderMod.dll",""),"Artwork/eightfuckingbears.png")); + List specialAbilities = new List + { + SpecialTriggeredAbility.TalkingCardChooser // Required for talking cards! + }; + + // Load the image into a Texture2D object + byte[] imgBytes = File.ReadAllBytes(Path.Combine(this.Info.Location.Replace("ExampleMod.dll", ""),"Artwork/eightfuckingbears.png")); Texture2D tex = new Texture2D(2,2); tex.LoadImage(imgBytes); - NewCard.Add("Eight_Bears", metaCategories, CardComplexity.Simple, CardTemple.Nature,"8 fucking bears!",32,48,description:"Kill this abomination please",cost:3,appearanceBehaviour:appearanceBehaviour, tex:tex); + // Add the card + NewCard.Add("Eight_Bears", "8 fucking bears!", 32, 48, metaCategories, CardComplexity.Simple, CardTemple.Nature, description: "Kill this abomination please", + bloodCost: 3, appearanceBehaviour: appearanceBehaviour, defaultTex: tex, specialAbilities: specialAbilities); + + // Add the talking card behaviour. The name must be the same as the card name! + NewTalkingCard.Add("Eight_Bears", EightBearsTalkingCard.GetDictionary()); } private NewAbility AddAbility() - { + { AbilityInfo info = ScriptableObject.CreateInstance(); info.powerLevel = 0; info.rulebookName = "Example Ability"; info.rulebookDescription = "Example ability which adds a PiggyBank!"; - info.metaCategories = new List {AbilityMetaCategory.Part1Rulebook, AbilityMetaCategory.Part1Modular}; + // metaCategories determine the pools + info.metaCategories = new List { AbilityMetaCategory.Part1Rulebook, AbilityMetaCategory.Part1Modular }; + + // Create the 'learned' dialogue List lines = new List(); DialogueEvent.Line line = new DialogueEvent.Line(); line.text = "New abilities? I didn't authorise homebrew!"; lines.Add(line); info.abilityLearnedDialogue = new DialogueEvent.LineSet(lines); - byte[] imgBytes = System.IO.File.ReadAllBytes(Path.Combine(this.Info.Location.Replace("CardLoaderMod.dll",""),"Artwork/new.png")); - Texture2D tex = new Texture2D(2,2); + // Load the image into a Texture2D object + byte[] imgBytes = File.ReadAllBytes(Path.Combine(this.Info.Location.Replace("ExampleMod.dll", ""), "Artwork/new.png")); + Texture2D tex = new Texture2D(2, 2); tex.LoadImage(imgBytes); - NewAbility ability = new NewAbility(info,typeof(NewTestAbility),tex,AbilityIdentifier.GetAbilityIdentifier(PluginGuid, info.rulebookName)); + NewAbility ability = new NewAbility(info, typeof(NewTestAbility), tex, AbilityIdentifier.GetID(PluginGuid, info.rulebookName)); NewTestAbility.ability = ability.ability; return ability; - } + } private void ChangeWolf() { - List abilities = new List {NewTestAbility.ability}; - new CustomCard("Wolf") {baseAttack=10, abilities=abilities}; + List abilities = new List { NewTestAbility.ability }; + new CustomCard("Wolf") { baseAttack = 10, abilities = abilities }; } + private void AddRegion() + { + // Load the default first region (NOTE: For Kaycee's Mod, use 'regions[0]') + RegionData regionData = ResourceBank.Get("Data/Map/RegionProgression").regions[0][0]; + + regionData.name = "Example_Region"; + + // Clear default encounters + regionData.encounters.Clear(); + + // Modify the colors to be red/green + regionData.boardLightColor = new Color(1f, 0f, 0f); + regionData.cardsLightColor = new Color(0f, 1f, 0f); + + // Adds the region to tier 0 + new NewRegion(regionData, 0); + + + // Add eight turns with four 'Eight_Bears' cards + List> turns = new List>(); + for (int i = 0; i < 8; i++) + { + List turn = new List(); + for (int j = 0; j < 4; j++) + { + turn.Add(new EncounterBlueprintData.CardBlueprint() { + // We have to get it directly from the new card list because it is not yet loaded into data - will be fixed in the future + card = NewCard.cards.Find(card => card.name == "Eight_Bears") + }); + } + turns.Add(turn); + } + EncounterBlueprintData bearsBlueprint = ScriptableObject.CreateInstance(); + + // Which totem to use for totem battles (Bears are tribeless, so using squirrel here) + bearsBlueprint.dominantTribes = new List() { Tribe.Squirrel }; + bearsBlueprint.turns = turns; + + // Add the encounter as 'regular' encounter of the example region + // Usually it's better to add it to the encounters field instead, if you create the region in the same mod + new NewEncounter("Bear_Spam", bearsBlueprint, "Example_Region", true, false); + } + + public class NewTestAbility : AbilityBehaviour - { - public override Ability Ability - { - get - { - return ability; - } - } + { + public override Ability Ability + { + get + { + return ability; + } + } public static Ability ability; - public override bool RespondsToResolveOnBoard() - { - return true; - } - - public override IEnumerator OnResolveOnBoard() - { - yield return base.PreSuccessfulTriggerSequence(); - yield return new WaitForSeconds(0.2f); - Singleton.Instance.SwitchToView(View.Default, false, false); - yield return new WaitForSeconds(0.25f); - if (RunState.Run.consumables.Count < 3) - { - RunState.Run.consumables.Add("PiggyBank"); - Singleton.Instance.UpdateItems(false); - } - else - { - base.Card.Anim.StrongNegationEffect(); - yield return new WaitForSeconds(0.2f); - Singleton.Instance.ShakeConsumableSlots(0f); - } - yield return new WaitForSeconds(0.2f); - yield return base.LearnAbility(0f); - yield break; - } - } + public override bool RespondsToResolveOnBoard() + { + return true; + } + + public override IEnumerator OnResolveOnBoard() + { + yield return base.PreSuccessfulTriggerSequence(); + yield return new WaitForSeconds(0.2f); + Singleton.Instance.SwitchToView(View.Default, false, false); + yield return new WaitForSeconds(0.25f); + // Add piggy bank, only if there is room for it + if (RunState.Run.consumables.Count < 3) + { + RunState.Run.consumables.Add("PiggyBank"); + Singleton.Instance.UpdateItems(false); + } + else + { + base.Card.Anim.StrongNegationEffect(); + yield return new WaitForSeconds(0.2f); + Singleton.Instance.ShakeConsumableSlots(0f); + } + yield return new WaitForSeconds(0.2f); + yield return base.LearnAbility(0f); + yield break; + } + } } + public class EightBearsTalkingCard : PaperTalkingCard + { + // Static method for easy access + public static DialogueEvent.Speaker Speaker => (DialogueEvent.Speaker) 100; + + // Only important for multi-speaker dialogs + public override DialogueEvent.Speaker SpeakerType => Speaker; + + // IDs should point to dictionary entries in GetDictionary(). + // Required: + + public override string OnDrawnDialogueId => "TalkingEightBearsDrawn"; + + public override string OnDrawnFallbackDialogueId => "TalkingEightBearsDrawn2"; + + public override string OnPlayFromHandDialogueId => "TalkingEightBearsPlayed"; + + public override string OnAttackedDialogueId => "TalkingEightBearsAttacked"; + + public override string OnBecomeSelectablePositiveDialogueId => "TalkingEightBearsPositiveSelectable"; + + public override string OnBecomeSelectableNegativeDialogueId => "TalkingEightBearsNegativeSelectable"; + + public override Dictionary OnDrawnSpecialOpponentDialogueIds => new Dictionary(); + + // Optional: + + public override string OnSacrificedDialogueId => "TalkingEightBearsSacrificed"; + + public override string OnSelectedForCardMergeDialogueId => "TalkingEightBearsMerged"; + + public override string OnSelectedForCardRemoveDialogueId => "TalkingEightBearsRemoved"; + + public override string OnSelectedForDeckTrialDialogueId => "TalkingEightBearsDeckTrial"; + + public override string OnDiscoveredInExplorationDialogueId => "TalkingEightBearsDiscovered"; + + public static Dictionary GetDictionary() + { + Dictionary events = new Dictionary(); + events.Add("TalkingEightBearsDrawn", new DialogueEvent() + { + id = "TalkingEightBearsDrawn", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsDrawn2", new DialogueEvent() + { + id = "TalkingEightBearsDrawn2", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsPlayed", new DialogueEvent() + { + id = "TalkingEightBearsPlayed", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsAttacked", new DialogueEvent() + { + id = "TalkingEightBearsAttacked", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsPositiveSelectable", new DialogueEvent() + { + id = "TalkingEightBearsPositiveSelectable", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsNegativeSelectable", new DialogueEvent() + { + id = "TalkingEightBearsNegativeSelectable", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsSacrificed", new DialogueEvent() + { + id = "TalkingEightBearsSacrificed", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsMerged", new DialogueEvent() + { + id = "TalkingEightBearsMerged", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsRemoved", new DialogueEvent() + { + id = "TalkingEightBearsRemoved", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsDeckTrial", new DialogueEvent() + { + id = "TalkingEightBearsDeckTrial", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + events.Add("TalkingEightBearsDiscovered", new DialogueEvent() + { + id = "TalkingEightBearsDiscovered", + speakers = new List() { Speaker }, + mainLines = new DialogueEvent.LineSet() + { + lines = new List() + { + new DialogueEvent.Line { text = "*Bear Noises*" } + } + } + }); + return events; + } + } } diff --git a/README.md b/README.md index 701bd5c..dcc7a93 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,27 @@ # ExampleMod ## Example mod for Inscryption API made by Cyantist -This plugin is a BepInEx plugin made for Inscryption to create custom cards for the API by Cyantist. -One example card is provided in the Plugin class with method name AddBears. -One customised card is provided in the Plugin class with method name ChangeWolf. +This plugin is a BepInEx plugin made for Inscryption to add content using the API by Cyantist. +Examples for the following features are included in the Plugin class: +- `AddBears()`: custom cards and talking cards +- `AddAbility()`: custom abilities +- `ChangeWolf()`: modifying existing cards +- `AddRegion()`: custom regions and encounters ## 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 Install with Mod Manager button on top of the [page](https://inscryption.thunderstore.io/package/Cyantist/ExampleMod/) +- Click Install with Mod Manager button on top of the [page](https://inscryption.thunderstore.io/package/API_dev/ExampleMod/) - 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 will also need to install the [CardLoaderPlugin](https://github.com/ScottWilson0903/InscryptionAPI) +You will also need to install the [API](https://github.com/ScottWilson0903/InscryptionAPI) To install Inscryption API you simply need to copy **API.dll** from [releases](https://github.com/ScottWilson0903/InscryptionAPI/releases) to **Inscryption/BepInEx/plugins**. -To install ExampleMod with just the default example card included "Eight Fucking Bears!" and example modified wolf, you simply need to copy **CardLoaderMod.dll** and the **Artwork** folder from the source code zip in [releases](https://github.com/ScottWilson0903/InscryptionExampleMod/releases) to a **Cyantist-ExampleMod** folder inside **Inscryption/BepInEx/plugins**. - -## Creating your own -To generate your own cards, you will need to either pass in an already created **CardInfo** object to the **NewCard.Add** function, or you will need to pass all the required and optional parameters to the **NewCard** constructor as done in **Plugin.AddBears**. Any png files should be added to the **Artwork** folder and should be 114x94 pixels. -To alter existing cards you will need to pass the card name and the values you want to change to the optional parameters in the **CustomCard** constructor, as done in **Plugin.ChangeWolf**. -To add custom abilities you will need a class inheriting **AbilityBehaviour**, an **AbilityInfo** and a texture which should be 49x49 pixels and also placed in the **Artwork** folder. - -The newly compiled **CardLoaderMod.dll** should be installed exactly the same way as above. +To install ExampleMod with just the default examples, you simply need to copy **ExampleMod.dll** and the **Artwork** folder from the source code zip in [releases](https://github.com/ScottWilson0903/InscryptionExampleMod/releases) to a **Cyantist-ExampleMod** folder inside **Inscryption/BepInEx/plugins**. ## Can I donate? Donations are totally not needed, this is a passion project before anything else. If you do still want to donate though, you can buy me a coffee on [ko-fi](https://ko-fi.com/madcyantist). diff --git a/lib/API.dll b/lib/API.dll index 1d699bb..5c2207d 100644 Binary files a/lib/API.dll and b/lib/API.dll differ diff --git a/lib/Assembly-CSharp.dll b/lib/Assembly-CSharp.dll index 4fdb2e6..6bfcbba 100644 Binary files a/lib/Assembly-CSharp.dll and b/lib/Assembly-CSharp.dll differ diff --git a/manifest.json b/manifest.json index 280671b..5c4d57d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { "name": "ExampleMod", - "version_number": "1.5.0", + "version_number": "1.6.0", "website_url": "https://github.com/ScottWilson0903/InscryptionExampleMod", - "description": "This plugin is a BepInEx plugin made for Inscryption to create custom cards and abilities for the API by Cyantist.", + "description": "This plugin is a BepInEx plugin made for Inscryption to provide various examples for the API by Cyantist.", "dependencies": [ "BepInEx-BepInExPack_Inscryption-5.4.1701", - "API_dev-API-1.11.0" + "API_dev-API-1.13.0" ] }