Bläddra i källkod

对上次提交的补充

Luxnk 6 år sedan
förälder
incheckning
4da15a4a7e
34 ändrade filer med 1498 tillägg och 132 borttagningar
  1. BIN
      lib/ModTheSpire.jar
  2. 59 0
      mxmmod/pom.xml
  3. 241 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/MxmMod.java
  4. 61 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/action/LuckyCatAction.java
  5. 61 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/action/PoorWineAction.java
  6. 90 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/action/SadCatAction.java
  7. 66 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/Defend_MXM.java
  8. 63 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/LuckyCat_MXM.java
  9. 79 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/PoorWine_MXM.java
  10. 63 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/QuickStrike_MXM.java
  11. 67 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/SadCat_MXM.java
  12. 73 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/SpeedUp.java
  13. 71 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/Strike_MXM.java
  14. 71 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/TwinStrike_MXM.java
  15. 79 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/Whirlwind_MXM.java
  16. 190 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/characters/Mxm.java
  17. 8 0
      mxmmod/src/main/java/xyz/luxnk/mxmmod/patches/AbstractCardEnum.java
  18. 7 0
      mxmmod/src/main/java/xyz/luxnk/mxmmod/patches/LibraryTypeEnum.java
  19. 6 0
      mxmmod/src/main/java/xyz/luxnk/mxmmod/patches/MxmModClassEnum.java
  20. 53 1
      mxmmod/src/main/java/xyz/luxnk/mxmmod/relics/Hamakagami.java
  21. 7 9
      mxmmod/src/main/resources/ModTheSpire.json
  22. BIN
      mxmmod/src/main/resources/img/1024/cardOrb.png
  23. BIN
      mxmmod/src/main/resources/img/512/cardOrb.png
  24. BIN
      mxmmod/src/main/resources/img/cards/skill/lucky_cat.png
  25. BIN
      mxmmod/src/main/resources/img/cards/skill/lucky_cat_p.png
  26. 2 107
      mxmmod/src/main/resources/img/char/skeleton.atlas
  27. 1 1
      mxmmod/src/main/resources/img/char/skeleton.json
  28. BIN
      mxmmod/src/main/resources/img/char/skeleton.png
  29. BIN
      mxmmod/src/main/resources/img/charSelect/mxmButton.png
  30. BIN
      mxmmod/src/main/resources/img/charSelect/mxmPortrait.jpg
  31. 41 0
      mxmmod/src/main/resources/localization/mxm_cards-zh.json
  32. 16 0
      mxmmod/src/main/resources/localization/mxm_keywords-zh.json
  33. 10 0
      mxmmod/src/main/resources/localization/mxm_relics-zh.json
  34. 13 0
      mxmmod/src/main/resources/localization/mxm_ui-zh.json

BIN
lib/ModTheSpire.jar


+ 59 - 0
mxmmod/pom.xml

@@ -8,5 +8,64 @@
     <artifactId>mxmmod</artifactId>
     <version>1.0-SNAPSHOT</version>
 
+    <dependencies>
+        <dependency>
+            <groupId>com.megacrit.cardcrawl</groupId>
+            <artifactId>slaythespire</artifactId>
+            <version>906</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/../lib/desktop-1.0.jar</systemPath>
+        </dependency>
+        <dependency>
+            <groupId>basemod</groupId>
+            <artifactId>basemod</artifactId>
+            <version>3.2.2</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/../lib/BaseMod.jar</systemPath>
+        </dependency>
+        <dependency>
+            <groupId>com.evacipated.cardcrawl</groupId>
+            <artifactId>ModTheSpire</artifactId>
+            <version>3.1.0</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/../lib/ModTheSpire.jar</systemPath>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>STS_Mod_Mxm</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.7.0</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>1.8</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <configuration>
+                            <target>
+                                <copy file="target/STS_Mod_Mxm.jar"
+                                      tofile="../out/STS_Mod_Mxm.jar"/>
+                                <copy file="target/STS_Mod_Mxm.jar"
+                                      tofile="E:/Steam/steamapps/common/SlayTheSpire/mods/STS_Mod_Mxm.jar"/>
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
     
 </project>

+ 241 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/MxmMod.java

