Compare commits
2 Commits
f4c96a4a72
...
63e55a828e
| Author | SHA1 | Date |
|---|---|---|
|
|
63e55a828e | |
|
|
8ec95cbf81 |
|
|
@ -1,5 +1,5 @@
|
||||||
# type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard'
|
# type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard'
|
||||||
# type CardEffectTarget = 'user' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player'
|
# type CardEffectTarget = 'source' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player'
|
||||||
# type CardEffectList = [effect: @effect; stacks: number][]
|
# type CardEffectList = [effect: @effect; stacks: number][]
|
||||||
|
|
||||||
id,card,trigger,target,effects
|
id,card,trigger,target,effects
|
||||||
|
|
@ -9,28 +9,28 @@ greataxe,greataxe,onPlay,eachTarget,[attack;5]
|
||||||
spear,spear,onPlay,eachTarget,[attack;2];[attack;2];[attack;2]
|
spear,spear,onPlay,eachTarget,[attack;2];[attack;2];[attack;2]
|
||||||
dagger,dagger,onPlay,eachTarget,[attack;3];[attack;3]
|
dagger,dagger,onPlay,eachTarget,[attack;3];[attack;3]
|
||||||
dart,dart,onPlay,eachTarget,[attack;1]
|
dart,dart,onPlay,eachTarget,[attack;1]
|
||||||
dart-draw,dart,onPlay,user,[draw;1]
|
dart-draw,dart,onPlay,source,[draw;1]
|
||||||
crossbow,crossbow,onPlay,eachTarget,[attack;6]
|
crossbow,crossbow,onPlay,eachTarget,[attack;6]
|
||||||
crossbow-combo,crossbow,onPlay,user,[crossbow;0]
|
crossbow-combo,crossbow,onPlay,source,[crossbow;0]
|
||||||
shield,shield,onPlay,user,[defend;3]
|
shield,shield,onPlay,source,[defend;3]
|
||||||
hat,hat,onPlay,user,[defend;8]
|
hat,hat,onPlay,source,[defend;8]
|
||||||
cape,cape,onPlay,user,[defend;2];[defendNext;2]
|
cape,cape,onPlay,source,[defend;2];[defendNext;2]
|
||||||
bracer,bracer,onPlay,user,[defend;1];[draw;1]
|
bracer,bracer,onPlay,source,[defend;1];[draw;1]
|
||||||
greatshield,greatshield,onPlay,user,[defend;5]
|
greatshield,greatshield,onPlay,source,[defend;5]
|
||||||
chainmail,chainmail,onPlay,user,[damageReduce;3]
|
chainmail,chainmail,onPlay,source,[damageReduce;3]
|
||||||
bandage,bandage,onPlay,user,[removeWound;1]
|
bandage,bandage,onPlay,source,[removeWound;1]
|
||||||
poisonPotion,poisonPotion,onPlay,user,[attackBuff;2]
|
poisonPotion,poisonPotion,onPlay,source,[attackBuff;2]
|
||||||
fortifyPotion,fortifyPotion,onPlay,user,[defendBuff;2]
|
fortifyPotion,fortifyPotion,onPlay,source,[defendBuff;2]
|
||||||
vitalityPotion,vitalityPotion,onPlay,user,[gainEnergy;1]
|
vitalityPotion,vitalityPotion,onPlay,source,[gainEnergy;1]
|
||||||
focusPotion,focusPotion,onPlay,user,[draw;2]
|
focusPotion,focusPotion,onPlay,source,[draw;2]
|
||||||
healingPotion,healingPotion,onPlay,user,[removeWound;3]
|
healingPotion,healingPotion,onPlay,source,[removeWound;3]
|
||||||
waterBag,waterBag,onPlay,user,[energyNext;1];[drawNext;2]
|
waterBag,waterBag,onPlay,source,[energyNext;1];[drawNext;2]
|
||||||
rope,rope,onPlay,user,[defendBuffUntilPlay;2]
|
rope,rope,onPlay,source,[defendBuffUntilPlay;2]
|
||||||
belt,belt,onPlay,user,[drawChoice;1]
|
belt,belt,onPlay,source,[drawChoice;1]
|
||||||
torch,torch,onPlay,user,[burnForEnergy;1]
|
torch,torch,onPlay,source,[burnForEnergy;1]
|
||||||
whetstone,whetstone,onPlay,user,[attackBuffUntilPlay;3]
|
whetstone,whetstone,onPlay,source,[attackBuffUntilPlay;3]
|
||||||
blacksmithHammer,blacksmithHammer,onPlay,user,[transformRandom;1]
|
blacksmithHammer,blacksmithHammer,onPlay,source,[transformRandom;1]
|
||||||
venom,venom,onDiscard,user,[attack;3]
|
venom,venom,onDiscard,source,[attack;3]
|
||||||
curse,curse,onDraw,user,[curse;1]
|
curse,curse,onDraw,source,[curse;1]
|
||||||
static,static,onDraw,user,[static;1]
|
static,static,onDraw,source,[static;1]
|
||||||
vultureEye,vultureEye,onDraw,user,[expose;3]
|
vultureEye,vultureEye,onDraw,source,[expose;3]
|
||||||
|
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type { Card } from './card.csv';
|
||||||
import type { Effect } from './effect.csv';
|
import type { Effect } from './effect.csv';
|
||||||
|
|
||||||
export type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard';
|
export type CardEffectTrigger = 'onPlay' | 'onDraw' | 'onDiscard';
|
||||||
export type CardEffectTarget = 'user' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player';
|
export type CardEffectTarget = 'source' | 'eachTarget' | 'eachEnemy' | 'randomEnemy' | 'player';
|
||||||
export type CardEffectList = [effect: Effect, stacks: number][];
|
export type CardEffectList = [effect: Effect, stacks: number][];
|
||||||
|
|
||||||
type CardEffectTable = readonly {
|
type CardEffectTable = readonly {
|
||||||
|
|
|
||||||
|
|
@ -6,50 +6,50 @@
|
||||||
# initBuffs: initial buffs for this intent (applied when intent becomes active)
|
# initBuffs: initial buffs for this intent (applied when intent becomes active)
|
||||||
# effects: effects executed when this intent is active
|
# effects: effects executed when this intent is active
|
||||||
|
|
||||||
# type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player'
|
# type IntentEffectTarget = 'source' | 'eachEnemy' | 'randomEnemy' | 'player'
|
||||||
# type IntentEffect = [IntentEffectTarget;@effect;number]
|
# type IntentEffect = [IntentEffectTarget;@effect;number]
|
||||||
# type IntentEffectList = IntentEffect[]
|
# type IntentEffectList = IntentEffect[]
|
||||||
|
|
||||||
id,enemy,initialIntent,nextIntents,brokenIntent,effects
|
id,enemy,initialIntent,nextIntents,brokenIntent,effects
|
||||||
string,@enemy,boolean,@intent[],@intent[],IntentEffectList
|
string,@enemy,boolean,@intent[],@intent[],IntentEffectList
|
||||||
仙人掌怪-boost,仙人掌怪,true,仙人掌怪-boost;仙人掌怪-defend,,[user;spike;1];[user;defend;4]
|
仙人掌怪-boost,仙人掌怪,true,仙人掌怪-boost;仙人掌怪-defend,,[source;spike;1];[source;defend;4]
|
||||||
仙人掌怪-defend,仙人掌怪,false,仙人掌怪-attack,,[user;defend;8]
|
仙人掌怪-defend,仙人掌怪,false,仙人掌怪-attack,,[source;defend;8]
|
||||||
仙人掌怪-attack,仙人掌怪,false,仙人掌怪-boost,,[player;attack;5]
|
仙人掌怪-attack,仙人掌怪,false,仙人掌怪-boost,,[player;attack;5]
|
||||||
蛇-poison,蛇,true,蛇-attack;蛇-attack,,[player;venom;1];[player;attack;4]
|
蛇-poison,蛇,true,蛇-attack;蛇-attack,,[player;venom;1];[player;attack;4]
|
||||||
蛇-attack,蛇,false,蛇-poison;蛇-boost,,[player;attack;6]
|
蛇-attack,蛇,false,蛇-poison;蛇-boost,,[player;attack;6]
|
||||||
蛇-boost,蛇,false,蛇-poison;蛇-attack,,[user;defend;3];[player;venom;1]
|
蛇-boost,蛇,false,蛇-poison;蛇-attack,,[source;defend;3];[player;venom;1]
|
||||||
木乃伊-attack,木乃伊,true,木乃伊-defend;木乃伊-curse,,[player;attack;6]
|
木乃伊-attack,木乃伊,true,木乃伊-defend;木乃伊-curse,,[player;attack;6]
|
||||||
木乃伊-defend,木乃伊,false,木乃伊-attack,,[user;defend;6]
|
木乃伊-defend,木乃伊,false,木乃伊-attack,,[source;defend;6]
|
||||||
木乃伊-curse,木乃伊,false,木乃伊-defend;木乃伊-attack,木乃伊-attack,[player;curse;1]
|
木乃伊-curse,木乃伊,false,木乃伊-defend;木乃伊-attack,木乃伊-attack,[player;curse;1]
|
||||||
枪手-aim,枪手,true,枪手-attack,,[user;aim;2]
|
枪手-aim,枪手,true,枪手-attack,,[source;aim;2]
|
||||||
枪手-attack,枪手,false,枪手-aim;枪手-defend,枪手-aim,[player;attack;8]
|
枪手-attack,枪手,false,枪手-aim;枪手-defend,枪手-aim,[player;attack;8]
|
||||||
枪手-defend,枪手,false,枪手-aim,枪手-aim,[user;defend;5]
|
枪手-defend,枪手,false,枪手-aim,枪手-aim,[source;defend;5]
|
||||||
风卷草-boost,风卷草,true,风卷草-defend;风卷草-defend;风卷草-boost,,[user;roll;5];[user;defend;4]
|
风卷草-boost,风卷草,true,风卷草-defend;风卷草-defend;风卷草-boost,,[source;roll;5];[source;defend;4]
|
||||||
风卷草-defend,风卷草,false,风卷草-boost;风卷草-attack,,[user;defend;8]
|
风卷草-defend,风卷草,false,风卷草-boost;风卷草-attack,,[source;defend;8]
|
||||||
风卷草-attack,风卷草,false,风卷草-boost,,[player;rollDamage;0]
|
风卷草-attack,风卷草,false,风卷草-boost,,[player;rollDamage;0]
|
||||||
秃鹫-attack,秃鹫,true,秃鹫-defend;秃鹫-defend,,[player;attack;6];[player;vultureEye;1]
|
秃鹫-attack,秃鹫,true,秃鹫-defend;秃鹫-defend,,[player;attack;6];[player;vultureEye;1]
|
||||||
秃鹫-defend,秃鹫,false,秃鹫-attack;秃鹫-attack,,[user;defend;5]
|
秃鹫-defend,秃鹫,false,秃鹫-attack;秃鹫-attack,,[source;defend;5]
|
||||||
沙蝎-boost,沙蝎,true,沙蝎-attack;沙蝎-attack,,[user;tailSting;2]
|
沙蝎-boost,沙蝎,true,沙蝎-attack;沙蝎-attack,,[source;tailSting;2]
|
||||||
沙蝎-attack,沙蝎,false,沙蝎-boost;沙蝎-attack,,[player;attack;6]
|
沙蝎-attack,沙蝎,false,沙蝎-boost;沙蝎-attack,,[player;attack;6]
|
||||||
幼沙虫-defend,幼沙虫,true,幼沙虫-defend;幼沙虫-boost,,[user;defend;6]
|
幼沙虫-defend,幼沙虫,true,幼沙虫-defend;幼沙虫-boost,,[source;defend;6]
|
||||||
幼沙虫-boost,幼沙虫,false,幼沙虫-attack;幼沙虫-defend,,[user;energyDrain;1];[user;defend;4]
|
幼沙虫-boost,幼沙虫,false,幼沙虫-attack;幼沙虫-defend,,[source;energyDrain;1];[source;defend;4]
|
||||||
幼沙虫-attack,幼沙虫,false,幼沙虫-defend;幼沙虫-defend,,[player;attack;5]
|
幼沙虫-attack,幼沙虫,false,幼沙虫-defend;幼沙虫-defend,,[player;attack;5]
|
||||||
蜥蜴-attack,蜥蜴,true,蜥蜴-defend;蜥蜴-molt,,[player;attack;5]
|
蜥蜴-attack,蜥蜴,true,蜥蜴-defend;蜥蜴-molt,,[player;attack;5]
|
||||||
蜥蜴-defend,蜥蜴,false,蜥蜴-attack;蜥蜴-attack,,[user;defend;6]
|
蜥蜴-defend,蜥蜴,false,蜥蜴-attack;蜥蜴-attack,,[source;defend;6]
|
||||||
蜥蜴-molt,蜥蜴,false,蜥蜴-defend;蜥蜴-attack,,[user;molt;3]
|
蜥蜴-molt,蜥蜴,false,蜥蜴-defend;蜥蜴-attack,,[source;molt;3]
|
||||||
沙匪-attack,沙匪,true,沙匪-attack;沙匪-heavyAttack,,[player;attack;6]
|
沙匪-attack,沙匪,true,沙匪-attack;沙匪-heavyAttack,,[player;attack;6]
|
||||||
沙匪-heavyAttack,沙匪,false,沙匪-attack;沙匪-attack;沙匪-debuff,,[player;attack;10]
|
沙匪-heavyAttack,沙匪,false,沙匪-attack;沙匪-attack;沙匪-debuff,,[player;attack;10]
|
||||||
沙匪-debuff,沙匪,false,沙匪-attack;沙匪-attack,,[player;discard;1]
|
沙匪-debuff,沙匪,false,沙匪-attack;沙匪-attack,,[player;discard;1]
|
||||||
风暴之灵-storm,风暴之灵,true,风暴之灵-attack;风暴之灵-storm,,[user;storm;2];[user;defend;3]
|
风暴之灵-storm,风暴之灵,true,风暴之灵-attack;风暴之灵-storm,,[source;storm;2];[source;defend;3]
|
||||||
风暴之灵-attack,风暴之灵,false,风暴之灵-storm;风暴之灵-defend,,[player;attack;8];[player;static;1]
|
风暴之灵-attack,风暴之灵,false,风暴之灵-storm;风暴之灵-defend,,[player;attack;8];[player;static;1]
|
||||||
风暴之灵-defend,风暴之灵,false,风暴之灵-storm;风暴之灵-attack,,[user;defend;8]
|
风暴之灵-defend,风暴之灵,false,风暴之灵-storm;风暴之灵-attack,,[source;defend;8]
|
||||||
骑马枪手-charge,骑马枪手,true,骑马枪手-attack,,[user;charge;2]
|
骑马枪手-charge,骑马枪手,true,骑马枪手-attack,,[source;charge;2]
|
||||||
骑马枪手-attack,骑马枪手,false,骑马枪手-charge;骑马枪手-defend,骑马枪手-charge,[player;attack;6]
|
骑马枪手-attack,骑马枪手,false,骑马枪手-charge;骑马枪手-defend,骑马枪手-charge,[player;attack;6]
|
||||||
骑马枪手-defend,骑马枪手,false,骑马枪手-charge;骑马枪手-attack,骑马枪手-charge,[user;defend;5]
|
骑马枪手-defend,骑马枪手,false,骑马枪手-charge;骑马枪手-attack,骑马枪手-charge,[source;defend;5]
|
||||||
沙虫王-summon,沙虫王,true,沙虫王-attack;沙虫王-defend,,[user;summonSandwormLarva;18]
|
沙虫王-summon,沙虫王,true,沙虫王-attack;沙虫王-defend,,[source;summonSandwormLarva;18]
|
||||||
沙虫王-attack,沙虫王,false,沙虫王-summon;沙虫王-defend,,[player;attack;9]
|
沙虫王-attack,沙虫王,false,沙虫王-summon;沙虫王-defend,,[player;attack;9]
|
||||||
沙虫王-defend,沙虫王,false,沙虫王-attack;沙虫王-summon,,[user;defend;6]
|
沙虫王-defend,沙虫王,false,沙虫王-attack;沙虫王-summon,,[source;defend;6]
|
||||||
沙漠守卫-summon,沙漠守卫,true,沙漠守卫-attack;沙漠守卫-defend,,[user;summonMummy;14]
|
沙漠守卫-summon,沙漠守卫,true,沙漠守卫-attack;沙漠守卫-defend,,[source;summonMummy;14]
|
||||||
沙漠守卫-attack,沙漠守卫,false,沙漠守卫-defend;沙漠守卫-summon,,[player;attack;8]
|
沙漠守卫-attack,沙漠守卫,false,沙漠守卫-defend;沙漠守卫-summon,,[player;attack;8]
|
||||||
沙漠守卫-defend,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-revive,,[user;defend;8]
|
沙漠守卫-defend,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-revive,,[source;defend;8]
|
||||||
沙漠守卫-revive,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-summon,,[user;reviveMummy;1]
|
沙漠守卫-revive,沙漠守卫,false,沙漠守卫-attack;沙漠守卫-summon,,[source;reviveMummy;1]
|
||||||
|
|
|
||||||
|
Can't render this file because it has a wrong number of fields in line 13.
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { Enemy } from './enemy.csv';
|
import type { Enemy } from './enemy.csv';
|
||||||
import type { Effect } from './effect.csv';
|
import type { Effect } from './effect.csv';
|
||||||
|
|
||||||
export type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player';
|
export type IntentEffectTarget = 'source' | 'eachEnemy' | 'randomEnemy' | 'player';
|
||||||
export type IntentEffect = [IntentEffectTarget, Effect, number];
|
export type IntentEffect = [IntentEffectTarget, Effect, number];
|
||||||
export type IntentEffectList = IntentEffect[];
|
export type IntentEffectList = IntentEffect[];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ export function addCardEventTriggers(triggers: Triggers, run: IRunContext) {
|
||||||
for (let i = 0; i < storm; i++) {
|
for (let i = 0; i < storm; i++) {
|
||||||
await triggers.onEffectApplied.execute(ctx.game, {
|
await triggers.onEffectApplied.execute(ctx.game, {
|
||||||
effect: findEffect("static"),
|
effect: findEffect("static"),
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
stacks: 1,
|
stacks: 1,
|
||||||
sourceEntityKey: ctx.enemyId,
|
sourceEntityId: ctx.enemyId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +52,7 @@ export function addCardEventTriggers(triggers: Triggers, run: IRunContext) {
|
||||||
await triggers.onCardPlayed.execute(ctx.game, {
|
await triggers.onCardPlayed.execute(ctx.game, {
|
||||||
cardId: id,
|
cardId: id,
|
||||||
targetId: ctx.targetId,
|
targetId: ctx.targetId,
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,17 +113,17 @@ export function addCardEventTriggers(triggers: Triggers, run: IRunContext) {
|
||||||
await next();
|
await next();
|
||||||
|
|
||||||
const dealt = ctx.amount - (ctx.prevented ?? 0);
|
const dealt = ctx.amount - (ctx.prevented ?? 0);
|
||||||
if (dealt <= 0 || !ctx.sourceEntityKey) return;
|
if (dealt <= 0 || !ctx.sourceEntityId) return;
|
||||||
|
|
||||||
const attacker = getCombatEntity(ctx.game.value, ctx.sourceEntityKey);
|
const attacker = getCombatEntity(ctx.game.value, ctx.sourceEntityId);
|
||||||
if (!attacker || !("enemy" in attacker) || attacker.enemy.id !== "秃鹫")
|
if (!attacker || !("enemy" in attacker) || attacker.enemy.id !== "秃鹫")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await triggers.onEffectApplied.execute(ctx.game, {
|
await triggers.onEffectApplied.execute(ctx.game, {
|
||||||
effect: findEffect("vultureEye"),
|
effect: findEffect("vultureEye"),
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
stacks: 1,
|
stacks: 1,
|
||||||
sourceEntityKey: ctx.sourceEntityKey,
|
sourceEntityId: ctx.sourceEntityId,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// block / damage prevention
|
// block / damage prevention
|
||||||
triggers.onDamage.use(async (ctx, next) => {
|
triggers.onDamage.use(async (ctx, next) => {
|
||||||
const entity = getCombatEntity(ctx.game.value, ctx.entityKey);
|
const entity = getCombatEntity(ctx.game.value, ctx.entityId);
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
|
|
||||||
let preventable = ctx.amount - (ctx.prevented ?? 0);
|
let preventable = ctx.amount - (ctx.prevented ?? 0);
|
||||||
|
|
@ -42,7 +42,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
ctx.prevented = (ctx.prevented ?? 0) + blocked;
|
ctx.prevented = (ctx.prevented ?? 0) + blocked;
|
||||||
preventable -= blocked;
|
preventable -= blocked;
|
||||||
await ctx.game.produceAsync((draft) => {
|
await ctx.game.produceAsync((draft) => {
|
||||||
const e = getCombatEntity(draft, ctx.entityKey);
|
const e = getCombatEntity(draft, ctx.entityId);
|
||||||
if (e) addEntityEffect(e, findEffect("defend"), -blocked);
|
if (e) addEntityEffect(e, findEffect("defend"), -blocked);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -61,26 +61,26 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
if (ctx.amount - (ctx.prevented ?? 0) <= 0) return;
|
if (ctx.amount - (ctx.prevented ?? 0) <= 0) return;
|
||||||
|
|
||||||
const entity = getCombatEntity(ctx.game.value, ctx.entityKey);
|
const entity = getCombatEntity(ctx.game.value, ctx.entityId);
|
||||||
if (!entity || !entity.isAlive) return;
|
if (!entity || !entity.isAlive) return;
|
||||||
|
|
||||||
const spike = entity.effects.spike?.stacks ?? 0;
|
const spike = entity.effects.spike?.stacks ?? 0;
|
||||||
if (spike > 0 && ctx.sourceEntityKey) {
|
if (spike > 0 && ctx.sourceEntityId) {
|
||||||
await triggers.onDamage.execute(ctx.game, {
|
await triggers.onDamage.execute(ctx.game, {
|
||||||
entityKey: ctx.sourceEntityKey,
|
entityId: ctx.sourceEntityId,
|
||||||
amount: spike,
|
amount: spike,
|
||||||
sourceEntityKey: ctx.entityKey,
|
sourceEntityId: ctx.entityId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// energyDrain: player loses energy when enemy takes damage
|
// energyDrain: player loses energy when enemy takes damage
|
||||||
triggers.onDamage.use(async (ctx, next) => {
|
triggers.onDamage.use(async (ctx, next) => {
|
||||||
const entity = getCombatEntity(ctx.game.value, ctx.entityKey);
|
const entity = getCombatEntity(ctx.game.value, ctx.entityId);
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
|
|
||||||
const energyDrain = entity.effects.energyDrain?.stacks ?? 0;
|
const energyDrain = entity.effects.energyDrain?.stacks ?? 0;
|
||||||
if (energyDrain > 0 && ctx.entityKey !== "player") {
|
if (energyDrain > 0 && ctx.entityId !== "player") {
|
||||||
const dealt = Math.min(
|
const dealt = Math.min(
|
||||||
Math.max(0, entity.hp),
|
Math.max(0, entity.hp),
|
||||||
ctx.amount - (ctx.prevented ?? 0),
|
ctx.amount - (ctx.prevented ?? 0),
|
||||||
|
|
@ -97,7 +97,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// molt: enemy flees if molt >= maxHp
|
// molt: enemy flees if molt >= maxHp
|
||||||
triggers.onDamage.use(async (ctx, next) => {
|
triggers.onDamage.use(async (ctx, next) => {
|
||||||
const entity = getCombatEntity(ctx.game.value, ctx.entityKey);
|
const entity = getCombatEntity(ctx.game.value, ctx.entityId);
|
||||||
if (!entity || !entity.isAlive) {
|
if (!entity || !entity.isAlive) {
|
||||||
await next();
|
await next();
|
||||||
return;
|
return;
|
||||||
|
|
@ -106,7 +106,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
const molt = entity.effects.molt?.stacks ?? 0;
|
const molt = entity.effects.molt?.stacks ?? 0;
|
||||||
if (molt >= entity.maxHp) {
|
if (molt >= entity.maxHp) {
|
||||||
await ctx.game.produceAsync((draft) => {
|
await ctx.game.produceAsync((draft) => {
|
||||||
const e = draft.enemies.find((en) => en.id === ctx.entityKey);
|
const e = draft.enemies.find((en) => en.id === ctx.entityId);
|
||||||
if (e) {
|
if (e) {
|
||||||
e.isAlive = false;
|
e.isAlive = false;
|
||||||
e.hp = 0;
|
e.hp = 0;
|
||||||
|
|
@ -124,7 +124,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// aim: double damage, lose aim on damage
|
// aim: double damage, lose aim on damage
|
||||||
triggers.onDamage.use(async (ctx, next) => {
|
triggers.onDamage.use(async (ctx, next) => {
|
||||||
if (ctx.sourceEntityKey === "player") {
|
if (ctx.sourceEntityId === "player") {
|
||||||
const player = ctx.game.value.player;
|
const player = ctx.game.value.player;
|
||||||
const aim = player.effects.aim?.stacks ?? 0;
|
const aim = player.effects.aim?.stacks ?? 0;
|
||||||
if (aim > 0) {
|
if (aim > 0) {
|
||||||
|
|
@ -136,7 +136,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// roll: consume 10 roll per 10 damage
|
// roll: consume 10 roll per 10 damage
|
||||||
triggers.onDamage.use(async (ctx, next) => {
|
triggers.onDamage.use(async (ctx, next) => {
|
||||||
if (ctx.sourceEntityKey === "player") {
|
if (ctx.sourceEntityId === "player") {
|
||||||
const player = ctx.game.value.player;
|
const player = ctx.game.value.player;
|
||||||
const roll = player.effects.roll?.stacks ?? 0;
|
const roll = player.effects.roll?.stacks ?? 0;
|
||||||
if (roll >= 10) {
|
if (roll >= 10) {
|
||||||
|
|
@ -152,8 +152,8 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// tailSting: bonus damage on attack
|
// tailSting: bonus damage on attack
|
||||||
triggers.onDamage.use(async (ctx, next) => {
|
triggers.onDamage.use(async (ctx, next) => {
|
||||||
if (ctx.sourceEntityKey && ctx.sourceEntityKey !== "player") {
|
if (ctx.sourceEntityId && ctx.sourceEntityId !== "player") {
|
||||||
const attacker = getCombatEntity(ctx.game.value, ctx.sourceEntityKey);
|
const attacker = getCombatEntity(ctx.game.value, ctx.sourceEntityId);
|
||||||
if (attacker) {
|
if (attacker) {
|
||||||
const tailSting = attacker.effects.tailSting?.stacks ?? 0;
|
const tailSting = attacker.effects.tailSting?.stacks ?? 0;
|
||||||
if (tailSting > 0) {
|
if (tailSting > 0) {
|
||||||
|
|
@ -166,7 +166,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// charge: double damage dealt/received, consume equal charge
|
// charge: double damage dealt/received, consume equal charge
|
||||||
triggers.onDamage.use(async (ctx, next) => {
|
triggers.onDamage.use(async (ctx, next) => {
|
||||||
const entity = getCombatEntity(ctx.game.value, ctx.entityKey);
|
const entity = getCombatEntity(ctx.game.value, ctx.entityId);
|
||||||
if (entity) {
|
if (entity) {
|
||||||
const charge = entity.effects.charge?.stacks ?? 0;
|
const charge = entity.effects.charge?.stacks ?? 0;
|
||||||
if (charge > 0) {
|
if (charge > 0) {
|
||||||
|
|
@ -178,20 +178,20 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
ctx.amount += dealt;
|
ctx.amount += dealt;
|
||||||
if (consumed > 0) {
|
if (consumed > 0) {
|
||||||
await ctx.game.produceAsync((draft) => {
|
await ctx.game.produceAsync((draft) => {
|
||||||
const e = getCombatEntity(draft, ctx.entityKey);
|
const e = getCombatEntity(draft, ctx.entityId);
|
||||||
if (e) addEntityEffect(e, findEffect("charge"), -consumed);
|
if (e) addEntityEffect(e, findEffect("charge"), -consumed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.sourceEntityKey) {
|
if (ctx.sourceEntityId) {
|
||||||
const attacker = getCombatEntity(ctx.game.value, ctx.sourceEntityKey);
|
const attacker = getCombatEntity(ctx.game.value, ctx.sourceEntityId);
|
||||||
if (attacker) {
|
if (attacker) {
|
||||||
const charge = attacker.effects.charge?.stacks ?? 0;
|
const charge = attacker.effects.charge?.stacks ?? 0;
|
||||||
if (charge > 0) {
|
if (charge > 0) {
|
||||||
const baseAmount = ctx.amount;
|
const baseAmount = ctx.amount;
|
||||||
const targetEntity = getCombatEntity(ctx.game.value, ctx.entityKey);
|
const targetEntity = getCombatEntity(ctx.game.value, ctx.entityId);
|
||||||
const dealt = Math.min(
|
const dealt = Math.min(
|
||||||
Math.max(0, targetEntity?.hp ?? 0),
|
Math.max(0, targetEntity?.hp ?? 0),
|
||||||
baseAmount - (ctx.prevented ?? 0),
|
baseAmount - (ctx.prevented ?? 0),
|
||||||
|
|
@ -200,7 +200,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
||||||
ctx.amount += dealt;
|
ctx.amount += dealt;
|
||||||
if (consumed > 0) {
|
if (consumed > 0) {
|
||||||
await ctx.game.produceAsync((draft) => {
|
await ctx.game.produceAsync((draft) => {
|
||||||
const a = getCombatEntity(draft, ctx.sourceEntityKey!);
|
const a = getCombatEntity(draft, ctx.sourceEntityId!);
|
||||||
if (a) addEntityEffect(a, findEffect("charge"), -consumed);
|
if (a) addEntityEffect(a, findEffect("charge"), -consumed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,10 @@ export function addInstantEffectTriggers(triggers: Triggers) {
|
||||||
triggers.onEffectApplied.use(async (ctx, next) => {
|
triggers.onEffectApplied.use(async (ctx, next) => {
|
||||||
if (ctx.effect.id === "attack") {
|
if (ctx.effect.id === "attack") {
|
||||||
await triggers.onDamage.execute(ctx.game, {
|
await triggers.onDamage.execute(ctx.game, {
|
||||||
entityKey: ctx.entityKey,
|
entityId: ctx.entityId,
|
||||||
amount: ctx.stacks,
|
amount: ctx.stacks,
|
||||||
sourceEntityKey:
|
sourceEntityId:
|
||||||
(ctx.sourceEntityKey ?? ctx.entityKey === "player")
|
(ctx.sourceEntityId ?? ctx.entityId === "player")
|
||||||
? undefined
|
? undefined
|
||||||
: "player",
|
: "player",
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export function addTurnStartTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// discard: random discard at turn start
|
// discard: random discard at turn start
|
||||||
triggers.onTurnStart.use(async (ctx, next) => {
|
triggers.onTurnStart.use(async (ctx, next) => {
|
||||||
if (ctx.entityKey !== "player") {
|
if (ctx.entityId !== "player") {
|
||||||
await next();
|
await next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ export function addTurnStartTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// energyNext: gain energy next turn
|
// energyNext: gain energy next turn
|
||||||
triggers.onTurnStart.use(async (ctx, next) => {
|
triggers.onTurnStart.use(async (ctx, next) => {
|
||||||
if (ctx.entityKey !== "player") {
|
if (ctx.entityId !== "player") {
|
||||||
await next();
|
await next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +74,7 @@ export function addTurnStartTriggers(triggers: Triggers) {
|
||||||
|
|
||||||
// drawNext: draw extra cards next turn
|
// drawNext: draw extra cards next turn
|
||||||
triggers.onTurnStart.use(async (ctx, next) => {
|
triggers.onTurnStart.use(async (ctx, next) => {
|
||||||
if (ctx.entityKey !== "player") {
|
if (ctx.entityId !== "player") {
|
||||||
await next();
|
await next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ export function* getEffectTargets(
|
||||||
for (const enemy of getAliveEnemies(game.value)) {
|
for (const enemy of getAliveEnemies(game.value)) {
|
||||||
yield enemy;
|
yield enemy;
|
||||||
}
|
}
|
||||||
} else if (target === "user") {
|
} else if (target === "source") {
|
||||||
const entity = getCombatEntity(game.value, sourceEntityKey);
|
const entity = getCombatEntity(game.value, sourceEntityKey);
|
||||||
if (entity) yield entity;
|
if (entity) yield entity;
|
||||||
} else if (target === "player") {
|
} else if (target === "player") {
|
||||||
|
|
|
||||||
|
|
@ -19,33 +19,33 @@ import { EffectData } from "@/samples/slay-the-spire-like/system/types";
|
||||||
|
|
||||||
type TriggerTypes = {
|
type TriggerTypes = {
|
||||||
onCombatStart: {};
|
onCombatStart: {};
|
||||||
onTurnStart: { entityKey: "player" | string };
|
onTurnStart: { entityId: "player" | string };
|
||||||
onTurnEnd: { entityKey: "player" | string };
|
onTurnEnd: { entityId: "player" | string };
|
||||||
onShuffle: {};
|
onShuffle: {};
|
||||||
onCardPlayed: {
|
onCardPlayed: {
|
||||||
cardId: string;
|
cardId: string;
|
||||||
targetId?: string;
|
targetId?: string;
|
||||||
sourceEntityKey?: "player" | string;
|
sourceEntityId?: "player" | string;
|
||||||
};
|
};
|
||||||
onCardDiscarded: { cardId: string; sourceEntityKey?: "player" | string };
|
onCardDiscarded: { cardId: string; sourceEntityId?: "player" | string };
|
||||||
onCardDrawn: { cardId: string; sourceEntityKey?: "player" | string };
|
onCardDrawn: { cardId: string; sourceEntityId?: "player" | string };
|
||||||
onDraw: { count: number };
|
onDraw: { count: number };
|
||||||
onEffectApplied: {
|
onEffectApplied: {
|
||||||
effect: EffectData;
|
effect: EffectData;
|
||||||
entityKey: "player" | string;
|
entityId: "player" | string;
|
||||||
stacks: number;
|
stacks: number;
|
||||||
cardId?: string;
|
cardId?: string;
|
||||||
sourceEntityKey?: "player" | string;
|
sourceEntityId?: "player" | string;
|
||||||
targetId?: string;
|
targetId?: string;
|
||||||
};
|
};
|
||||||
onHpChange: { entityKey: "player" | string; amount: number };
|
onHpChange: { entityId: "player" | string; amount: number };
|
||||||
onDamage: {
|
onDamage: {
|
||||||
entityKey: "player" | string;
|
entityId: "player" | string;
|
||||||
amount: number;
|
amount: number;
|
||||||
prevented?: number;
|
prevented?: number;
|
||||||
sourceEntityKey?: "player" | string;
|
sourceEntityId?: "player" | string;
|
||||||
};
|
};
|
||||||
onEnemyIntent: { enemyId: string; sourceEntityKey?: "player" | string };
|
onEnemyIntent: { enemyId: string; sourceEntityId?: "player" | string };
|
||||||
onIntentUpdate: { enemyId: string };
|
onIntentUpdate: { enemyId: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -57,13 +57,13 @@ export function createTriggers(run: IRunContext) {
|
||||||
}),
|
}),
|
||||||
onTurnStart: createTrigger("onTurnStart", async (ctx) => {
|
onTurnStart: createTrigger("onTurnStart", async (ctx) => {
|
||||||
await ctx.game.produceAsync((draft) => {
|
await ctx.game.produceAsync((draft) => {
|
||||||
const entity = getCombatEntity(draft, ctx.entityKey);
|
const entity = getCombatEntity(draft, ctx.entityId);
|
||||||
if (entity) onEntityEffectUpkeep(entity);
|
if (entity) onEntityEffectUpkeep(entity);
|
||||||
if (entity === draft.player) onPlayerItemEffectUpkeep(draft.player);
|
if (entity === draft.player) onPlayerItemEffectUpkeep(draft.player);
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
onTurnEnd: createTrigger("onTurnEnd", async (ctx) => {
|
onTurnEnd: createTrigger("onTurnEnd", async (ctx) => {
|
||||||
if (ctx.entityKey !== "player") return;
|
if (ctx.entityId !== "player") return;
|
||||||
const { regions } = ctx.game.value.player.deck;
|
const { regions } = ctx.game.value.player.deck;
|
||||||
for (const cardId of Object.values(regions.hand.childIds)) {
|
for (const cardId of Object.values(regions.hand.childIds)) {
|
||||||
await triggers.onCardDiscarded.execute(ctx.game, { cardId });
|
await triggers.onCardDiscarded.execute(ctx.game, { cardId });
|
||||||
|
|
@ -97,7 +97,7 @@ export function createTriggers(run: IRunContext) {
|
||||||
});
|
});
|
||||||
const { cards, regions } = ctx.game.value.player.deck;
|
const { cards, regions } = ctx.game.value.player.deck;
|
||||||
const card = cards[ctx.cardId];
|
const card = cards[ctx.cardId];
|
||||||
const source = ctx.sourceEntityKey ?? "player";
|
const source = ctx.sourceEntityId ?? "player";
|
||||||
for (const { trigger, target, effects } of card.cardData.effects) {
|
for (const { trigger, target, effects } of card.cardData.effects) {
|
||||||
if (trigger !== "onPlay") continue;
|
if (trigger !== "onPlay") continue;
|
||||||
for (const [effect, stacks] of effects)
|
for (const [effect, stacks] of effects)
|
||||||
|
|
@ -109,10 +109,10 @@ export function createTriggers(run: IRunContext) {
|
||||||
))
|
))
|
||||||
await triggers.onEffectApplied.execute(ctx.game, {
|
await triggers.onEffectApplied.execute(ctx.game, {
|
||||||
effect,
|
effect,
|
||||||
entityKey: entity.id,
|
entityId: entity.id,
|
||||||
stacks,
|
stacks,
|
||||||
cardId: ctx.cardId,
|
cardId: ctx.cardId,
|
||||||
sourceEntityKey: source,
|
sourceEntityId: source,
|
||||||
targetId: ctx.targetId,
|
targetId: ctx.targetId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +125,7 @@ export function createTriggers(run: IRunContext) {
|
||||||
});
|
});
|
||||||
const { cards, regions } = ctx.game.value.player.deck;
|
const { cards, regions } = ctx.game.value.player.deck;
|
||||||
const card = cards[ctx.cardId];
|
const card = cards[ctx.cardId];
|
||||||
const source = ctx.sourceEntityKey ?? "player";
|
const source = ctx.sourceEntityId ?? "player";
|
||||||
for (const { trigger, target, effects } of card.cardData.effects) {
|
for (const { trigger, target, effects } of card.cardData.effects) {
|
||||||
if (trigger !== "onDiscard") continue;
|
if (trigger !== "onDiscard") continue;
|
||||||
for (const [effect, stacks] of effects)
|
for (const [effect, stacks] of effects)
|
||||||
|
|
@ -137,10 +137,10 @@ export function createTriggers(run: IRunContext) {
|
||||||
))
|
))
|
||||||
await triggers.onEffectApplied.execute(ctx.game, {
|
await triggers.onEffectApplied.execute(ctx.game, {
|
||||||
effect,
|
effect,
|
||||||
entityKey: entity.id,
|
entityId: entity.id,
|
||||||
stacks,
|
stacks,
|
||||||
cardId: ctx.cardId,
|
cardId: ctx.cardId,
|
||||||
sourceEntityKey: source,
|
sourceEntityId: source,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -151,7 +151,7 @@ export function createTriggers(run: IRunContext) {
|
||||||
});
|
});
|
||||||
const { cards, regions } = ctx.game.value.player.deck;
|
const { cards, regions } = ctx.game.value.player.deck;
|
||||||
const card = cards[ctx.cardId];
|
const card = cards[ctx.cardId];
|
||||||
const source = ctx.sourceEntityKey ?? "player";
|
const source = ctx.sourceEntityId ?? "player";
|
||||||
for (const { trigger, target, effects } of card.cardData.effects) {
|
for (const { trigger, target, effects } of card.cardData.effects) {
|
||||||
if (trigger !== "onDraw") continue;
|
if (trigger !== "onDraw") continue;
|
||||||
for (const [effect, stacks] of effects)
|
for (const [effect, stacks] of effects)
|
||||||
|
|
@ -163,10 +163,10 @@ export function createTriggers(run: IRunContext) {
|
||||||
))
|
))
|
||||||
await triggers.onEffectApplied.execute(ctx.game, {
|
await triggers.onEffectApplied.execute(ctx.game, {
|
||||||
effect,
|
effect,
|
||||||
entityKey: entity.id,
|
entityId: entity.id,
|
||||||
stacks,
|
stacks,
|
||||||
cardId: ctx.cardId,
|
cardId: ctx.cardId,
|
||||||
sourceEntityKey: source,
|
sourceEntityId: source,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -204,18 +204,18 @@ export function createTriggers(run: IRunContext) {
|
||||||
|
|
||||||
await ctx.game.produceAsync((draft) => {
|
await ctx.game.produceAsync((draft) => {
|
||||||
const entity =
|
const entity =
|
||||||
ctx.entityKey === "player"
|
ctx.entityId === "player"
|
||||||
? draft.player
|
? draft.player
|
||||||
: draft.enemies.find((e) => e.id === ctx.entityKey);
|
: draft.enemies.find((e) => e.id === ctx.entityId);
|
||||||
if (entity) addEntityEffect(entity, ctx.effect, ctx.stacks);
|
if (entity) addEntityEffect(entity, ctx.effect, ctx.stacks);
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
onHpChange: createTrigger("onHpChange", async (ctx) => {
|
onHpChange: createTrigger("onHpChange", async (ctx) => {
|
||||||
await ctx.game.produceAsync((draft) => {
|
await ctx.game.produceAsync((draft) => {
|
||||||
const entity =
|
const entity =
|
||||||
ctx.entityKey === "player"
|
ctx.entityId === "player"
|
||||||
? draft.player
|
? draft.player
|
||||||
: draft.enemies.find((e) => e.id === ctx.entityKey);
|
: draft.enemies.find((e) => e.id === ctx.entityId);
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
entity.hp += ctx.amount;
|
entity.hp += ctx.amount;
|
||||||
entity.isAlive = entity.hp > 0;
|
entity.isAlive = entity.hp > 0;
|
||||||
|
|
@ -229,9 +229,9 @@ export function createTriggers(run: IRunContext) {
|
||||||
}),
|
}),
|
||||||
onDamage: createTrigger("onDamage", async (ctx) => {
|
onDamage: createTrigger("onDamage", async (ctx) => {
|
||||||
const entity =
|
const entity =
|
||||||
ctx.entityKey === "player"
|
ctx.entityId === "player"
|
||||||
? ctx.game.value.player
|
? ctx.game.value.player
|
||||||
: ctx.game.value.enemies.find((e) => e.id === ctx.entityKey);
|
: ctx.game.value.enemies.find((e) => e.id === ctx.entityId);
|
||||||
if (!entity || !entity.isAlive) return;
|
if (!entity || !entity.isAlive) return;
|
||||||
const dealt = Math.min(
|
const dealt = Math.min(
|
||||||
Math.max(0, entity.hp),
|
Math.max(0, entity.hp),
|
||||||
|
|
@ -241,7 +241,7 @@ export function createTriggers(run: IRunContext) {
|
||||||
onEntityPostureDamage(entity, dealt);
|
onEntityPostureDamage(entity, dealt);
|
||||||
});
|
});
|
||||||
await triggers.onHpChange.execute(ctx.game, {
|
await triggers.onHpChange.execute(ctx.game, {
|
||||||
entityKey: ctx.entityKey,
|
entityId: ctx.entityId,
|
||||||
amount: -dealt,
|
amount: -dealt,
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
@ -252,7 +252,7 @@ export function createTriggers(run: IRunContext) {
|
||||||
const intent = enemy.currentIntent;
|
const intent = enemy.currentIntent;
|
||||||
if (!intent) return;
|
if (!intent) return;
|
||||||
|
|
||||||
const source = ctx.sourceEntityKey ?? enemy.id;
|
const source = ctx.sourceEntityId ?? enemy.id;
|
||||||
for (const [target, effect, stacks] of intent.effects) {
|
for (const [target, effect, stacks] of intent.effects) {
|
||||||
for (const entity of getEffectTargets(
|
for (const entity of getEffectTargets(
|
||||||
target,
|
target,
|
||||||
|
|
@ -262,9 +262,9 @@ export function createTriggers(run: IRunContext) {
|
||||||
))
|
))
|
||||||
await triggers.onEffectApplied.execute(ctx.game, {
|
await triggers.onEffectApplied.execute(ctx.game, {
|
||||||
effect,
|
effect,
|
||||||
entityKey: entity.id,
|
entityId: entity.id,
|
||||||
stacks,
|
stacks,
|
||||||
sourceEntityKey: source,
|
sourceEntityId: source,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -298,7 +298,7 @@ export function createStartWith(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
await triggers.onTurnStart.execute(game, { entityKey: "player" });
|
await triggers.onTurnStart.execute(game, { entityId: "player" });
|
||||||
while (true) {
|
while (true) {
|
||||||
const action = await promptMainAction(game, run);
|
const action = await promptMainAction(game, run);
|
||||||
if (action.action === "end-turn") break;
|
if (action.action === "end-turn") break;
|
||||||
|
|
@ -306,17 +306,17 @@ export function createStartWith(
|
||||||
await triggers.onCardPlayed.execute(game, action);
|
await triggers.onCardPlayed.execute(game, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await triggers.onTurnEnd.execute(game, { entityKey: "player" });
|
await triggers.onTurnEnd.execute(game, { entityId: "player" });
|
||||||
|
|
||||||
for (const enemy of getAliveEnemies(game.value)) {
|
for (const enemy of getAliveEnemies(game.value)) {
|
||||||
await triggers.onTurnStart.execute(game, { entityKey: enemy.id });
|
await triggers.onTurnStart.execute(game, { entityId: enemy.id });
|
||||||
}
|
}
|
||||||
for (const enemy of getAliveEnemies(game.value)) {
|
for (const enemy of getAliveEnemies(game.value)) {
|
||||||
await triggers.onEnemyIntent.execute(game, { enemyId: enemy.id });
|
await triggers.onEnemyIntent.execute(game, { enemyId: enemy.id });
|
||||||
await triggers.onIntentUpdate.execute(game, { enemyId: enemy.id });
|
await triggers.onIntentUpdate.execute(game, { enemyId: enemy.id });
|
||||||
}
|
}
|
||||||
for (const enemy of getAliveEnemies(game.value)) {
|
for (const enemy of getAliveEnemies(game.value)) {
|
||||||
await triggers.onTurnEnd.execute(game, { entityKey: enemy.id });
|
await triggers.onTurnEnd.execute(game, { entityId: enemy.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -205,9 +205,9 @@ describe("desert triggers", () => {
|
||||||
|
|
||||||
await triggers.onEffectApplied.execute(ctx, {
|
await triggers.onEffectApplied.execute(ctx, {
|
||||||
effect: attackEffect,
|
effect: attackEffect,
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
stacks: 5,
|
stacks: 5,
|
||||||
sourceEntityKey: "enemy-0",
|
sourceEntityId: "enemy-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.hp).toBe(25);
|
expect(ctx.value.player.hp).toBe(25);
|
||||||
|
|
@ -223,7 +223,7 @@ describe("desert triggers", () => {
|
||||||
|
|
||||||
await triggers.onEffectApplied.execute(ctx, {
|
await triggers.onEffectApplied.execute(ctx, {
|
||||||
effect: drawEffect,
|
effect: drawEffect,
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
stacks: 2,
|
stacks: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -239,7 +239,7 @@ describe("desert triggers", () => {
|
||||||
const initialEnergy = ctx.value.player.energy;
|
const initialEnergy = ctx.value.player.energy;
|
||||||
await triggers.onEffectApplied.execute(ctx, {
|
await triggers.onEffectApplied.execute(ctx, {
|
||||||
effect: gainEnergyEffect,
|
effect: gainEnergyEffect,
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
stacks: 2,
|
stacks: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -261,7 +261,7 @@ describe("desert triggers", () => {
|
||||||
|
|
||||||
await triggers.onEffectApplied.execute(ctx, {
|
await triggers.onEffectApplied.execute(ctx, {
|
||||||
effect: removeWoundEffect,
|
effect: removeWoundEffect,
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
stacks: 2,
|
stacks: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -286,9 +286,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
amount: 8,
|
amount: 8,
|
||||||
sourceEntityKey: "enemy-0",
|
sourceEntityId: "enemy-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.hp).toBe(27);
|
expect(ctx.value.player.hp).toBe(27);
|
||||||
|
|
@ -312,9 +312,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
amount: 8,
|
amount: 8,
|
||||||
sourceEntityKey: "enemy-0",
|
sourceEntityId: "enemy-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.hp).toBe(25);
|
expect(ctx.value.player.hp).toBe(25);
|
||||||
|
|
@ -334,9 +334,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "enemy-0",
|
sourceEntityId: "enemy-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.hp).toBe(23);
|
expect(ctx.value.player.hp).toBe(23);
|
||||||
|
|
@ -359,9 +359,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "仙人掌怪-0",
|
entityId: "仙人掌怪-0",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.hp).toBe(27);
|
expect(ctx.value.player.hp).toBe(27);
|
||||||
|
|
@ -402,9 +402,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "幼沙虫-0",
|
entityId: "幼沙虫-0",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.energy).toBe(2);
|
expect(ctx.value.player.energy).toBe(2);
|
||||||
|
|
@ -429,9 +429,9 @@ describe("desert triggers", () => {
|
||||||
let threw = false;
|
let threw = false;
|
||||||
try {
|
try {
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "蜥蜴-0",
|
entityId: "蜥蜴-0",
|
||||||
amount: 1,
|
amount: 1,
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
threw = true;
|
threw = true;
|
||||||
|
|
@ -457,7 +457,7 @@ describe("desert triggers", () => {
|
||||||
draft.player.effects.discard = { data: discardEffect, stacks: 1 };
|
draft.player.effects.discard = { data: discardEffect, stacks: 1 };
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onTurnStart.execute(ctx, { entityKey: "player" });
|
await triggers.onTurnStart.execute(ctx, { entityId: "player" });
|
||||||
|
|
||||||
expect(ctx.value.player.deck.regions.hand.childIds.length).toBe(2);
|
expect(ctx.value.player.deck.regions.hand.childIds.length).toBe(2);
|
||||||
expect(ctx.value.player.deck.regions.discardPile.childIds.length).toBe(1);
|
expect(ctx.value.player.deck.regions.discardPile.childIds.length).toBe(1);
|
||||||
|
|
@ -474,7 +474,7 @@ describe("desert triggers", () => {
|
||||||
draft.player.effects.defendNext = { data: defendNextEffect, stacks: 5 };
|
draft.player.effects.defendNext = { data: defendNextEffect, stacks: 5 };
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onTurnStart.execute(ctx, { entityKey: "player" });
|
await triggers.onTurnStart.execute(ctx, { entityId: "player" });
|
||||||
|
|
||||||
expect(ctx.value.player.effects.defend?.stacks).toBe(5);
|
expect(ctx.value.player.effects.defend?.stacks).toBe(5);
|
||||||
expect(ctx.value.player.effects.defendNext).toBeUndefined();
|
expect(ctx.value.player.effects.defendNext).toBeUndefined();
|
||||||
|
|
@ -489,7 +489,7 @@ describe("desert triggers", () => {
|
||||||
draft.player.effects.energyNext = { data: energyNextEffect, stacks: 2 };
|
draft.player.effects.energyNext = { data: energyNextEffect, stacks: 2 };
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onTurnStart.execute(ctx, { entityKey: "player" });
|
await triggers.onTurnStart.execute(ctx, { entityId: "player" });
|
||||||
|
|
||||||
expect(ctx.value.player.energy).toBe(5);
|
expect(ctx.value.player.energy).toBe(5);
|
||||||
expect(ctx.value.player.effects.energyNext).toBeUndefined();
|
expect(ctx.value.player.effects.energyNext).toBeUndefined();
|
||||||
|
|
@ -508,7 +508,7 @@ describe("desert triggers", () => {
|
||||||
draft.player.effects.drawNext = { data: drawNextEffect, stacks: 2 };
|
draft.player.effects.drawNext = { data: drawNextEffect, stacks: 2 };
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onTurnStart.execute(ctx, { entityKey: "player" });
|
await triggers.onTurnStart.execute(ctx, { entityId: "player" });
|
||||||
|
|
||||||
expect(ctx.value.player.deck.regions.hand.childIds.length).toBe(2);
|
expect(ctx.value.player.deck.regions.hand.childIds.length).toBe(2);
|
||||||
expect(ctx.value.player.effects.drawNext).toBeUndefined();
|
expect(ctx.value.player.effects.drawNext).toBeUndefined();
|
||||||
|
|
@ -530,9 +530,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "仙人掌怪-0",
|
entityId: "仙人掌怪-0",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.enemies[0].hp).toBe(2);
|
expect(ctx.value.enemies[0].hp).toBe(2);
|
||||||
|
|
@ -552,9 +552,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "仙人掌怪-0",
|
entityId: "仙人掌怪-0",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.enemies[0].hp).toBe(74);
|
expect(ctx.value.enemies[0].hp).toBe(74);
|
||||||
|
|
@ -576,9 +576,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "沙蝎-0",
|
sourceEntityId: "沙蝎-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.hp).toBe(23);
|
expect(ctx.value.player.hp).toBe(23);
|
||||||
|
|
@ -599,9 +599,9 @@ describe("desert triggers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "骑马枪手-0",
|
sourceEntityId: "骑马枪手-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.player.hp).toBe(20);
|
expect(ctx.value.player.hp).toBe(20);
|
||||||
|
|
@ -623,10 +623,10 @@ describe("desert triggers", () => {
|
||||||
|
|
||||||
await triggers.onEffectApplied.execute(ctx, {
|
await triggers.onEffectApplied.execute(ctx, {
|
||||||
effect: crossbowEffect,
|
effect: crossbowEffect,
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
stacks: 0,
|
stacks: 0,
|
||||||
cardId: "crossbow-1",
|
cardId: "crossbow-1",
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
targetId: "仙人掌怪-0",
|
targetId: "仙人掌怪-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -647,7 +647,7 @@ describe("desert triggers", () => {
|
||||||
|
|
||||||
await triggers.onCardDiscarded.execute(ctx, {
|
await triggers.onCardDiscarded.execute(ctx, {
|
||||||
cardId: "fatigue-1",
|
cardId: "fatigue-1",
|
||||||
sourceEntityKey: "player",
|
sourceEntityId: "player",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(ctx.value.enemies[0].hp).toBe(40);
|
expect(ctx.value.enemies[0].hp).toBe(40);
|
||||||
|
|
@ -664,9 +664,9 @@ describe("desert triggers", () => {
|
||||||
const triggers = getTriggers();
|
const triggers = getTriggers();
|
||||||
|
|
||||||
await triggers.onDamage.execute(ctx, {
|
await triggers.onDamage.execute(ctx, {
|
||||||
entityKey: "player",
|
entityId: "player",
|
||||||
amount: 5,
|
amount: 5,
|
||||||
sourceEntityKey: "秃鹫-0",
|
sourceEntityId: "秃鹫-0",
|
||||||
});
|
});
|
||||||
|
|
||||||
const vultureEyeCards = Object.values(ctx.value.player.deck.cards).filter(
|
const vultureEyeCards = Object.values(ctx.value.player.deck.cards).filter(
|
||||||
|
|
|
||||||
|
|
@ -1,174 +1,176 @@
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from "vitest";
|
||||||
import { parseCommand, type Command } from '@/utils/command';
|
import { parseCommand, type Command } from "@/utils/command";
|
||||||
|
|
||||||
describe('parseCommand', () => {
|
describe("parseCommand", () => {
|
||||||
it('should parse empty string', () => {
|
it("should parse empty string", () => {
|
||||||
const result = parseCommand('');
|
const result = parseCommand("");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: '',
|
name: "",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: {},
|
options: {},
|
||||||
params: []
|
params: [],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse command name only', () => {
|
it("should parse command name only", () => {
|
||||||
const result = parseCommand('move');
|
const result = parseCommand("move");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: {},
|
options: {},
|
||||||
params: []
|
params: [],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse command with params', () => {
|
it("should parse command with params", () => {
|
||||||
const result = parseCommand('move meeple1 region1');
|
const result = parseCommand("move meeple1 region1");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: {},
|
options: {},
|
||||||
params: ['meeple1', 'region1']
|
params: ["meeple1", "region1"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse command with long flags', () => {
|
it("should parse command with long flags", () => {
|
||||||
const result = parseCommand('move meeple1 --force --quiet');
|
const result = parseCommand("move meeple1 --force --quiet");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: { force: true, quiet: true },
|
flags: { force: true, quiet: true },
|
||||||
options: {},
|
options: {},
|
||||||
params: ['meeple1']
|
params: ["meeple1"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse command with short flags', () => {
|
it("should parse command with short flags", () => {
|
||||||
const result = parseCommand('move meeple1 -f -q');
|
const result = parseCommand("move meeple1 -f -q");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: { f: true, q: true },
|
flags: { f: true, q: true },
|
||||||
options: {},
|
options: {},
|
||||||
params: ['meeple1']
|
params: ["meeple1"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse command with long options', () => {
|
it("should parse command with long options", () => {
|
||||||
const result = parseCommand('move meeple1 --x 10 --y 20');
|
const result = parseCommand("move meeple1 --x 10 --y 20");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: { x: '10', y: '20' },
|
options: { x: "10", y: "20" },
|
||||||
params: ['meeple1']
|
params: ["meeple1"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse command with short options', () => {
|
it("should parse command with short options", () => {
|
||||||
const result = parseCommand('move meeple1 -x 10 -y 20');
|
const result = parseCommand("move meeple1 -x 10 -y 20");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: { x: '10', y: '20' },
|
options: { x: "10", y: "20" },
|
||||||
params: ['meeple1']
|
params: ["meeple1"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse command with mixed flags和选项', () => {
|
it("should parse command with mixed flags和选项", () => {
|
||||||
const result = parseCommand('move meeple1 region1 --force -x 10 -q');
|
const result = parseCommand("move meeple1 region1 --force -x 10 -q");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: { force: true, q: true },
|
flags: { force: true, q: true },
|
||||||
options: { x: '10' },
|
options: { x: "10" },
|
||||||
params: ['meeple1', 'region1']
|
params: ["meeple1", "region1"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle extra whitespace', () => {
|
it("should handle extra whitespace", () => {
|
||||||
const result = parseCommand(' move meeple1 --force ');
|
const result = parseCommand(" move meeple1 --force ");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'move',
|
name: "move",
|
||||||
flags: { force: true },
|
flags: { force: true },
|
||||||
options: {},
|
options: {},
|
||||||
params: ['meeple1']
|
params: ["meeple1"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse complex command', () => {
|
it("should parse complex command", () => {
|
||||||
const result = parseCommand('place meeple1 board --x 5 --y 3 --rotate 90 --force');
|
const result = parseCommand(
|
||||||
expect(result).toEqual({
|
"place meeple1 board --x 5 --y 3 --rotate 90 --force",
|
||||||
name: 'place',
|
);
|
||||||
flags: { force: true },
|
expect(result).toEqual({
|
||||||
options: { x: '5', y: '3', rotate: '90' },
|
name: "place",
|
||||||
params: ['meeple1', 'board']
|
flags: { force: true },
|
||||||
});
|
options: { x: "5", y: "3", rotate: "90" },
|
||||||
|
params: ["meeple1", "board"],
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should treat negative number as option value', () => {
|
it("should treat negative number as option value", () => {
|
||||||
const result = parseCommand('set --value -10');
|
const result = parseCommand("set --value -10");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'set',
|
name: "set",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: { value: '-10' },
|
options: { value: "-10" },
|
||||||
params: []
|
params: [],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse quoted string with double quotes', () => {
|
it("should parse quoted string with double quotes", () => {
|
||||||
const result = parseCommand('place tile "large castle" --x 5');
|
const result = parseCommand('place tile "large castle" --x 5');
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'place',
|
name: "place",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: { x: '5' },
|
options: { x: "5" },
|
||||||
params: ['tile', 'large castle']
|
params: ["tile", "large castle"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse quoted string with single quotes', () => {
|
it("should parse quoted string with single quotes", () => {
|
||||||
const result = parseCommand("place tile 'large castle' --x 5");
|
const result = parseCommand("place tile 'large castle' --x 5");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'place',
|
name: "place",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: { x: '5' },
|
options: { x: "5" },
|
||||||
params: ['tile', 'large castle']
|
params: ["tile", "large castle"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle escaped quotes', () => {
|
it("should handle escaped quotes", () => {
|
||||||
const result = parseCommand('say "hello \\"world\\""');
|
const result = parseCommand('say "hello \\"world\\""');
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'say',
|
name: "say",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: {},
|
options: {},
|
||||||
params: ['hello "world"']
|
params: ['hello "world"'],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle escaped backslash', () => {
|
it("should handle escaped backslash", () => {
|
||||||
const result = parseCommand('set path "C:\\\\Users"');
|
const result = parseCommand('set path "C:\\\\Users"');
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'set',
|
name: "set",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: {},
|
options: {},
|
||||||
params: ['path', 'C:\\Users']
|
params: ["path", "C:\\Users"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle mixed quotes', () => {
|
it("should handle mixed quotes", () => {
|
||||||
const result = parseCommand('cmd "hello world" \'foo bar\' --flag');
|
const result = parseCommand("cmd \"hello world\" 'foo bar' --flag");
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'cmd',
|
name: "cmd",
|
||||||
flags: { flag: true },
|
flags: { flag: true },
|
||||||
options: {},
|
options: {},
|
||||||
params: ['hello world', 'foo bar']
|
params: ["hello world", "foo bar"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle quote in middle of argument', () => {
|
it("should handle quote in middle of argument", () => {
|
||||||
const result = parseCommand('cmd "hello\'s world"');
|
const result = parseCommand('cmd "hello\'s world"');
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
name: 'cmd',
|
name: "cmd",
|
||||||
flags: {},
|
flags: {},
|
||||||
options: {},
|
options: {},
|
||||||
params: ["hello's world"]
|
params: ["hello's world"],
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue