refactor: add more effect

This commit is contained in:
hypercross 2026-04-15 15:41:20 +08:00
parent 7472095822
commit 7b954bb5a5
5 changed files with 65 additions and 30 deletions

View File

@ -6,9 +6,11 @@
# card: 不施加buff对玩家时在玩家弃牌堆创建同名卡牌对敌人无效敌人没有牌堆 # card: 不施加buff对玩家时在玩家弃牌堆创建同名卡牌对敌人无效敌人没有牌堆
# cardDraw: 不施加buff在抓牌堆洗入同名卡牌 # cardDraw: 不施加buff在抓牌堆洗入同名卡牌
# cardHand不施加buff在玩家手牌中创建同名卡牌 # cardHand不施加buff在玩家手牌中创建同名卡牌
# item: 施加buff到周围物品永久生效
# itemUntilPlayed: 施加buff到周围物品物品被打出后失效
id, name, description, timing id, name, description, timing
string, string, string, 'instant'|'temporary'|'lingering'|'permanent'|'posture'|'card'|'cardDraw'|'cardHand' string, string, string, 'instant'|'temporary'|'lingering'|'permanent'|'posture'|'card'|'cardDraw'|'cardHand'|'item'|'itemUntilPlayed'
attack, 攻击, 对对手造成伤害, instant attack, 攻击, 对对手造成伤害, instant
defend, 防御, 抵消下次行动前受到的伤害, posture defend, 防御, 抵消下次行动前受到的伤害, posture
spike, 尖刺, 对攻击者造成X点伤害, lingering spike, 尖刺, 对攻击者造成X点伤害, lingering
@ -28,3 +30,18 @@ charge, 冲锋, 受到或造成的伤害翻倍并消耗等量冲锋, lingering
summonMummy, 召唤木乃伊, 召唤1个木乃伊, instant summonMummy, 召唤木乃伊, 召唤1个木乃伊, instant
summonSandwormLarva, 召唤幼沙虫, 召唤1个幼沙虫, instant summonSandwormLarva, 召唤幼沙虫, 召唤1个幼沙虫, instant
reviveMummy, 复活木乃伊, 复活1个已死亡的木乃伊, instant reviveMummy, 复活木乃伊, 复活1个已死亡的木乃伊, instant
draw, 抓牌, 抓X张牌, instant
crossbow, 十字弩连击, 对同一目标打出其他十字弩, instant
defendNext, 下回合防御, 下回合开始时获得防御, temporary
damageReduce, 减伤, 本回合受到的伤害减少X, temporary
removeWound, 移除伤口, 从牌堆或弃牌堆移除X张伤口, instant
attackBuff, 攻击增益, 周围物品的攻击+X, itemUntilPlayed
defendBuff, 防御增益, 周围物品的防御+X, itemUntilPlayed
gainEnergy, 获得能量, 获得X点能量, instant
energyNext, 下回合获能量, 下回合开始时获得X点能量, temporary
drawNext, 下回合抓牌, 下回合开始时抓X张牌, temporary
defendBuffUntilPlay, 防御增益直到打出, 周围物品的牌防御+X直到打出, itemUntilPlayed
drawChoice, 选择抓牌, 从牌堆周围物品的牌中选择一张加入手牌, instant
burnForEnergy, 消耗获能量, 打出周围物品的牌时消耗并获得X能量, itemUntilPlayed
attackBuffUntilPlay, 攻击增益直到打出, 周围物品的牌攻击+X直到打出, itemUntilPlayed
transformRandom, 随机变牌, 选择一张牌随机变为周围物品的牌, instant

Can't render this file because it has a wrong number of fields in line 12.

View File

@ -2,7 +2,7 @@ type EffectDesertTable = readonly {
readonly id: string; readonly id: string;
readonly name: string; readonly name: string;
readonly description: string; readonly description: string;
readonly timing: "instant" | "temporary" | "lingering" | "permanent" | "posture" | "card" | "cardDraw" | "cardHand"; readonly timing: "instant" | "temporary" | "lingering" | "permanent" | "posture" | "card" | "cardDraw" | "cardHand" | "item" | "itemUntilPlayed";
}[]; }[];
export type EffectDesert = EffectDesertTable[number]; export type EffectDesert = EffectDesertTable[number];

View File