@@ -1,2 +1,242 @@
-public class MxmMod {
+package xyz.luxnk.mxmmod;
+
+import basemod.BaseMod;
+import basemod.ModPanel;
+import basemod.helpers.RelicType;
+import basemod.interfaces.*;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.utils.compression.lzma.Base;
+import com.evacipated.cardcrawl.modthespire.lib.SpireInitializer;
+import com.google.gson.Gson;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.CardGroup;
+import com.megacrit.cardcrawl.cards.green.*;
+import com.megacrit.cardcrawl.cards.red.*;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.helpers.CardHelper;
+import com.megacrit.cardcrawl.helpers.ImageMaster;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.localization.Keyword;
+import com.megacrit.cardcrawl.localization.RelicStrings;
+import com.megacrit.cardcrawl.localization.UIStrings;
+import com.megacrit.cardcrawl.rooms.AbstractRoom;
+import com.megacrit.cardcrawl.unlock.UnlockTracker;
+import com.sun.org.apache.xpath.internal.compiler.Keywords;
+import xyz.luxnk.mxmmod.cards.*;
+import xyz.luxnk.mxmmod.characters.Mxm;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+import xyz.luxnk.mxmmod.patches.MxmModClassEnum;
+import xyz.luxnk.mxmmod.relics.Hamakagami;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Map;
+
+@SpireInitializer
+public class MxmMod implements PostInitializeSubscriber,
+        PostCreateStartingDeckSubscriber,
+        PostCreateStartingRelicsSubscriber,
+        PostExhaustSubscriber,
+        PostBattleSubscriber,
+        PostDungeonInitializeSubscriber,
+        EditCharactersSubscriber,
+        EditStringsSubscriber,
+        EditRelicsSubscriber,
+        EditCardsSubscriber,
+        EditKeywordsSubscriber {
+
+    private static final String RELIC_STRING = "localization/mxm_relics-zh.json";
+    private static final String CARD_STRING = "localization/mxm_cards-zh.json";
+    private static final String KEYWORD_STRING = "localization/mxm_keywords-zh.json";
+    private static final String UI_STRING = "localization/mxm_ui-zh.json";
+
+    public static final Color CYAN = CardHelper.getColor(100f, 240f, 245f);
+
+    private static final String MOD_BADGE = "img/UI/badge.png";
+
+    private static final String MXM_BUTTON = "img/charSelect/mxmButton.png";
+    private static final String MXM_PORTRAIT = "img/charSelect/mxmPortrait.jpg";
+
+    // 卡片背景图(暂时借用魔理沙小姐的
+    private static final String ATTACK_CC = "img/512/bg_attack_MRS_s.png";
+    private static final String SKILL_CC = "img/512/bg_skill_mxm_s.png";
+    private static final String POWER_CC = "img/512/bg_power_MRS_s.png";
+    private static final String ENERGY_ORB_CC = "img/512/cardOrb.png";
+
+    private static final String ATTACK_CC_PORTRAIT = "img/1024/bg_attack_MRS.png";
+    private static final String SKILL_CC_PORTRAIT = "img/1024/bg_skill_mxm.png";
+    private static final String POWER_CC_PORTRAIT = "img/1024/bg_power_MRS.png";
+    private static final String ENERGY_ORB_CC_PORTRAIT = "img/1024/cardOrb.png";
+
+    public static final String CARD_ENERGY_ORB = "img/UI/energyOrb.png";
+
+    public MxmMod() {
+        BaseMod.subscribe(this);
+        BaseMod.addColor(
+                AbstractCardEnum.MXM_COLOR,
+                CYAN,
+                CYAN,
+                CYAN,
+                CYAN,
+                CYAN,
+                CYAN,
+                CYAN,
+                ATTACK_CC,
+                SKILL_CC,
+                POWER_CC,
+                ENERGY_ORB_CC,
+                ATTACK_CC_PORTRAIT,
+                SKILL_CC_PORTRAIT,
+                POWER_CC_PORTRAIT,
+                ENERGY_ORB_CC_PORTRAIT,
+                CARD_ENERGY_ORB
+        );
+    }
+
+    public static void initialize() {
+        new MxmMod();
+    }
+
+    @Override
+    public void receivePostInitialize() {
+        ModPanel settingsPanel = new ModPanel();
+        Texture badge = ImageMaster.loadImage(MOD_BADGE);
+        BaseMod.registerModBadge(
+                badge,
+                "MxmMod",
+                "Luxnk , litter cat",
+                "猫小咪来了",
+                settingsPanel
+        );
+    }
+
+    @Override
+    public void receiveEditCharacters() {
+        BaseMod.addCharacter(
+                new Mxm("MaoXiaomi"),
+                MXM_BUTTON,
+                MXM_PORTRAIT,
+                MxmModClassEnum.MXM
+        );
+    }
+
+    @Override
+    public void receiveEditStrings() {
+
+        BaseMod.loadCustomStrings(RelicStrings.class, Gdx.files.internal(RELIC_STRING).readString(
+                String.valueOf(StandardCharsets.UTF_8)
+        ));
+        BaseMod.loadCustomStrings(CardStrings.class, Gdx.files.internal(CARD_STRING).readString(
+                String.valueOf(StandardCharsets.UTF_8)
+        ));
+        BaseMod.loadCustomStrings(UIStrings.class, Gdx.files.internal(UI_STRING).readString(
+                String.valueOf(StandardCharsets.UTF_8)
+        ));
+
+    }
+
+    @Override
+    public void receiveEditRelics() {
+
+        //BaseMod.addRelic(new Hamakagami(), RelicType.SHARED);
+        BaseMod.addRelicToCustomPool(
+                new Hamakagami(),
+                AbstractCardEnum.MXM_COLOR
+        );
+    }
+
+    @Override
+    public void receiveEditCards() {
+        BaseMod.addCard(new Strike_MXM());
+        BaseMod.addCard(new TwinStrike_MXM());
+        BaseMod.addCard(new QuickStrike_MXM());
+        BaseMod.addCard(new Whirlwind_MXM());
+        BaseMod.addCard(new Defend_MXM());
+        BaseMod.addCard(new SpeedUp());
+        BaseMod.addCard(new PoorWine_MXM());
+        BaseMod.addCard(new SadCat_MXM());
+        BaseMod.addCard(new LuckyCat_MXM());
+
+        // 借用下卡牌
+
+        // 攻击
+        BaseMod.addCard(new Anger());
+        BaseMod.addCard(new BodySlam());
+        BaseMod.addCard(new DieDieDie());
+        BaseMod.addCard(new HeelHook());
+        BaseMod.addCard(new SuckerPunch());
+        BaseMod.addCard(new GrandFinale());
+        BaseMod.addCard(new Feed());
+        BaseMod.addCard(new HeavyBlade());
+        BaseMod.addCard(new Unload());
+        BaseMod.addCard(new RecklessCharge());
+        BaseMod.addCard(new Uppercut());
+        BaseMod.addCard(new Clash());
+
+        // 技能
+        BaseMod.addCard(new SecondWind());
+        BaseMod.addCard(new SpotWeakness());
+        BaseMod.addCard(new Backflip());
+        BaseMod.addCard(new DodgeAndRoll());
+        BaseMod.addCard(new Warcry());
+        BaseMod.addCard(new Flex());
+        BaseMod.addCard(new Intimidate());
+        BaseMod.addCard(new Disarm());
+        BaseMod.addCard(new Rage());
+        BaseMod.addCard(new Blur());
+
+        // 能力
+        BaseMod.addCard(new Inflame());
+        BaseMod.addCard(new Berserk());
+        BaseMod.addCard(new Footwork());
+        BaseMod.addCard(new Caltrops());
+        BaseMod.addCard(new AfterImage());
+    }
+
+    @Override
+    public void receiveEditKeywords() {
+        Gson gson = new Gson();
+        Keywords keywords = gson.fromJson(loadJson(KEYWORD_STRING), Keywords.class);
+        for (Keyword key : keywords.keywords) {
+            BaseMod.addKeyword(key.NAMES, key.DESCRIPTION);
+        }
+    }
+
+    private static String loadJson(String jsonPath) {
+        return Gdx.files.internal(jsonPath).readString(String.valueOf(StandardCharsets.UTF_8));
+    }
+
+    @Override
+    public void receivePostBattle(AbstractRoom abstractRoom) {
+    }
+
+    @Override
+    public void receivePostDungeonInitialize() {
+    }
+
+    @Override
+    public void receivePostExhaust(AbstractCard abstractCard) {
+    }
+
+    @Override
+    public void receivePostCreateStartingDeck(AbstractPlayer.PlayerClass playerClass, CardGroup cardGroup) {
+        if (playerClass == AbstractPlayer.PlayerClass.IRONCLAD) {
+            cardGroup.addToTop(new Anger());
+        }
+    }
+
+    @Override
+    public void receivePostCreateStartingRelics(AbstractPlayer.PlayerClass playerClass, ArrayList<String> arrayList) {
+        if (playerClass == AbstractPlayer.PlayerClass.IRONCLAD) {
+            arrayList.add("Hamakagami");
+            UnlockTracker.markRelicAsSeen("Hamakagami");
+        }
+    }
+
+    class Keywords {
+
+        Keyword[] keywords;
+    }
 }

+ 61 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/action/LuckyCatAction.java

@@ -1,4 +1,64 @@
 package xyz.luxnk.mxmmod.action;
 
-public class LuckyCatAction {
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.CardGroup;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.core.Settings;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+
+public class LuckyCatAction extends AbstractGameAction {
+
+    public static final String[] TEXT = CardCrawlGame.languagePack.getUIString("LuckyCatAction").TEXT;
+
+    private AbstractPlayer p;
+
+    public LuckyCatAction(int amount) {
+        this.p = AbstractDungeon.player;
+        this.setValues(this.p, AbstractDungeon.player, amount);
+        this.actionType = AbstractGameAction.ActionType.CARD_MANIPULATION;
+    }
+
+    @Override
+    public void update() {
+        AbstractCard card;
+        if (this.p.drawPile.isEmpty()) {
+            this.isDone = true;
+            return;
+        }
+        if (this.p.drawPile.size() == 1) {
+            card = this.p.drawPile.group.get(0);
+            if (card.cost > 0) {
+                card.freeToPlayOnce = true;
+            }
+            this.p.hand.refreshHandLayout();
+            this.isDone = true;
+            return;
+        }
+        if (this.duration == 0.5F) {
+            AbstractDungeon.gridSelectScreen.open(this.p.drawPile, this.amount, TEXT[0], false);
+            tickDuration();
+            return;
+        }
+        if (AbstractDungeon.gridSelectScreen.selectedCards.size() != 0) {
+            for (AbstractCard c : AbstractDungeon.gridSelectScreen.selectedCards) {
+                this.p.drawPile.removeCard(c);
+                this.p.drawPile.addToTop(c);
+                if (c.cost > 0) {
+                    c.freeToPlayOnce = true;
+                }
+                c.unhover();
+            }
+            AbstractDungeon.gridSelectScreen.selectedCards.clear();
+            this.p.hand.refreshHandLayout();
+            /*for (AbstractCard c : this.p.exhaustPile.group) {
+                c.unhover();
+                c.target_x = CardGroup.DISCARD_PILE_X;
+                c.target_y = 0.0F;
+            }*/
+            this.isDone = true;
+        }
+        tickDuration();
+    }
 }

+ 61 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/action/PoorWineAction.java

@@ -1,4 +1,64 @@
 package xyz.luxnk.mxmmod.action;
 
-public class PoorWineAction {
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.CardGroup;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+
+/**
+ * 从消耗牌堆挑选卡牌加入手牌
+ */
+public class PoorWineAction extends AbstractGameAction {
+
+    public static final String[] TEXT = CardCrawlGame.languagePack.getUIString("DiscardPileToHandAction").TEXT;
+
+    private AbstractPlayer p;
+
+    public PoorWineAction(int amount) {
+        this.p = AbstractDungeon.player;
+        this.setValues(this.p, AbstractDungeon.player, amount);
+        this.actionType = ActionType.CARD_MANIPULATION;
+    }
+
+    @Override
+    public void update() {
+        if ((p.hand.size() >= 10) || (p.exhaustPile.isEmpty())) {
+            this.isDone = true;
+            return;
+        }
+        AbstractCard card;
+        if (this.p.exhaustPile.size() == 1) {
+            card = this.p.exhaustPile.group.get(0);
+            this.p.hand.addToHand(card);
+            card.lighten(false);
+            this.p.exhaustPile.removeCard(card);
+            this.p.hand.refreshHandLayout();
+            this.isDone = true;
+            return;
+        }
+        if (this.duration == 0.5F) {
+            AbstractDungeon.gridSelectScreen.open(this.p.exhaustPile, this.amount, TEXT[0], false);
+            tickDuration();
+            return;
+        }
+        if (AbstractDungeon.gridSelectScreen.selectedCards.size() != 0) {
+            for (AbstractCard c : AbstractDungeon.gridSelectScreen.selectedCards) {
+                this.p.hand.addToHand(c);
+                this.p.exhaustPile.removeCard(c);
+                c.lighten(false);
+                c.unhover();
+            }
+            AbstractDungeon.gridSelectScreen.selectedCards.clear();
+            this.p.hand.refreshHandLayout();
+            for (AbstractCard c : this.p.exhaustPile.group) {
+                c.unhover();
+                c.target_x = CardGroup.DISCARD_PILE_X;
+                c.target_y = 0.0F;
+            }
+            this.isDone = true;
+        }
+        tickDuration();
+    }
 }

+ 90 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/action/SadCatAction.java

@@ -1,4 +1,93 @@
 package xyz.luxnk.mxmmod.action;
 
-public class SadCatAction {
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.actions.common.ApplyPowerAction;
+import com.megacrit.cardcrawl.actions.common.HealAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.CardGroup;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.powers.DexterityPower;
+import com.megacrit.cardcrawl.powers.StrengthPower;
+
+public class SadCatAction extends AbstractGameAction {
+
+    public static final String[] TEXT = CardCrawlGame.languagePack.getUIString("SadCatAction").TEXT;
+
+    private AbstractPlayer p;
+
+    public SadCatAction(int amount) {
+        this.p = AbstractDungeon.player;
+        this.setValues(this.p, AbstractDungeon.player, amount);
+        this.actionType = ActionType.CARD_MANIPULATION;
+    }
+
+    @Override
+    public void update() {
+        if ((p.hand.size() >= 10) || (p.discardPile.isEmpty())) {
+            this.isDone = true;
+            return;
+        }
+        AbstractCard card;
+        if (this.p.discardPile.size() == 1) {
+            card = this.p.discardPile.group.get(0);
+            //this.p.exhaustPile.addToTop(card);
+            this.p.discardPile.moveToExhaustPile(card);
+            //this.p.discardPile.removeCard(card);
+            card.lighten(false);
+            this.p.hand.refreshHandLayout();
+            checkCardType(card);
+            this.isDone = true;
+            return;
+        }
+        if (this.duration == 0.5F) {
+            AbstractDungeon.gridSelectScreen.open(this.p.discardPile, this.amount, TEXT[1], false);
+            tickDuration();
+            return;
+        }
+        if (AbstractDungeon.gridSelectScreen.selectedCards.size() != 0) {
+            for (AbstractCard c : AbstractDungeon.gridSelectScreen.selectedCards) {
+                //this.p.exhaustPile.addToTop(c);
+                this.p.discardPile.moveToExhaustPile(c);
+                checkCardType(c);
+                //this.p.discardPile.removeCard(c);
+                c.lighten(false);
+                c.unhover();
+            }
+            AbstractDungeon.gridSelectScreen.selectedCards.clear();
+            this.p.hand.refreshHandLayout();
+            for (AbstractCard c : this.p.discardPile.group) {
+                c.unhover();
+                c.target_x = CardGroup.DISCARD_PILE_X;
+                c.target_y = 0.0F;
+            }
+            this.isDone = true;
+        }
+        tickDuration();
+    }
+
+    public void checkCardType(AbstractCard card) {
+        if (card.type.equals(AbstractCard.CardType.ATTACK)) {
+            AbstractDungeon.actionManager.addToBottom(
+                    new ApplyPowerAction(
+                            p, p, new StrengthPower(p, 1), 1));
+        } else if (card.type.equals(AbstractCard.CardType.SKILL)) {
+            AbstractDungeon.actionManager.addToBottom(
+                    new ApplyPowerAction(
+                            p, p, new DexterityPower(p, 1), 1));
+        } else if (card.type.equals(AbstractCard.CardType.POWER)) {
+            AbstractDungeon.actionManager.addToBottom(
+                    new HealAction(
+                            p, p, 10));
+        } else if (card.type.equals(AbstractCard.CardType.CURSE)) {
+            AbstractDungeon.actionManager.addToBottom(
+                    new ApplyPowerAction(
+                            p, p, new StrengthPower(p, -1), -1));
+        } else if (card.type.equals(AbstractCard.CardType.STATUS)) {
+            AbstractDungeon.actionManager.addToBottom(
+                    new ApplyPowerAction(
+                            p, p, new DexterityPower(p, -1), -1));
+        }
+    }
 }

+ 66 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/Defend_MXM.java

@@ -1,4 +1,69 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class Defend_MXM {
+import basemod.abstracts.CustomCard;
+import basemod.helpers.BaseModCardTags;
+import com.megacrit.cardcrawl.actions.common.GainBlockAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+/**
+ * 防御
+ * cost 1
+ * 获得5点格挡 → 获得8点格挡
+ */
+public class Defend_MXM extends CustomCard {
+
+    public static final String ID = "Defend_MXM";
+    public static final String IMG_PATH = "img/cards/mxmCard.png";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    private static final int COST = 1;
+    private static final int BLOCK_AMT = 5;
+    private static final int UPGRADE_PLUS_BLOCK = 3;
+
+    public Defend_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                AbstractCard.CardType.SKILL,
+                AbstractCardEnum.MXM_COLOR,
+                AbstractCard.CardRarity.BASIC,
+                AbstractCard.CardTarget.SELF
+        );
+        this.tags.add(BaseModCardTags.BASIC_DEFEND);
+        this.baseBlock = BLOCK_AMT;
+    }
+
+    @Override
+    public void use(AbstractPlayer p, AbstractMonster m) {
+        AbstractDungeon.actionManager.addToBottom(
+                new GainBlockAction(p, p, this.block)
+        );
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new Defend_MXM();
+    }
+
+    @Override
+    public boolean isDefend() {
+        return true;
+    }
+
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            upgradeBlock(UPGRADE_PLUS_BLOCK);
+        }
+    }
 }

+ 63 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/LuckyCat_MXM.java

@@ -1,4 +1,66 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class LuckyCat_MXM {
+import basemod.abstracts.CustomCard;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import xyz.luxnk.mxmmod.action.LuckyCatAction;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+public class LuckyCat_MXM extends CustomCard {
+
+    public static final String ID = "LuckyCat_MXM";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String DESCRIPTION_UPG = cardStrings.UPGRADE_DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/skill/lucky_cat.png";
+    private static final int COST = 1;
+
+    public LuckyCat_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.SKILL,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.RARE,
+                CardTarget.SELF
+        );
+        this.exhaust = true;
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+        AbstractDungeon.actionManager.addToBottom(
+                new LuckyCatAction(1)
+        );
+    }
+
+    @Override
+    public boolean canUse(AbstractPlayer p, AbstractMonster m) {
+        if (p.drawPile.isEmpty()) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new LuckyCat_MXM();
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            upgradeBaseCost(0);
+            this.rawDescription = DESCRIPTION_UPG;
+        }
+    }
 }

