feat: add posture damage & item effect update trigger

This commit is contained in:
hypercross 2026-04-17 11:57:07 +08:00
parent 65afe6dc8f
commit 1d749f59a6
2 changed files with 43 additions and 9 deletions

View File

@ -34,6 +34,14 @@ export function onEntityEffectUpkeep(entity: CombatEntity){
} }
} }
export function onEntityPostureDamage(entity: CombatEntity, damage: number){
for(const effect of Object.values(entity.effects)){
const lifecycle = effect.data.lifecycle;
if(lifecycle === 'posture')
addEntityEffect(entity, effect.data, -Math.min(damage, effect.stacks));
}
}
export function onPlayerItemEffectUpkeep(entity: PlayerEntity){ export function onPlayerItemEffectUpkeep(entity: PlayerEntity){
for(const [itemKey, itemEffects] of Object.entries(entity.itemEffects)){ for(const [itemKey, itemEffects] of Object.entries(entity.itemEffects)){
for(const effect of Object.values(itemEffects)){ for(const effect of Object.values(itemEffects)){
@ -44,6 +52,26 @@ export function onPlayerItemEffectUpkeep(entity: PlayerEntity){
} }
} }
export function onItemPlay(entity: PlayerEntity, itemKey: string){
const effects = entity.itemEffects[itemKey];
if(!effects)return;
for(const effect of Object.values(effects)){
if(effect.data.lifecycle === 'itemUntilPlay'){
addItemEffect(entity, itemKey, effect.data, -effect.stacks);
}
}
}
export function onItemDiscard(entity: PlayerEntity, itemKey: string){
const effects = entity.itemEffects[itemKey];
if(!effects)return;
for(const effect of Object.values(effects)){
if(effect.data.lifecycle === 'itemUntilDiscard'){
addItemEffect(entity, itemKey, effect.data, -effect.stacks);
}
}
}
export function* getAliveEnemies(state: CombatState) { export function* getAliveEnemies(state: CombatState) {
for (let enemy of state.enemies) { for (let enemy of state.enemies) {
if (enemy.isAlive) { if (enemy.isAlive) {

View File

@ -2,9 +2,9 @@ import {CombatGameContext} from "./types";
import { import {
addEntityEffect, addEntityEffect,
addItemEffect, addItemEffect,
getAliveEnemies, getAliveEnemies, onEntityPostureDamage,
onEntityEffectUpkeep, onEntityEffectUpkeep,
onPlayerItemEffectUpkeep onPlayerItemEffectUpkeep, onItemDiscard, onItemPlay
} from "@/samples/slay-the-spire-like/system/combat/effects"; } from "@/samples/slay-the-spire-like/system/combat/effects";
import {promptMainAction} from "@/samples/slay-the-spire-like/system/combat/prompts"; import {promptMainAction} from "@/samples/slay-the-spire-like/system/combat/prompts";
import {moveToRegion, shuffle} from "@/core/region"; import {moveToRegion, shuffle} from "@/core/region";
@ -24,6 +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},
} }
function createTriggers(){ function createTriggers(){
@ -58,12 +59,14 @@ function createTriggers(){
await ctx.game.produceAsync(draft => { await ctx.game.produceAsync(draft => {
const {cards, regions} = draft.player.deck; const {cards, regions} = draft.player.deck;
moveToRegion(cards[ctx.cardId], regions.hand, regions.discardPile); moveToRegion(cards[ctx.cardId], regions.hand, regions.discardPile);
onItemPlay(draft.player, cards[ctx.cardId].itemId);
}); });
}), }),
onCardDiscarded: createTrigger("onCardDiscarded", async ctx => { onCardDiscarded: createTrigger("onCardDiscarded", async ctx => {
await ctx.game.produceAsync(draft => { await ctx.game.produceAsync(draft => {
const {cards, regions} = draft.player.deck; const {cards, regions} = draft.player.deck;
moveToRegion(cards[ctx.cardId], regions.hand, regions.discardPile); moveToRegion(cards[ctx.cardId], regions.hand, regions.discardPile);
onItemDiscard(draft.player, cards[ctx.cardId].itemId);
}); });
}), }),
onCardDrawn: createTrigger("onCardDrawn", async ctx => { onCardDrawn: createTrigger("onCardDrawn", async ctx => {
@ -103,13 +106,6 @@ function createTriggers(){
return; return;
} }
if(ctx.effect.lifecycle.startsWith('card')){
await ctx.game.produceAsync(draft => {
// TODO
});
return;
}
await ctx.game.produceAsync(draft => { await ctx.game.produceAsync(draft => {
const entity = ctx.entityKey === "player" ? draft.player : draft.enemies.find(e => e.id === ctx.entityKey); const entity = ctx.entityKey === "player" ? draft.player : draft.enemies.find(e => e.id === ctx.entityKey);
if(entity) addEntityEffect(entity, ctx.effect, ctx.stacks); if(entity) addEntityEffect(entity, ctx.effect, ctx.stacks);
@ -125,6 +121,16 @@ function createTriggers(){
}); });
if(ctx.game.value.result) throw ctx.game.value; if(ctx.game.value.result) throw ctx.game.value;
}), }),
onDamage: createTrigger("onDamage", async ctx => {
const entity = ctx.entityKey === "player" ? ctx.game.value.player : ctx.game.value.enemies.find(e => e.id === ctx.entityKey);
if(!entity || !entity.isAlive) return;
const dealt = ctx.dealt = Math.min(Math.max(0,entity.hp), ctx.amount);
ctx.prevented = ctx.amount - ctx.dealt;
await ctx.game.produceAsync(draft => {
onEntityPostureDamage(entity, dealt);
});
await triggers.onHpChange.execute(ctx.game,{entityKey: ctx.entityKey, amount: -ctx.amount});
}),
} }
return triggers; return triggers;
} }