(许多代码是反编译学来的,如有雷同可能我参考的就是你的代码【doge】)
书接上文
准备工作完成,可以开始写东西了。
卡牌
制作卡牌需要继承CustomCard
先看构造方法
public CustomCard(String id, String name, String img, int cost, String rawDescription, AbstractCard.CardType type, AbstractCard.CardColor color, AbstractCard.CardRarity rarity, AbstractCard.CardTarget target) {
super(id, name, "status/beta", "status/beta", cost, rawDescription, type, color, rarity, target);
this.textureImg = img;
if (img != null) {
this.loadCardImage(img);
}
this.initializeInherentMods();
}
public CustomCard(String id, String name, RegionName img, int cost, String rawDescription, AbstractCard.CardType type, AbstractCard.CardColor color, AbstractCard.CardRarity rarity, AbstractCard.CardTarget target) {
super(id, name, "status/beta", img.name, cost, rawDescription, type, color, rarity, target);
this.initializeInherentMods();
}
一般调用的是第一个
id即卡牌的id,name为卡牌名,img为卡绘路径,cost 费用,rawDescription 描述,type 类型(攻击能力技能),color卡色(即属于哪一卡池),rarity稀有度,target目标
搞个抽象类
public abstract class AbstractModCard extends CustomCard {
public AbstractModCard(String id, String img, int cost, AbstractCard.CardType type, AbstractCard.CardColor color, AbstractCard.CardRarity rarity, AbstractCard.CardTarget target) {
super(id, CardCrawlGame.languagePack.getCardStrings(id).NAME, img, cost, CardCrawlGame.languagePack.getCardStrings(id).DESCRIPTION, type, color, rarity, target);
initSwitches();
}
public void initSwitches(){
//初始化一下这张卡
}
@Override
public void upgrade() {
//升级
}
@Override
public void use(AbstractPlayer abstractPlayer, AbstractMonster abstractMonster) {
//打出的效果
}
@Override
public boolean canUse(AbstractPlayer p,AbstractMonster m){
//什么时候能用?
return super.canUse(p,m);
}
}
实际上是读了本地化文件的东西,id写规范点就很舒服了
当然你完全可以多重载几次构造方法,比如默认使用自定义卡池,使用id通过字符串操作默认设置img路径(当然你得在对应的地方放卡绘)
类似这样
public static String getResPath(){
return "ModResources/";
}
public static String getImgPath(){
return getResPath() + "img/";
}
public static String makeCardImgPath(String cardName){
return getImgPath() + "cards/" + cardName + ".png";
}
public AbstractModCard(String id, String name, String img, int cost, String rawDescription, CardType type, CardColor color, CardRarity rarity, CardTarget target) {
super(id, name, img, cost, rawDescription, type, color, rarity, target);
initSwitches();
}
public AbstractModCard(String id, String img, int cost, AbstractCard.CardType type, AbstractCard.CardColor color, AbstractCard.CardRarity rarity, AbstractCard.CardTarget target) {
super(id, CardCrawlGame.languagePack.getCardStrings(id).NAME, img, cost, CardCrawlGame.languagePack.getCardStrings(id).DESCRIPTION, type, color, rarity, target);
initSwitches();
}
public AbstractModCard(String id, int cost, AbstractCard.CardType type, AbstractCard.CardColor color, AbstractCard.CardRarity rarity, AbstractCard.CardTarget target) {
super(id, CardCrawlGame.languagePack.getCardStrings(id).NAME, ModInfo.makeCardImgPath(id.split(":")[1]), cost, CardCrawlGame.languagePack.getCardStrings(id).DESCRIPTION, type, color, rarity, target);
initSwitches();
}
public AbstractModCard(String id, int cost, AbstractCard.CardType type, AbstractCard.CardRarity rarity, AbstractCard.CardTarget target) {
super(id, CardCrawlGame.languagePack.getCardStrings(id).NAME, ModInfo.makeCardImgPath(id.split(":")[1]), cost, CardCrawlGame.languagePack.getCardStrings(id).DESCRIPTION, type, CardEnum.MY_CARD, rarity, target);
initSwitches();
}
public AbstractModCard(String id, int cost, AbstractCard.CardType type, AbstractCard.CardRarity rarity) {
super(id, CardCrawlGame.languagePack.getCardStrings(id).NAME, ModInfo.makeCardImgPath(id.split(":")[1]), cost, CardCrawlGame.languagePack.getCardStrings(id).DESCRIPTION, type, CardEnum.MY_CARD, rarity, CardTarget.NONE);
initSwitches();
}
以下代码使用了上述构造方法,不多说了
做张打防
代码
public class Strike extends AbstractModCard {
public static final String ID = "Mod:Strike";
public Strike() {
super(ID,1,CardType.ATTACK,CardRarity.BASIC,CardTarget.ENEMY);
//this.tags.add(BaseModCardTags.BASIC_STRIKE);
this.baseDamage = 6;
}
public void use(AbstractPlayer p, AbstractMonster m){
addToBot(new DamageAction(m,new DamageInfo(p,this.damage,this.damageTypeForTurn), AbstractGameAction.AttackEffect.SLASH_HORIZONTAL));
}
@Override
//升级
public void upgrade(){
if(!this.upgraded){//只能升级一次
upgradeName();//变个名(给个加号
upgradeDamage(4);//伤害加4
}
}
}
public class Defend extends AbstractModCard {
public static final String ID = "Mod:Defend";
public Defend(){
super(ID,1,CardType.SKILL,CardRarity.BASIC,CardTarget.SELF);
this.tags.add(BaseModCardTags.BASIC_DEFEND);
this.baseBlock = 5;
}
public void use(AbstractPlayer p, AbstractMonster m){
addToBot(new GainBlockAction(p,this.block));
}
public void upgrade(){
if(!this.upgraded){
upgradeName();
upgradeBlock(3);
}
}
}
实际上卡牌使用后一般会触发一个action来实现想要的效果。
如打击使用DamageAction造成伤害,防使用GainBlockAction来获取格挡
addToBot方法就是将一个action放在底部,等待其他action完成再进行。
同理也可以使用addToTop方法放在顶部优先执行。
自己也可以自定义action(先挖个坑
卡绘
打防的卡绘不要忘记加上,在正确的路径中放图片,图片的名字也要跟自己在代码中填的一样。
同时,一张卡需要两张分辨率不一样的图片,如打击需要配一张Strike.png(250×190)和一张Strike_p.png(500×380)
本地化
cards.json
{
"Mod:Strike":{
"NAME" :"打击",
"DESCRIPTION": "造成 !D! 点伤害。"
},
"Mod:Defend":{
"NAME": "防御",
"DESCRIPTION": "获得 !B! 点 格挡 。"
}
}
!D!对应baseDamage值
!B!对应baseBlock值
NL 换行
遇到关键词(keyword)时
如"格挡"为在游戏中会被解释的关键词,需要两边专门空一格出来
如文本 : ...获得 格挡 后....
( !D! 之类的同理)
注册
还记得那个注册类吗?我们的自定义内容都必须先注册才能被成功加载!
假设我们的注册类为Main
@SpireInitializer
public class Main{
public static void initialize(){
new Main();
}
}
我们在前文自定义了卡池MY_CARD,需要先注册才能使用
需要有卡牌的模板,建议直接拿官方的图来改
belike:
这里需要调用BaseMod.addColor
先来看看这个方法
public static void addColor(AbstractCard.CardColor color, Color everythingColor, String attackBg, String skillBg, String powerBg, String energyOrb, String attackBgPortrait, String skillBgPortrait, String powerBgPortrait, String energyOrbPortrait, String cardEnergyOrb) {
addColor(color, everythingColor, everythingColor, everythingColor, everythingColor, everythingColor, everythingColor, everythingColor, attackBg, skillBg, powerBg, energyOrb, attackBgPortrait, skillBgPortrait, powerBgPortrait, energyOrbPortrait, cardEnergyOrb);
}
各个参数分别为:要添加的卡色、颜色、攻击模板、技能模板、能力模板、能量球显示(就是左下角显示你有多少费的)、攻击模板(大)、技能模板(大)、能力模板(大)、卡面能量球(大)、卡面能量球(小)
有大小之分是因为你选中一张卡它会变答辩高
拿官方的图做参考,自己ps设计一下像素大小就可以了(只是练习照搬就可以)
@SpireInitializer
public class Main{
public Main(){
BaseMod.subscribe(this);
BaseMod.addColor(MY_CARD,Color.BLUE,......);//后面路径上面已说过,自己填
}
public static void initialize(){
new Main();
}
}
添加完颜色,可以注册本地化了
为了方便可以写个静态方法
public static String makeLocalizationPath(String lang,String content){
return getResPath() + "localization/" + lang + "/" + content + ".json";
}
@Override
public void receiveEditStrings() {
if (Settings.language == Settings.GameLanguage.ZHS) {
lang = "ZHS";
} else {
lang = "ENG";
}
BaseMod.loadCustomStringsFile(CardStrings.class, ModInfo.makeLocalizationPath(lang, "cards"));
//BaseMod.loadCustomStringsFile(CharacterStrings.class, ModInfo.makeLocalizationPath(lang, "characters"));
//BaseMod.loadCustomStringsFile(RelicStrings.class, ModInfo.makeLocalizationPath(lang, "relics"));
//BaseMod.loadCustomStringsFile(PotionStrings.class, ModInfo.makeLocalizationPath(lang, "potions"));
//BaseMod.loadCustomStringsFile(PowerStrings.class, ModInfo.makeLocalizationPath(lang, "powers"));
//BaseMod.loadCustomStringsFile(UIStrings.class,ModInfo.makeLocalizationPath(lang, "UIs"));
}
注释起来的之后会用到
如果不打算做别的语言可以不用细致划分
注册卡牌
@Override
public void receiveEditCards() {
BaseMod.addCard(new Strike());
BaseMod.addCard(new Defend());
}
也可以一键注册
@Override
public void receiveEditCards() {
String cardsClassPath = "xxx.cards";//填卡牌类的路径
(new AutoAdd(ModInfo.MOD_NAME)).packageFilter(cardsClassPath).setDefaultSeen(true).any(AbstractCard.class, (info, card) -> {
BaseMod.addCard(card);
});
}
拿下!!
未完待续。。。。。。