@ -8,29 +8,29 @@
# #
# targetType can be one of: single, none # targetType can be one of: single, none
type,name,shape,costType,costCount,targetType,price,desc type,name,shape,costType,costCount,targetType,price,desc,effects
string,string,string,'energy'|'uses',int,'single'|'none',int,string string,string,string,'energy'|'uses',int,'single'|'none',int,string,['self'|'target'|'all'|'random'; @effectDesert; number][]
weapon,剑,oee,energy,1,single,50,【攻击2】【攻击2】 weapon,剑,oee,energy,1,single,50,【攻击2】【攻击2】,[target;attack;2];[target;attack;2]
weapon,长斧,oees,energy,2,none,80,对全体【攻击5】 weapon,长斧,oees,energy,2,none,80,对全体【攻击5】,[all;attack;5]
weapon,长枪,oeee,energy,1,single,75,【攻击2】【攻击2】【攻击2】 weapon,长枪,oeee,energy,1,single,75,【攻击2】【攻击2】【攻击2】,[target;attack;2];[target;attack;2];[target;attack;2]
weapon,短刀,oe,energy,1,single,40,【攻击3】【攻击3】 weapon,短刀,oe,energy,1,single,40,【攻击3】【攻击3】,[target;attack;3];[target;attack;3]
weapon,飞镖,o,energy,0,single,30,【攻击1】抓一张牌 weapon,飞镖,o,energy,0,single,30,【攻击1】抓一张牌,[target;attack;1];[self;draw;1]
weapon,十字弩,onrersrw,energy,2,single,120,【攻击6】。对同一目标打出其他十字弩 weapon,十字弩,onrersrw,energy,2,single,120,【攻击6】。对同一目标打出其他十字弩,[target;attack;6];[self;crossbow;0]
armor,盾,oesw,energy,1,none,50,【防御3】 armor,盾,oesw,energy,1,none,50,【防御3】,[self;defend;3]
armor,斗笠,oerwrn,energy,2,none,90,【防御8】 armor,斗笠,oerwrn,energy,2,none,90,【防御8】,[self;defend;8]
armor,披风,oers,energy,1,none,45,【防御2】下回合【防御2】 armor,披风,oers,energy,1,none,45,【防御2】下回合【防御2】,[self;defend;2];[self;defendNext;2]
armor,护腕,o,energy,0,none,25,【防御1】抓1张牌 armor,护腕,o,energy,0,none,25,【防御1】抓1张牌,[self;defend;1];[self;draw;1]
armor,大盾,oesswn,energy,1,none,70,【防御5】 armor,大盾,oesswn,energy,1,none,70,【防御5】,[self;defend;5]
armor,锁子甲,oers,energy,1,none,60,本回合受到伤害-3 armor,锁子甲,oers,energy,1,none,60,本回合受到伤害-3,[self;damageReduce;3]
consumable,绷带,o,uses,3,none,20,从牌堆或弃牌堆随机移除1张伤口 consumable,绷带,o,uses,3,none,20,从牌堆或弃牌堆随机移除1张伤口,[self;removeWound;1]
consumable,淬毒药剂,o,uses,3,none,30,周围物品的【攻击】+2 consumable,淬毒药剂,o,uses,3,none,30,周围物品的【攻击】+2,[self;attackBuff;2]
consumable,强固药剂,o,uses,3,none,30,周围物品的【防御】+2 consumable,强固药剂,o,uses,3,none,30,周围物品的【防御】+2,[self;defendBuff;2]
consumable,活力药剂,o,uses,3,none,25,获得1点能量 consumable,活力药剂,o,uses,3,none,25,获得1点能量,[self;gainEnergy;1]
consumable,集中药剂,o,uses,3,none,25,抓2张牌 consumable,集中药剂,o,uses,3,none,25,抓2张牌,[self;draw;2]
consumable,治疗药剂,o,uses,3,none,35,从牌堆或弃牌堆移除3张伤口 consumable,治疗药剂,o,uses,3,none,35,从牌堆或弃牌堆移除3张伤口,[self;removeWound;3]
tool,水袋,os,energy,1,none,35,下回合开始时获得1能量抓2张牌 tool,水袋,os,energy,1,none,35,下回合开始时获得1能量抓2张牌,[self;energyNext;1];[self;drawNext;2]
tool,绳索,ose,energy,1,none,30,周围物品的牌【防御】+2直到打出 tool,绳索,ose,energy,1,none,30,周围物品的牌【防御】+2直到打出,[self;defendBuffUntilPlay;2]
tool,腰带,owre,energy,0,none,40,从牌堆周围物品的牌当中选择一张加入手牌 tool,腰带,owre,energy,0,none,40,从牌堆周围物品的牌当中选择一张加入手牌,[self;drawChoice;1]
tool,火把,on,energy,1,none,25,下次打出周围物品的牌时将其消耗并获得1能量 tool,火把,on,energy,1,none,25,下次打出周围物品的牌时将其消耗并获得1能量,[self;burnForEnergy;1]
tool,磨刀石,o,energy,1,none,30,周围物品的牌【攻击】+3直到打出 tool,磨刀石,o,energy,1,none,30,周围物品的牌【攻击】+3直到打出,[self;attackBuffUntilPlay;3]
tool,铁匠锤,oers,energy,1,none,45,从牌堆/弃牌堆选择一张牌,随机变为一张周围物品的牌 tool,铁匠锤,oers,energy,1,none,45,从牌堆/弃牌堆选择一张牌,随机变为一张周围物品的牌,[self;transformRandom;1]