+ 79 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/PoorWine_MXM.java

@@ -1,4 +1,82 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class PoorWine_MXM {
+import basemod.abstracts.CustomCard;
+import com.megacrit.cardcrawl.actions.common.MakeTempCardInDiscardAction;
+import com.megacrit.cardcrawl.actions.common.MakeTempCardInDrawPileAction;
+import com.megacrit.cardcrawl.actions.defect.DiscardPileToHandAction;
+import com.megacrit.cardcrawl.actions.unique.DeckToHandAction;
+import com.megacrit.cardcrawl.actions.utility.DiscardToHandAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.status.Dazed;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import com.megacrit.cardcrawl.random.Random;
+import xyz.luxnk.mxmmod.action.PoorWineAction;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+public class PoorWine_MXM extends CustomCard {
+
+    public static final String ID = "PoorWine_MXM";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String DESCRIPTION_UPG = cardStrings.UPGRADE_DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/mxmCard.png";
+    private static final int COST = 1;
+
+    public PoorWine_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.SKILL,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.RARE,
+                CardTarget.SELF
+        );
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+
+        int dazedCount = new Random().random(1, 6);
+        System.out.println("酒品极差:随机数值为:" + dazedCount);
+        AbstractDungeon.actionManager.addToBottom(
+                new MakeTempCardInDrawPileAction(
+                        new Dazed(), dazedCount, true, true
+                ));
+        AbstractDungeon.actionManager.addToBottom(
+                new MakeTempCardInDiscardAction(
+                        new Dazed(), (6 - dazedCount)
+                ));
+        AbstractDungeon.actionManager.addToBottom(
+                new DeckToHandAction(1)
+        );
+        AbstractDungeon.actionManager.addToBottom(
+                new DiscardPileToHandAction(1)
+        );
+        if (this.upgraded) {
+            AbstractDungeon.actionManager.addToBottom(
+                    new PoorWineAction(1)
+            );
+        }
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new PoorWine_MXM();
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            this.rawDescription = DESCRIPTION_UPG;
+        }
+    }
 }

