Skip to content

Adding Potions

Alchyr edited this page Aug 8, 2023 · 17 revisions

Registering Your Potions

The process of making potions has two steps.

Step 1: Make the potion.

Step 2: Register the potion.

AutoAdd is a feature of BaseMod that allows you to avoid manually registering every potion you make.

Setting up AutoAdd for potions

Potions do not have any specific subscriber you need to add to your main mod file to register them in. Instead, they're simply registered in receivePostInitialize, which you should already have in the main mod file.

For organization, we'll make a separate static method to register all the potions in, and just call that method in receivePostInitialize.

    @Override
    public void receivePostInitialize() {
        registerPotions();
        
        //... the rest of the method
    }

    public static void registerPotions() {

    }

You can find a bit more explanation of AutoAdd in the pages for adding cards and relics. This code utilizes information stored in the BasePotion class to register the potion appropriately.

    public static void registerPotions() {
        new AutoAdd(modID) //Loads files from this mod
                .packageFilter(BasePotion.class) //In the same package as this class
                .any(BasePotion.class, (info, potion) -> { //Run this code for any classes that extend this class
                    //These three null parameters are colors.
                    //If they're not null, they'll overwrite whatever color is set in the potions themselves.
                    //This is because setting colors to whatever you want in the potion itself wasn't possible before.
                    BaseMod.addPotion(potion.getClass(), null, null, null, potion.ID, potion.playerClass);
                    //playerClass will make a potion character-specific. By default, it's null and will do nothing.
                });
    }

You may need to use Alt+Enter to import some classes. Any potions you make should now be added automatically, as long as they're in the same package as BasePotion. This includes sub-packages. If you want the details of how AutoAdd works, check the BaseMod wiki page for documentation. This code is made to work with how BasicMod is setup and will require changes if you are not using BasicMod.

If you make potions that don't extend the BasePotion class, they will not be registered by this AutoAdd. You can register them manually with BaseMod.addPotion or set up AutoAdd differently.

Making Potions

The first step is to make a new class in the potions package.

image

You should probably organize your potions using packages, such as having a package for common, uncommon, and rare potions.

public class MyPotion extends BasePotion {

}

First, you'll need to define the relic's ID.

public class MyPotion extends BasePotion {
    private static final String ID = makeID("MyPotion");

}

Every potion has to have a unique ID. You can also use something like makeID(MyPotion.class.getSimpleName()). This will have the same result, but if you make a copy of the class it will be changed automatically.

BasePotion has two different constructors. In one of them you set the colors of the potion yourself, and in the other you just choose one of the "preset" colorings defined by the base game. In this example, we'll be using the one where you set the colors yourself. First, define the colors you'll be using.

public class MyPotion extends BasePotion {
    public static final String ID = makeID(MyPotion.class.getSimpleName());

    private static final Color LIQUID_COLOR = CardHelper.getColor(255, 0, 255);
    private static final Color HYBRID_COLOR = CardHelper.getColor(255, 0, 255);
    private static final Color SPOTS_COLOR = CardHelper.getColor(255, 0, 255);

CardHelper.getColor is a helper method defined by the base game to create a color based on red/green/blue values from 0 to 255. You can define these colors in any way you want, whether using a preexisting color (eg. Color.GRAY.cpy();) or using one of the constructors of the Color class (new Color().

It's important to note that which of these colors you need depends on the shape of the potion. Not all shapes support all three colors. In fact, if you provide a color that isn't supported, an error will occur and your potion will just turn into a Fire Potion. In these cases, you should be able to find an error message in the log explaining the problem, such as this:

image

In this example, the potion has a spots color, but the shape used doesn't support it. To fix this, you would just use null for SPOTS_COLOR.

    private static final Color LIQUID_COLOR = CardHelper.getColor(255, 0, 255);
    private static final Color HYBRID_COLOR = CardHelper.getColor(255, 0, 255);
    private static final Color SPOTS_COLOR = null;

Constructor

    public MyPotion() {
        super(ID, 5, PotionRarity.COMMON, PotionSize.MOON, LIQUID_COLOR, HYBRID_COLOR, SPOTS_COLOR);
    }

The first parameter is just the ID.

The second parameter is the potion's potency, the number that appears in its description and is affected by relics like Sacred Bark. If your potion doesn't have a number like this just use 0.

Third is the rarity.

Fourth is the shape. This determines the shape of the bottle and which of the color variables you can use. For a custom appearance, just use any of them and continue on until the end of this page.

Lastly, is the color. Here you'll either give it three colors you've chosen, or a PotionColor, like PotionColor.FIRE.

If you want the potion to be only for a specific character, add

    public MyPotion() {
        super(ID, 5, PotionRarity.COMMON, PotionSize.MOON, LIQUID_COLOR, HYBRID_COLOR, SPOTS_COLOR);
        playerClass = AbstractPlayer.PlayerClass.IRONCLAD;
    }

to the constructor. This would make this potion exclusive to the Ironclad.

If your potion is going to be thrown at an enemy, set isThrown = true; and targetRequired = true;. If it's just thrown but doesn't need a target (eg. Explosive Potion) just set isThrown to true.

Making the Potion Work

Right now, your potion class should look something like this:

image

Click on the class definition (the line with the error) and hit Alt+Enter. This should give you the option to "Implement methods".

image

Choose it. In the window appears, just leave it as-is and click Ok.

image

This should create two empty methods inside the class, getDescription and use.

PAGE INCOMPLETE

Text

  "${modID}:MyPotion": {
    "NAME": "Some Kind of Potion",
    "DESCRIPTIONS": [
      "Gain #b",
      " #yStrength."
    ]
  }
    @Override
    public String getDescription() {
        return potionStrings.DESCRIPTIONS[0] + potency + potionStrings.DESCRIPTIONS[1];
    }

Slay the Spire tends to construct descriptions using string concatenation like this, but you can also use the String.format method. In this case, you would use %d in the potion's description text for where the number should go.

    "DESCRIPTIONS": [
      "Gain #b%d #yStrength."
    ]

Then in getDescription, you would use String.format.

    @Override
    public String getDescription() {
        return String.format(potionStrings.DESCRIPTIONS[0], potency);
    }

Functionality

    @Override
    public void use(AbstractCreature target) {
        if (AbstractDungeon.getCurrRoom().phase == AbstractRoom.RoomPhase.COMBAT) {
            target = AbstractDungeon.player; //This potion just gives Strength to yourself. You don't need to use target if you don't want to.
            addToBot(new ApplyPowerAction(target, AbstractDungeon.player, new StrengthPower(target, potency), potency));
        }
    }

The in-combat check if (AbstractDungeon.getCurrRoom().phase == AbstractRoom.RoomPhase.COMBAT) may not be necessary.

Additional Tooltips

Potions do not generate keyword tooltips on their own. If required, override the getAdditionalTips method.

Custom Appearance

Utilize the set____Img methods.

Clone this wiki locally