1 # type can be one of: weapon, armor, consumable, tool
8 #
9 # targetType can be one of: single, none
10 type,name,shape,costType,costCount,targetType,price,desc type,name,shape,costType,costCount,targetType,price,desc,effects
11 string,string,string,'energy'|'uses',int,'single'|'none',int,string string,string,string,'energy'|'uses',int,'single'|'none',int,string,['self'|'target'|'all'|'random'; @effectDesert; number][]
12 weapon,剑,oee,energy,1,single,50,【攻击2】【攻击2】 weapon,剑,oee,energy,1,single,50,【攻击2】【攻击2】,[target;attack;2];[target;attack;2]
13 weapon,长斧,oees,energy,2,none,80,对全体【攻击5】 weapon,长斧,oees,energy,2,none,80,对全体【攻击5】,[all;attack;5]
14 weapon,长枪,oeee,energy,1,single,75,【攻击2】【攻击2】【攻击2】 weapon,长枪,oeee,energy,1,single,75,【攻击2】【攻击2】【攻击2】,[target;attack;2];[target;attack;2];[target;attack;2]
15 weapon,短刀,oe,energy,1,single,40,【攻击3】【攻击3】 weapon,短刀,oe,energy,1,single,40,【攻击3】【攻击3】,[target;attack;3];[target;attack;3]
16 weapon,飞镖,o,energy,0,single,30,【攻击1】,抓一张牌 weapon,飞镖,o,energy,0,single,30,【攻击1】,抓一张牌,[target;attack;1];[self;draw;1]
17 weapon,十字弩,onrersrw,energy,2,single,120,【攻击6】。对同一目标打出其他十字弩 weapon,十字弩,onrersrw,energy,2,single,120,【攻击6】。对同一目标打出其他十字弩,[target;attack;6];[self;crossbow;0]
18 armor,盾,oesw,energy,1,none,50,【防御3】 armor,盾,oesw,energy,1,none,50,【防御3】,[self;defend;3]
19 armor,斗笠,oerwrn,energy,2,none,90,【防御8】 armor,斗笠,oerwrn,energy,2,none,90,【防御8】,[self;defend;8]
20 armor,披风,oers,energy,1,none,45,【防御2】,下回合【防御2】 armor,披风,oers,energy,1,none,45,【防御2】,下回合【防御2】,[self;defend;2];[self;defendNext;2]
21 armor,护腕,o,energy,0,none,25,【防御1】,抓1张牌 armor,护腕,o,energy,0,none,25,【防御1】,抓1张牌,[self;defend;1];[self;draw;1]
22 armor,大盾,oesswn,energy,1,none,70,【防御5】 armor,大盾,oesswn,energy,1,none,70,【防御5】,[self;defend;5]
23 armor,锁子甲,oers,energy,1,none,60,本回合受到伤害-3 armor,锁子甲,oers,energy,1,none,60,本回合受到伤害-3,[self;damageReduce;3]
24 consumable,绷带,o,uses,3,none,20,从牌堆或弃牌堆随机移除1张伤口 consumable,绷带,o,uses,3,none,20,从牌堆或弃牌堆随机移除1张伤口,[self;removeWound;1]
25 consumable,淬毒药剂,o,uses,3,none,30,周围物品的【攻击】+2 consumable,淬毒药剂,o,uses,3,none,30,周围物品的【攻击】+2,[self;attackBuff;2]
26 consumable,强固药剂,o,uses,3,none,30,周围物品的【防御】+2 consumable,强固药剂,o,uses,3,none,30,周围物品的【防御】+2,[self;defendBuff;2]
27 consumable,活力药剂,o,uses,3,none,25,获得1点能量 consumable,活力药剂,o,uses,3,none,25,获得1点能量,[self;gainEnergy;1]
28 consumable,集中药剂,o,uses,3,none,25,抓2张牌 consumable,集中药剂,o,uses,3,none,25,抓2张牌,[self;draw;2]
29 consumable,治疗药剂,o,uses,3,none,35,从牌堆或弃牌堆移除3张伤口 consumable,治疗药剂,o,uses,3,none,35,从牌堆或弃牌堆移除3张伤口,[self;removeWound;3]
30 tool,水袋,os,energy,1,none,35,下回合开始时,获得1能量,抓2张牌 tool,水袋,os,energy,1,none,35,下回合开始时,获得1能量,抓2张牌,[self;energyNext;1];[self;drawNext;2]
31 tool,绳索,ose,energy,1,none,30,周围物品的牌【防御】+2直到打出 tool,绳索,ose,energy,1,none,30,周围物品的牌【防御】+2直到打出,[self;defendBuffUntilPlay;2]
32 tool,腰带,owre,energy,0,none,40,从牌堆周围物品的牌当中选择一张加入手牌 tool,腰带,owre,energy,0,none,40,从牌堆周围物品的牌当中选择一张加入手牌,[self;drawChoice;1]
33 tool,火把,on,energy,1,none,25,下次打出周围物品的牌时,将其消耗并获得1能量 tool,火把,on,energy,1,none,25,下次打出周围物品的牌时,将其消耗并获得1能量,[self;burnForEnergy;1]
34 tool,磨刀石,o,energy,1,none,30,周围物品的牌【攻击】+3直到打出 tool,磨刀石,o,energy,1,none,30,周围物品的牌【攻击】+3直到打出,[self;attackBuffUntilPlay;3]
35 tool,铁匠锤,oers,energy,1,none,45,从牌堆/弃牌堆选择一张牌,随机变为一张周围物品的牌 tool,铁匠锤,oers,energy,1,none,45,从牌堆/弃牌堆选择一张牌,随机变为一张周围物品的牌,[self;transformRandom;1]
36

View File

@ -1,3 +1,5 @@
import type { EffectDesert } from './effectDesert.csv';
type HeroItemFighter1Table = readonly { type HeroItemFighter1Table = readonly {
readonly type: string; readonly type: string;
readonly name: string; readonly name: string;
@ -7,6 +9,7 @@ type HeroItemFighter1Table = readonly {
readonly targetType: "single" | "none"; readonly targetType: "single" | "none";
readonly price: number; readonly price: number;
readonly desc: string; readonly desc: string;
readonly effects: readonly ["self" | "target" | "all" | "random", EffectDesert, number];
}[]; }[];
export type HeroItemFighter1 = HeroItemFighter1Table[number]; export type HeroItemFighter1 = HeroItemFighter1Table[number];

View File

@ -26,6 +26,7 @@ describe('heroItemFighter1.csv import', () => {
expect(item).toHaveProperty('costCount'); expect(item).toHaveProperty('costCount');
expect(item).toHaveProperty('targetType'); expect(item).toHaveProperty('targetType');
expect(item).toHaveProperty('desc'); expect(item).toHaveProperty('desc');
expect(item).toHaveProperty('effects');
} }
}); });
@ -75,6 +76,17 @@ describe('heroItemFighter1.csv import', () => {
expect(typeCounts['consumable']).toBe(6); expect(typeCounts['consumable']).toBe(6);
expect(typeCounts['tool']).toBe(6); expect(typeCounts['tool']).toBe(6);
}); });
it('should have effects with target, effect ref, and value', () => {
for (const item of heroItemFighter1Data) {
expect(Array.isArray(item.effects)).toBe(true);
for (const [target, effect, value] of item.effects) {
expect(target === 'self' || target === 'target' || target === 'all' || target === 'random').toBe(true);
expect(typeof effect === 'string' || typeof effect === 'object').toBe(true);
expect(typeof value).toBe('number');
}
}
});
}); });
describe('encounterDesert.csv import', () => { describe('encounterDesert.csv import', () => {
@ -135,7 +147,7 @@ describe('effectDesert.csv import', () => {
}); });
it('should have expected number of effects', () => { it('should have expected number of effects', () => {
expect(effectDesertData.length).toBe(19); expect(effectDesertData.length).toBe(34);
}); });
it('should have correct fields for each effect', () => { it('should have correct fields for each effect', () => {
@ -148,7 +160,7 @@ describe('effectDesert.csv import', () => {
}); });
it('should have valid timing values', () => { it('should have valid timing values', () => {
const validTimings = ['instant', 'temporary', 'lingering', 'permanent', 'posture', 'card', 'cardDraw', 'cardHand']; const validTimings = ['instant', 'temporary', 'lingering', 'permanent', 'posture', 'card', 'cardDraw', 'cardHand', 'item', 'itemUntilPlayed'];
for (const effect of effectDesertData) { for (const effect of effectDesertData) {
expect(validTimings).toContain(effect.timing); expect(validTimings).toContain(effect.timing);
} }
@ -160,6 +172,9 @@ describe('effectDesert.csv import', () => {
expect(ids).toContain('defend'); expect(ids).toContain('defend');
expect(ids).toContain('spike'); expect(ids).toContain('spike');
expect(ids).toContain('venom'); expect(ids).toContain('venom');
expect(ids).toContain('draw');
expect(ids).toContain('removeWound');
expect(ids).toContain('gainEnergy');
}); });
}); });