+ 63 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/QuickStrike_MXM.java

@@ -1,4 +1,66 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class QuickStrike {
+import basemod.abstracts.CustomCard;
+import basemod.helpers.BaseModCardTags;
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.actions.common.DamageAction;
+import com.megacrit.cardcrawl.actions.common.DrawCardAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.DamageInfo;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+public class QuickStrike_MXM extends CustomCard {
+
+    public static final String ID = "QuickStrike_MXM";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/mxmCard.png";
+    private static final int COST = 1;
+    private static final int ATTACK_DMG = 4;
+    private static final int UPGRADE_PLUS_DMG = 2;
+
+    public QuickStrike_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.ATTACK,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.UNCOMMON,
+                CardTarget.ENEMY
+        );
+        this.baseDamage = ATTACK_DMG;
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+        AbstractDungeon.actionManager.addToBottom(
+                new DamageAction(
+                        abstractMonster,
+                        new DamageInfo(abstractPlayer, this.damage, this.damageTypeForTurn),
+                        AbstractGameAction.AttackEffect.SLASH_HORIZONTAL));
+        AbstractDungeon.actionManager.addToBottom(new DrawCardAction(abstractPlayer, 1));
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new TwinStrike_MXM();
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            upgradeDamage(UPGRADE_PLUS_DMG);
+        }
+    }
+
 }

+ 67 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/SadCat_MXM.java

@@ -1,4 +1,70 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class SadCat_MXM {
+import basemod.abstracts.CustomCard;
+import com.megacrit.cardcrawl.actions.common.DiscardAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import xyz.luxnk.mxmmod.action.SadCatAction;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+public class SadCat_MXM extends CustomCard {
+
+    public static final String ID = "SadCat_MXM";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String DESCRIPTION_UPG = cardStrings.UPGRADE_DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/skill/lucky_cat.png";
+    private static final int COST = 1;
+
+    public SadCat_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.SKILL,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.RARE,
+                CardTarget.SELF
+        );
+        this.exhaust = true;
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+        int amount = 1;
+        if (this.upgraded) {
+            amount = 2;
+        }
+        AbstractDungeon.actionManager.addToBottom(
+                new DiscardAction(abstractPlayer, abstractPlayer, amount, false)
+        );
+        AbstractDungeon.actionManager.addToBottom(
+                new SadCatAction(amount)
+        );
+    }
+
+    @Override
+    public boolean canUse(AbstractPlayer p, AbstractMonster m) {
+        return super.canUse(p, m);
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new SadCat_MXM();
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            this.rawDescription = DESCRIPTION_UPG;
+        }
+    }
 }

