Slay the Spire Mod開発入門(3) 独自カード定義編

# はじめに

本章では以下のお作法について、それぞれソースコードを引用しつつ解説していきます。

* ModTheSpire.json
* エントリポイントクラス
* 独自カード定義クラス
* 言語ファイル

各ファイルの全体像が見たい方は以下をご参照ください。

https://github.com/kojim/StSModStudy/tree/master/mod001

# ModTheSpire.json

```json
{
  "modid": "StsModStudy",
  "name": "StsModStudy",
  "author_list": ["ykojim"],
  "description": "",
  "version": "0.0.1",
  "sts_version": "01-11-2019",
  "mts_version": "3.7.0",
  "dependencies": ["basemod", "stslib"],
  "update_json": ""
}
```

おおむね見たとおりです。
modidは一意である必要があるため、他人とかぶらない名前を付けてください。

# エントリポイントクラス

```java
@SpireInitializer
public class Main implements
  EditCardsSubscriber,   // カードを追加する場合にimplementする
  EditStringsSubscriber  // 言語ファイルを読み込む場合に implementする
{

    public Main(){
        BaseMod.subscribe(this);
    }

    // @SpireInitializerで修飾したクラスはこのメソッドを定義する必要がある
    public static void initialize() {
        Main main = new Main();
    }

    @Override
    public void receiveEditStrings() {
        // 独自定義した言語ファイルを追加
        // Settings.languageには日本語ならJPN, 英語ならENGが入っている
        BaseMod.loadCustomStringsFile(CardStrings.class, "assets/loc/cards-" + Settings.language + ".json");
    }

    @Override
    public void receiveEditCards() {
        // 独自定義したカードを追加
        BaseMod.addCard(new Flare());
    }
}
```

```@SpireInitializer``` アノテーションで修飾したクラスがエントリポイントクラスとなります。
ここで各独自定義した言語ファイルやカードを有効化していきます。
実現したい内容に応じてそれぞれimplements するインターフェイスが変わってくるので注意してください。
また```initialize```メソッドが必須な点にも注意です。

# 独自カード定義クラス

```java
// カードはCustomCardクラスを継承して定義する
public class Flare extends CustomCard {
    public static final String ID = "stsmodstudy:Flare";
    // getCardStringsで Mainクラスにて読み込んだ cards-JPN.json 内の文字列情報を取得する
    private static CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
    public static final String NAME = cardStrings.NAME;
    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
```

CustomCardクラスを継承したクラスを定義することにより、独自カードを定義することができます。

ユーザの目に触れる文字列データは国際化する必要があるため、本クラス内ではなく言語ファイル内に定義することとなります。
ここでは言語ファイルから情報を取得するためのキー ```stsmodstudy:Flare```のみ定義しています。
```:```の手前にmodidを、後ろにカード名を付けるのがお作法です。


```java
    // カード使用時に発動する効果
    @Override
    public void use(AbstractPlayer p, AbstractMonster m) {
        // ダメージを与える
        AbstractDungeon.actionManager.addToBottom(
            new com.megacrit.cardcrawl.actions.common.DamageAction(
                m,
                new DamageInfo(p, this.damage, this.damageTypeForTurn),
                AbstractGameAction.AttackEffect.SLASH_DIAGONAL) // 画面効果
        );
        // 脆弱化をかける
        AbstractDungeon.actionManager.addToBottom(
            new ApplyPowerAction(                                // バフ/デバフはすべて内部的にはパワー扱い
                m,
                p,
                new VulnerablePower(m, this.magicNumber, false), // 脆弱をm(=敵)にかける
                this.magicNumber,
                true,
                AbstractGameAction.AttackEffect.NONE)            // 画面効果
        );
    }
```

このメソッドがカードの一番のキーとなります。
ゲームをプレイした方なら察しがついている思いますが、このゲームはカード使用時の効果はスタックに積まれて順々に処理されていくモデルをとっています。
```AbstractDungeon.actionManager```の各メソッドを呼び出すことで、そのスタックに処理を追加していきます。
ここではダメージを与えつつ脆弱化を与えています。

# 言語ファイル

```json
{
  "stsmodstudy:Flare": {
    "NAME": "戦士56体",
    "DESCRIPTION": "!D! ダメージを与える"
  }
}
```

カードの言語情報を定義しています。
```NAME```がカード名、```DESCRIPTION```がカード効果の説明になります。
```DESCRIPTION```中の```!D!``` ```!B!``` ```!M!``` はそれぞれ特別な意味を持ちます。
```!D!``` は カードクラスの```damage``` ```baseDamage``` ```upgradedDamage``` 変数、
```!B!``` は カードクラスの```block``` ```baseBlock``` ```upgradedBlock``` 変数、
```!M!``` は カードクラスの```magicNumber``` ```baseMagicNumber``` ```upgradedMagicNumber``` 変数へと、それぞれ状況に応じて展開されます。