feat: effect and triggers

This commit is contained in:
hypercross 2026-04-17 12:58:12 +08:00
parent aa36f3ea67
commit f775d51a58
5 changed files with 47 additions and 4 deletions

View File

@ -5,6 +5,7 @@ import getEnemies from './enemy.csv';
import getIntents from './intent.csv'; import getIntents from './intent.csv';
import getItems from './item.csv'; import getItems from './item.csv';
export { default as dialogues } from './dialogues/dialogues.yarnproject'; export { default as dialogues } from './dialogues/dialogues.yarnproject';
export { addTriggers } from './triggers';
export const cards = getCards(); export const cards = getCards();
export const effects = getEffects(); export const effects = getEffects();

View File

@ -0,0 +1,33 @@
import {Triggers} from "@/samples/slay-the-spire-like/system/combat/triggers";
import {getCombatEntity} from "@/samples/slay-the-spire-like/system/combat/effects";
export function addEffectTriggers(triggers:Triggers){
// instant effects
triggers.onEffectApplied.use(async (ctx, next) => {
if(ctx.effect.id === "attack") {
await triggers.onDamage.execute(ctx.game, {
entityKey: ctx.entityKey,
amount: ctx.stacks
});
}else if(ctx.effect.id === "draw") {
await triggers.onDraw.execute(ctx.game, {
count: ctx.stacks
});
}
await next();
});
// blocks
triggers.onDamage.use(async (ctx, next) => {
const entity = getCombatEntity(ctx.game.value, ctx.entityKey);
if(!entity) return;
const preventable = (ctx.amount - (ctx.prevented ?? 0));
const blocks = entity.effects.block?.stacks ?? 0;
const blocked = Math.min(blocks, preventable);
if(blocked){
ctx.prevented = (ctx.prevented ?? 0) + blocked;
}
await next();
});
}

View File

@ -0,0 +1,6 @@
import {addEffectTriggers} from './effect';
import {Triggers} from "@/samples/slay-the-spire-like/system/combat/triggers";
export function addTriggers(triggers: Triggers){
addEffectTriggers(triggers);
}

View File

@ -79,3 +79,7 @@ export function* getAliveEnemies(state: CombatState) {
} }
} }
} }
export function getCombatEntity(state: CombatState, entityKey: string){
return entityKey === 'player' ? state.player : state.enemies.find(e => e.id === entityKey);
}

View File

@ -24,7 +24,7 @@ type TriggerTypes = {
onDraw: {count: number}, onDraw: {count: number},
onEffectApplied: { effect: EffectData, entityKey: "player" | string, stacks: number, cardId?: string }, onEffectApplied: { effect: EffectData, entityKey: "player" | string, stacks: number, cardId?: string },
onHpChange: { entityKey: "player" | string, amount: number}, onHpChange: { entityKey: "player" | string, amount: number},
onDamage: { entityKey: "player" | string, amount: number, dealt?: number, prevented?: number}, onDamage: { entityKey: "player" | string, amount: number, prevented?: number},
onEnemyIntent: { enemyId: string }, onEnemyIntent: { enemyId: string },
onIntentUpdate: { enemyId: string }, onIntentUpdate: { enemyId: string },
} }
@ -126,12 +126,11 @@ function createTriggers(){
onDamage: createTrigger("onDamage", async ctx => { onDamage: createTrigger("onDamage", async ctx => {
const entity = ctx.entityKey === "player" ? ctx.game.value.player : ctx.game.value.enemies.find(e => e.id === ctx.entityKey); const entity = ctx.entityKey === "player" ? ctx.game.value.player : ctx.game.value.enemies.find(e => e.id === ctx.entityKey);
if(!entity || !entity.isAlive) return; if(!entity || !entity.isAlive) return;
const dealt = ctx.dealt = Math.min(Math.max(0,entity.hp), ctx.amount); const dealt = Math.min(Math.max(0,entity.hp), ctx.amount - (ctx.prevented || 0));
ctx.prevented = ctx.amount - ctx.dealt;
await ctx.game.produceAsync(draft => { await ctx.game.produceAsync(draft => {
onEntityPostureDamage(entity, dealt); onEntityPostureDamage(entity, dealt);
}); });
await triggers.onHpChange.execute(ctx.game,{entityKey: ctx.entityKey, amount: -ctx.amount}); await triggers.onHpChange.execute(ctx.game,{entityKey: ctx.entityKey, amount: -dealt});
}), }),
onEnemyIntent: createTrigger("onEnemyIntent", async ctx => { onEnemyIntent: createTrigger("onEnemyIntent", async ctx => {
const enemy = ctx.game.value.enemies.find(e => e.id === ctx.enemyId); const enemy = ctx.game.value.enemies.find(e => e.id === ctx.enemyId);