+ 73 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/SpeedUp.java

@@ -1,4 +1,76 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class SpeedUp {
+import basemod.abstracts.CustomCard;
+import com.megacrit.cardcrawl.actions.common.ApplyPowerAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import com.megacrit.cardcrawl.powers.DexterityPower;
+import com.megacrit.cardcrawl.powers.LoseDexterityPower;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+/**
+ * 加速
+ * cost 0
+ * 获得2点敏捷。你的回合结束时,失去2点敏捷。
+ */
+public class SpeedUp extends CustomCard {
+
+    public static final String ID = "SpeedUp";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/mxmCard.png";
+    private static final int COST = 0;
+    private static final int DEX_AMOUNT = 2;
+    private static final int UPGRADE_PLUS_DEX = 3;
+
+    public SpeedUp() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.SKILL,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.COMMON,
+                CardTarget.SELF
+        );
+        this.baseMagicNumber = DEX_AMOUNT;
+        this.magicNumber = this.baseMagicNumber;
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+
+        AbstractDungeon.actionManager.addToBottom(
+                new ApplyPowerAction(
+                        abstractPlayer,
+                        abstractPlayer,
+                        new DexterityPower(abstractPlayer, this.magicNumber),
+                        this.magicNumber));
+        AbstractDungeon.actionManager.addToBottom(
+                new ApplyPowerAction(
+                        abstractPlayer,
+                        abstractPlayer,
+                        new LoseDexterityPower(abstractPlayer, this.magicNumber),
+                        this.magicNumber));
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new SpeedUp();
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            upgradeMagicNumber(UPGRADE_PLUS_DEX);
+        }
+    }
 }

+ 71 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/Strike_MXM.java

@@ -1,4 +1,74 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class Strike_MXM {
+import basemod.abstracts.CustomCard;
+import basemod.helpers.BaseModCardTags;
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.actions.common.DamageAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.DamageInfo;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+/**
+ * 爪击
+ * cost 1
+ * 造成6点伤害 → 造成9点伤害
+ */
+public class Strike_MXM extends CustomCard {
+
+    public static final String ID = "Strike_MXM";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/mxmCard.png";
+    private static final int COST = 1;
+    private static final int ATTACK_DMG = 6;
+    private static final int UPGRADE_PLUS_DMG = 3;
+
+    public Strike_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.ATTACK,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.BASIC,
+                CardTarget.ENEMY
+        );
+        this.tags.add(BaseModCardTags.BASIC_STRIKE);
+        this.baseDamage = ATTACK_DMG;
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+        AbstractDungeon.actionManager.addToBottom(
+                new DamageAction(
+                        abstractMonster,
+                        new DamageInfo(abstractPlayer, this.damage, this.damageTypeForTurn),
+                        AbstractGameAction.AttackEffect.SLASH_DIAGONAL));
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new Strike_MXM();
+    }
+
+    @Override
+    public boolean isStrike() {
+        return true;
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            upgradeDamage(UPGRADE_PLUS_DMG);
+        }
+    }
 }

+ 71 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/TwinStrike_MXM.java

@@ -1,4 +1,74 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class TwinStrike_MXM {
+import basemod.abstracts.CustomCard;
+import basemod.helpers.BaseModCardTags;
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.actions.common.DamageAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.DamageInfo;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+/**
+ * 二连斩
+ * cost 1
+ * 造成4点伤害2次 → 造成5点伤害2次
+ */
+public class TwinStrike_MXM extends CustomCard {
+
+    public static final String ID = "TwinStrike_MXM";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/mxmCard.png";
+    private static final int COST = 1;
+    private static final int ATTACK_DMG = 4;
+    private static final int UPGRADE_PLUS_DMG = 1;
+
+    public TwinStrike_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.ATTACK,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.COMMON,
+                CardTarget.ENEMY
+        );
+        this.tags.add(BaseModCardTags.BASIC_STRIKE);
+        this.baseDamage = ATTACK_DMG;
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+        AbstractDungeon.actionManager.addToBottom(
+                new DamageAction(
+                        abstractMonster,
+                        new DamageInfo(abstractPlayer, this.damage, this.damageTypeForTurn),
+                        AbstractGameAction.AttackEffect.SLASH_HORIZONTAL));
+        AbstractDungeon.actionManager.addToBottom(
+                new DamageAction(
+                        abstractMonster,
+                        new DamageInfo(abstractPlayer, this.damage, this.damageTypeForTurn),
+                        AbstractGameAction.AttackEffect.SLASH_VERTICAL));
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new TwinStrike_MXM();
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            upgradeDamage(UPGRADE_PLUS_DMG);
+        }
+    }
 }

+ 79 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/cards/Whirlwind_MXM.java

@@ -1,4 +1,82 @@
 package xyz.luxnk.mxmmod.cards;
 
-public class Whirlwind_MXM {
+import basemod.abstracts.CustomCard;
+import basemod.helpers.BaseModCardTags;
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.actions.animations.VFXAction;
+import com.megacrit.cardcrawl.actions.common.DamageAction;
+import com.megacrit.cardcrawl.actions.common.DamageAllEnemiesAction;
+import com.megacrit.cardcrawl.actions.unique.WhirlwindAction;
+import com.megacrit.cardcrawl.actions.utility.SFXAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.DamageInfo;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.localization.CardStrings;
+import com.megacrit.cardcrawl.monsters.AbstractMonster;
+import com.megacrit.cardcrawl.vfx.combat.CleaveEffect;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+
+/**
+ * 旋风斩击
+ * cost 2
+ * 对所有敌人造成12点伤害 → 对所有敌人造成18点伤害
+ */
+public class Whirlwind_MXM extends CustomCard {
+
+    public static final String ID = "Whirlwind_MXM";
+    private static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(ID);
+    public static final String NAME = cardStrings.NAME;
+    public static final String DESCRIPTION = cardStrings.DESCRIPTION;
+    public static final String IMG_PATH = "img/cards/mxmCard.png";
+    private static final int COST = 2;
+    private static final int ATTACK_DMG = 12;
+    private static final int UPGRADE_PLUS_DMG = 6;
+
+    public Whirlwind_MXM() {
+        super(
+                ID,
+                NAME,
+                IMG_PATH,
+                COST,
+                DESCRIPTION,
+                CardType.ATTACK,
+                AbstractCardEnum.MXM_COLOR,
+                CardRarity.COMMON,
+                CardTarget.ENEMY
+        );
+        this.baseDamage = ATTACK_DMG;
+        this.isMultiDamage = true;
+    }
+
+    @Override
+    public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
+        AbstractDungeon.actionManager.addToBottom(new SFXAction("ATTACK_HEAVY"));
+        AbstractDungeon.actionManager.addToBottom(new VFXAction(abstractPlayer, new CleaveEffect(), 0.1F));
+        AbstractDungeon.actionManager.addToBottom(
+                new DamageAllEnemiesAction(
+                        abstractPlayer,
+                        this.multiDamage,
+                        this.damageTypeForTurn,
+                        AbstractGameAction.AttackEffect.NONE));
+    }
+
+    @Override
+    public AbstractCard makeCopy() {
+        return new Whirlwind_MXM();
+    }
+
+    @Override
+    public boolean isStrike() {
+        return true;
+    }
+
+    @Override
+    public void upgrade() {
+        if (!this.upgraded) {
+            upgradeName();
+            upgradeDamage(UPGRADE_PLUS_DMG);
+        }
+    }
 }

+ 190 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/characters/Mxm.java

@@ -1,4 +1,193 @@
 package xyz.luxnk.mxmmod.characters;
 
-public class Mxm {
+import basemod.abstracts.CustomPlayer;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
+import com.badlogic.gdx.math.MathUtils;
+import com.esotericsoftware.spine.AnimationState;
+import com.megacrit.cardcrawl.actions.AbstractGameAction;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+import com.megacrit.cardcrawl.cards.red.Strike_Red;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+import com.megacrit.cardcrawl.core.CardCrawlGame;
+import com.megacrit.cardcrawl.core.EnergyManager;
+import com.megacrit.cardcrawl.core.Settings;
+import com.megacrit.cardcrawl.events.beyond.SpireHeart;
+import com.megacrit.cardcrawl.events.city.Vampires;
+import com.megacrit.cardcrawl.helpers.FontHelper;
+import com.megacrit.cardcrawl.helpers.ScreenShake;
+import com.megacrit.cardcrawl.screens.CharSelectInfo;
+import com.megacrit.cardcrawl.unlock.UnlockTracker;
+import xyz.luxnk.mxmmod.MxmMod;
+import xyz.luxnk.mxmmod.patches.AbstractCardEnum;
+import xyz.luxnk.mxmmod.patches.MxmModClassEnum;
+
+import java.util.ArrayList;
+
+public class Mxm extends CustomPlayer {
+
+    private static final int ENERGY_PER_TURN = 3; // how much energy you get every turn
+    private static final String MXM_SHOULDER_2 = "img/char/shoulder2.png"; // campfire pose
+    private static final String MXM_SHOULDER_1 = "img/char/shoulder1.png"; // another campfire pose
+    private static final String MXM_CORPSE = "img/char/corpse.png"; // dead corpse
+    private static final String MXM_SKELETON_ATLAS = "img/char/skeleton.atlas"; // spine animation atlas
+    private static final String MXM_SKELETON_JSON = "img/char/skeleton.json"; // spine animation json
+    private static final String MXM_ANIMATION = "Idle";
+
+    private static final String[] ORB_TEXTURES = {
+            "img/UI/EPanel/layer5.png",
+            "img/UI/EPanel/layer4.png",
+            "img/UI/EPanel/layer3.png",
+            "img/UI/EPanel/layer2.png",
+            "img/UI/EPanel/layer1.png",
+            "img/UI/EPanel/layer0.png",
+            "img/UI/EPanel/layer5d.png",
+            "img/UI/EPanel/layer4d.png",
+            "img/UI/EPanel/layer3d.png",
+            "img/UI/EPanel/layer2d.png",
+            "img/UI/EPanel/layer1d.png"
+    };
+    private static final String ORB_VFX = "img/UI/energyBlueVFX.png";
+    private static final float[] LAYER_SPEED =
+            {-40.0F, -32.0F, 20.0F, -20.0F, 0.0F, -10.0F, -8.0F, 5.0F, -5.0F, 0.0F};
+
+    public Mxm(String name) {
+        super(name, MxmModClassEnum.MXM, ORB_TEXTURES, ORB_VFX, LAYER_SPEED, null, null);
+
+        this.dialogX = (this.drawX + 0.0F * Settings.scale); // set location for text bubbles
+        this.dialogY = (this.drawY + 220.0F * Settings.scale); // you can just copy these values
+
+        initializeClass(null, MXM_SHOULDER_2, // required call to load textures and setup energy/loadout
+                MXM_SHOULDER_1,
+                MXM_CORPSE,
+                getLoadout(), 20.0F, -10.0F, 220.0F, 290.0F, new EnergyManager(ENERGY_PER_TURN));
+
+        loadAnimation(MXM_SKELETON_ATLAS, MXM_SKELETON_JSON, 1.0F);
+        // if you're using modified versions of base game animations or made animations in spine make sure to include this bit and the following lines
+        /*AnimationState.TrackEntry e = this.state.setAnimation(0, MXM_ANIMATION, true);
+        e.setTime(e.getEndTime() * MathUtils.random());
+        this.stateData.setMix("Hit", "Idle", 0.1F);
+        e.setTimeScale(1.0F);*/
+
+    }
+
+    @Override
+    public ArrayList<String> getStartingDeck() {
+        ArrayList<String> retVal = new ArrayList();
+        retVal.add("Strike_MXM");
+        retVal.add("Strike_MXM");
+        retVal.add("Strike_MXM");
+        retVal.add("Strike_MXM");
+        retVal.add("TwinStrike_MXM");
+        retVal.add("TwinStrike_MXM");
+        retVal.add("Defend_MXM");
+        retVal.add("Defend_MXM");
+        retVal.add("Defend_MXM");
+        retVal.add("Defend_MXM");
+        retVal.add("PoorWine_MXM");
+        retVal.add("SadCat_MXM");
+        retVal.add("LuckyCat_MXM");
+        return retVal;
+    }
+
+    @Override
+    public ArrayList<String> getStartingRelics() {
+        ArrayList<String> retVal = new ArrayList<>();
+        retVal.add("Hamakagami");
+        UnlockTracker.markRelicAsSeen("Hamakagami");
+        return retVal;
+    }
+
+    public static final int STARTING_HP = 70;
+    public static final int MAX_HP = 70;
+    public static final int STARTING_GOLO = 30; // 猫小咪小姐比较贫穷
+    public static final int HAND_SIZE = 5;
+
+
+    @Override
+    public CharSelectInfo getLoadout() {
+        return new CharSelectInfo("猫小咪",
+                "来自另一个世界的千年猫妖, NL 因为好奇和追求挑战而来到尖塔冒险。",
+                STARTING_HP, MAX_HP, 0, STARTING_GOLO, HAND_SIZE, this,
+                getStartingRelics(),
+                getStartingDeck(),
+                false);
+    }
+
+    @Override
+    public String getTitle(PlayerClass playerClass) {
+        return "千年猫妖";
+    }
+
+    @Override
+    public AbstractCard.CardColor getCardColor() {
+        return AbstractCard.CardColor.RED;
+        //return AbstractCardEnum.MXM_COLOR;
+    }
+
+    @Override
+    public Color getCardRenderColor() {
+        return MxmMod.CYAN;
+    }
+
+    @Override
+    public AbstractCard getStartCardForEvent() {
+        return new Strike_Red();
+    }
+
+    @Override
+    public Color getCardTrailColor() {
+        return MxmMod.CYAN;
+    }
+
+    @Override
+    public int getAscensionMaxHPLoss() {
+        return 5;
+    }
+
+    @Override
+    public BitmapFont getEnergyNumFont() {
+        return FontHelper.energyNumFontBlue;
+    }
+
+    @Override
+    public void doCharSelectScreenSelectEffect() {
+        CardCrawlGame.sound.playA("ATTACK_HEAVY", MathUtils.random(-0.2F, 0.2F));
+        CardCrawlGame.screenShake.shake(ScreenShake.ShakeIntensity.MED, ScreenShake.ShakeDur.SHORT, true);
+    }
+
+    @Override
+    public String getCustomModeCharacterButtonSoundKey() {
+        return "ATTACK_HEAVY";
+    }
+
+    @Override
+    public String getLocalizedCharacterName() {
+        return "猫小咪";
+    }
+
+    @Override
+    public AbstractPlayer newInstance() {
+        return new Mxm(this.name);
+    }
+
+    @Override
+    public String getSpireHeartText() {
+        return SpireHeart.DESCRIPTIONS[8];
+    }
+
+    @Override
+    public Color getSlashAttackColor() {
+        return MxmMod.CYAN;
+    }
+
+    @Override
+    public AbstractGameAction.AttackEffect[] getSpireHeartSlashEffect() {
+        return new AbstractGameAction.AttackEffect[0];
+    }
+
+    @Override
+    public String getVampireText() {
+        return Vampires.DESCRIPTIONS[0];
+    }
 }

+ 8 - 0
mxmmod/src/main/java/xyz/luxnk/mxmmod/patches/AbstractCardEnum.java

@@ -1,4 +1,12 @@
 package xyz.luxnk.mxmmod.patches;
 
+import com.evacipated.cardcrawl.modthespire.lib.SpireEnum;
+import com.megacrit.cardcrawl.cards.AbstractCard;
+
 public class AbstractCardEnum {
+
+    @SpireEnum
+    public static AbstractCard.CardColor MXM_COLOR;
+
+
 }

+ 7 - 0
mxmmod/src/main/java/xyz/luxnk/mxmmod/patches/LibraryTypeEnum.java

@@ -1,4 +1,11 @@
 package xyz.luxnk.mxmmod.patches;
 
+import com.evacipated.cardcrawl.modthespire.lib.SpireEnum;
+import com.megacrit.cardcrawl.helpers.CardLibrary;
+
 public class LibraryTypeEnum {
+
+    @SpireEnum
+    public static CardLibrary.LibraryType MXM_COLOR;
+
 }

+ 6 - 0
mxmmod/src/main/java/xyz/luxnk/mxmmod/patches/MxmModClassEnum.java

@@ -1,4 +1,10 @@
 package xyz.luxnk.mxmmod.patches;
 
+import com.evacipated.cardcrawl.modthespire.lib.SpireEnum;
+import com.megacrit.cardcrawl.characters.AbstractPlayer;
+
 public class MxmModClassEnum {
+
+    @SpireEnum
+    public static AbstractPlayer.PlayerClass MXM;
 }

+ 53 - 1
mxmmod/src/main/java/xyz/luxnk/mxmmod/relics/Hamakagami.java

@@ -1,4 +1,56 @@
 package xyz.luxnk.mxmmod.relics;
 
-public class Hamakagami {
+import basemod.abstracts.CustomRelic;
+import com.megacrit.cardcrawl.actions.common.ApplyPowerAction;
+import com.megacrit.cardcrawl.actions.common.RelicAboveCreatureAction;
+import com.megacrit.cardcrawl.core.Settings;
+import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
+import com.megacrit.cardcrawl.helpers.ImageMaster;
+import com.megacrit.cardcrawl.powers.ArtifactPower;
+import com.megacrit.cardcrawl.powers.DexterityPower;
+import com.megacrit.cardcrawl.relics.AbstractRelic;
+
+public class Hamakagami extends CustomRelic {
+
+    public static final String ID = "Hamakagami";
+    private static final String IMG = "img/relics/hamakagami.png";
+    private static final String IMG_OTL = "img/relics/hamakagami.png";
+
+    private static final int CON_AMT = 1;
+
+    public Hamakagami() {
+        super(
+                ID,
+                ImageMaster.loadImage(IMG),
+                ImageMaster.loadImage(IMG_OTL),
+                RelicTier.STARTER,
+                LandingSound.FLAT
+        );
+        this.counter = 1;
+    }
+
+    @Override
+    public void setCounter(int counter) {
+        this.counter = counter;
+        if (counter == 0) {
+            this.usedUp();
+        }
+    }
+
+    @Override
+    public String getUpdatedDescription() {
+        return this.DESCRIPTIONS[0] + this.DESCRIPTIONS[1] + CON_AMT + this.DESCRIPTIONS[2];
+    }
+
+    @Override
+    public void atBattleStart() {
+        this.flash();
+        AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(AbstractDungeon.player, AbstractDungeon.player, new ArtifactPower(AbstractDungeon.player, CON_AMT), 1));
+        AbstractDungeon.actionManager.addToTop(new RelicAboveCreatureAction(AbstractDungeon.player, this));
+    }
+
+    @Override
+    public AbstractRelic makeCopy() {
+        return new Hamakagami();
+    }
 }

+ 7 - 9
mxmmod/src/main/resources/ModTheSpire.json

@@ -1,17 +1,15 @@
 {
-  "modid": "TS05_Marisa",
-  "name": "Marisa(霧雨 魔理沙)",
+  "modid": "Luxnk_STS_Mod1_Mxm",
+  "name": "猫小咪来了",
   "author_list": [
-    "Flynn",
-    "Hell",
-    "Hohner257",
-    "Samsara"
+    "Luxnk",
+    "litter cat"
   ],
-  "description": "Adds Marisa(霧雨 魔理沙) from Touhou Project as a new playable character.",
+  "description": "增加了一个原创角色——猫小咪",
   "dependencies": [
     "basemod"
   ],
-  "version": "0.14.30",
+  "version": "0.1.0",
   "sts_version": "01-23-2019",
-  "update_json": "https://api.github.com/repos/lf201014/STS_ThMod_MRS/releases/latest"
+  "update_json": ""
 }

BIN
mxmmod/src/main/resources/img/1024/cardOrb.png


BIN
mxmmod/src/main/resources/img/512/cardOrb.png


BIN
mxmmod/src/main/resources/img/cards/skill/lucky_cat.png


BIN
mxmmod/src/main/resources/img/cards/skill/lucky_cat_p.png


+ 2 - 107
mxmmod/src/main/resources/img/char/skeleton.atlas

@@ -3,115 +3,10 @@ skeleton.png
 format: RGBA8888
 filter: Linear,Linear
 repeat: none
-examples/mxm/bozi£¨7
-  rotate: true
-  xy: 379, 22
-  size: 26, 39
-  orig: 512, 512
-  offset: 258, 167
-  index: -1
-examples/mxm/datui£¨9
-  rotate: true
-  xy: 293, 28
-  size: 46, 57
-  orig: 512, 512
-  offset: 248, 80
-  index: -1
-examples/mxm/hidiejie£¨3£©
-  rotate: false
-  xy: 379, 50
-  size: 38, 32
-  orig: 512, 512
-  offset: 257, 219
-  index: -1
-examples/mxm/lian£¨2£©
-  rotate: true
-  xy: 249, 51
-  size: 38, 42
-  orig: 512, 512
-  offset: 265, 188
-  index: -1
-examples/mxm/qunzi£¨8
-  rotate: true
-  xy: 352, 22
-  size: 52, 25
-  orig: 512, 512
-  offset: 236, 119
-  index: -1
-examples/mxm/shou£¨15
-  rotate: true
-  xy: 161, 44
-  size: 20, 15
-  orig: 512, 512
-  offset: 214, 113
-  index: -1
-examples/mxm/toufa£¨13
-  rotate: true
-  xy: 80, 38
-  size: 26, 79
-  orig: 512, 512
-  offset: 290, 134
-  index: -1
-examples/mxm/toufa£¨14
+mxm
   rotate: false
-  xy: 2, 37
-  size: 76, 89
-  orig: 512, 512
-  offset: 226, 135
-  index: -1
-examples/mxm/toufa£¨1£©
-  rotate: true
-  xy: 80, 66
-  size: 60, 100
-  orig: 512, 512
-  offset: 253, 134
-  index: -1
-examples/mxm/xiaotui£¨12
-  rotate: true
-  xy: 182, 48
-  size: 41, 65
-  orig: 512, 512
-  offset: 252, 35
-  index: -1
-examples/mxm/xiezi£¨11
-  rotate: true
-  xy: 249, 21
-  size: 28, 42
-  orig: 512, 512
-  offset: 254, 13
-  index: -1
-examples/mxm/xiuzi£¨4£©
-  rotate: true
-  xy: 379, 84
-  size: 42, 68
-  orig: 512, 512
-  offset: 224, 121
-  index: -1
-examples/mxm/yifu£¨10
-  rotate: true
   xy: 2, 2
-  size: 33, 62
-  orig: 512, 512
-  offset: 271, 115
-  index: -1
-examples/mxm/yifu£¨5£©
-  rotate: true
-  xy: 295, 76
-  size: 50, 82
-  orig: 512, 512
-  offset: 225, 117
-  index: -1
-examples/mxm/yifu£¨6£©
-  rotate: true
-  xy: 449, 82
-  size: 44, 59
-  orig: 512, 512
-  offset: 245, 135
-  index: -1
-examples/mxm/yingzi£¨16
-  rotate: false
-  xy: 182, 91
-  size: 111, 35
+  size: 111, 241
   orig: 512, 512
   offset: 209, 10
   index: -1

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
mxmmod/src/main/resources/img/char/skeleton.json


BIN
mxmmod/src/main/resources/img/char/skeleton.png


BIN
mxmmod/src/main/resources/img/charSelect/mxmButton.png


BIN
mxmmod/src/main/resources/img/charSelect/mxmPortrait.jpg


+ 41 - 0
mxmmod/src/main/resources/localization/mxm_cards-zh.json

@@ -0,0 +1,41 @@
+{
+  "Strike_MXM": {
+    "NAME": "爪击",
+    "DESCRIPTION": "造成 !D! 点伤害。"
+  },
+  "Defend_MXM": {
+    "NAME": "防御",
+    "DESCRIPTION": "获得 !B! 点 格挡 。"
+  },
+  "TwinStrike_MXM": {
+    "NAME": "双重爪击",
+    "DESCRIPTION": "造成 !D! 点伤害两次。"
+  },
+  "QuickStrike_MXM": {
+    "NAME": "快速爪击",
+    "DESCRIPTION": "造成 !D! 点伤害。抽一张牌。"
+  },
+  "Whirlwind_MXM": {
+    "NAME": "穿刺",
+    "DESCRIPTION": "对所有敌人造成 !D! 点伤害。"
+  },
+  "SpeedUp": {
+    "NAME": "加速",
+    "DESCRIPTION": "获得 !M! 点 敏捷 。你的回合结束时,失去 !M! 点 敏捷 。"
+  },
+  "PoorWine_MXM": {
+    "NAME": "酒品极差",
+    "DESCRIPTION": "将6张 晕眩 随机加入抽牌堆与弃牌堆。 NL 在抽牌堆、弃牌堆中各选一张卡加入手牌。",
+    "UPGRADE_DESCRIPTION": "将6张 晕眩 随机加入抽牌堆与弃牌堆。 NL 在抽牌堆、弃牌堆和 消耗牌 中各选一张卡加入手牌。"
+  },
+  "SadCat_MXM": {
+    "NAME": "厄运猫",
+    "DESCRIPTION": "丢弃一张牌,从弃牌堆中选择一张卡消耗,根据消耗的卡获得不同的效果。 NL 消耗 。 NL 厄运猫 。",
+    "UPGRADE_DESCRIPTION": "丢弃两张牌,从弃牌堆中选择两张卡消耗,根据消耗的卡获得不同的效果。 NL 消耗 。 NL 厄运猫 。"
+  },
+  "LuckyCat_MXM": {
+    "NAME": "好运猫",
+    "DESCRIPTION": "选择抽牌堆中的一张卡放入抽牌堆顶端,这张卡在打出之前为0费。 NL 消耗 。",
+    "UPGRADE_DESCRIPTION": "选择抽牌堆中的一张卡放入抽牌堆顶端,这张卡在打出之前为0费。 NL 消耗 。"
+  }
+}

+ 16 - 0
mxmmod/src/main/resources/localization/mxm_keywords-zh.json

@@ -0,0 +1,16 @@
+{
+  "keywords": [
+    {
+      "NAMES": [
+        "厄运猫"
+      ],
+      "DESCRIPTION": "据说黑猫会带来厄运。这张技能牌可以通过消耗的卡牌类型不同获得不同效果: NL ·攻击牌:获得1点力量 NL ·技能牌:获得1点敏捷 NL ·能力牌:恢复10点生命 NL ·诅咒牌:失去1点力量 NL ·状态牌:失去1点敏捷"
+    },
+    {
+      "NAMES": [
+        "消耗牌"
+      ],
+      "DESCRIPTION": "游戏中被消耗掉的牌。"
+    }
+  ]
+}

+ 10 - 0
mxmmod/src/main/resources/localization/mxm_relics-zh.json

@@ -0,0 +1,10 @@
+{
+  "Hamakagami": {
+    "NAME": "破魔镜",
+    "DESCRIPTIONS": [
+      "猫小咪持有的破魔镜,可以抵挡灾祸。 NL ",
+      "在每场战斗开始时,获得 #b",
+      " 层 #y 人工制品 。"
+    ]
+  }
+}

+ 13 - 0
mxmmod/src/main/resources/localization/mxm_ui-zh.json

@@ -0,0 +1,13 @@
+{
+  "SadCatAction": {
+    "TEXT": [
+      "选择要丢弃的牌",
+      "选择要消耗的牌"
+    ]
+  },
+  "LuckyCatAction": {
+    "TEXT": [
+      "选择一张牌放到抽牌堆顶部"
+    ]
+  }
+}