refactor: update turn start triggers in desert sample

Fixes logic in `defendNext` to ensure effects are applied after
buff updates by calling `next()` before mutation. Also updates
indentation and formatting to match project style guidelines.
This commit is contained in:
hypercross 2026-04-22 20:13:31 +08:00
parent a5e2e4888e
commit f4c96a4a72
2 changed files with 74 additions and 76 deletions

View File

@ -4,85 +4,89 @@ import { EffectData } from "@/samples/slay-the-spire-like/system/types";
import getEffects from "../effect.csv"; import getEffects from "../effect.csv";
export function addTurnStartTriggers(triggers: Triggers) { export function addTurnStartTriggers(triggers: Triggers) {
const effects = getEffects(); const effects = getEffects();
function findEffect(id: string): EffectData { function findEffect(id: string): EffectData {
const found = effects.find(e => e.id === id); const found = effects.find((e) => e.id === id);
if (found) return found; if (found) return found;
return { id, name: id, description: "", lifecycle: "instant" } as EffectData; return {
id,
name: id,
description: "",
lifecycle: "instant",
} as EffectData;
}
// discard: random discard at turn start
triggers.onTurnStart.use(async (ctx, next) => {
if (ctx.entityKey !== "player") {
await next();
return;
} }
// discard: random discard at turn start const discard = ctx.game.value.player.effects.discard;
triggers.onTurnStart.use(async (ctx, next) => { if (discard && discard.stacks > 0) {
if (ctx.entityKey !== "player") { const handIds = [...ctx.game.value.player.deck.regions.hand.childIds];
await next(); if (handIds.length > 0) {
return; const randomIndex = ctx.game.rng.nextInt(handIds.length);
} const randomCardId = handIds[randomIndex];
await triggers.onCardDiscarded.execute(ctx.game, {
cardId: randomCardId,
});
}
}
const discard = ctx.game.value.player.effects.discard; await next();
if (discard && discard.stacks > 0) { });
const handIds = [...ctx.game.value.player.deck.regions.hand.childIds];
if (handIds.length > 0) {
const randomIndex = ctx.game.rng.nextInt(handIds.length);
const randomCardId = handIds[randomIndex];
await triggers.onCardDiscarded.execute(ctx.game, { cardId: randomCardId });
}
}
await next(); // defendNext: gain block next turn
// record how many defendNext there is, before buff update
// then apply after buff update
triggers.onTurnStart.use(async (ctx, next) => {
const defendNext = ctx.game.value.player.effects.defendNext;
if (!defendNext || defendNext.stacks <= 0) {
await next();
return;
}
await next();
await ctx.game.produceAsync((draft) => {
addEntityEffect(draft.player, findEffect("defend"), defendNext.stacks);
}); });
});
// defendNext: gain block 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.entityKey !== "player") {
await next(); await next();
return; return;
} }
const defendNext = ctx.game.value.player.effects.defendNext; const energyNext = ctx.game.value.player.effects.energyNext;
if (defendNext && defendNext.stacks > 0) { if (energyNext && energyNext.stacks > 0) {
await ctx.game.produceAsync(draft => { await ctx.game.produceAsync((draft) => {
addEntityEffect(draft.player, findEffect("defend"), defendNext.stacks); draft.player.energy += energyNext.stacks;
addEntityEffect(draft.player, defendNext.data, -defendNext.stacks); addEntityEffect(draft.player, energyNext.data, -energyNext.stacks);
}); });
} }
await next(); await next();
}); });
// energyNext: gain energy 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.entityKey !== "player") {
await next(); await next();
return; return;
} }
const energyNext = ctx.game.value.player.effects.energyNext; const drawNext = ctx.game.value.player.effects.drawNext;
if (energyNext && energyNext.stacks > 0) { if (drawNext && drawNext.stacks > 0) {
await ctx.game.produceAsync(draft => { await ctx.game.produceAsync((draft) => {
draft.player.energy += energyNext.stacks; addEntityEffect(draft.player, drawNext.data, -drawNext.stacks);
addEntityEffect(draft.player, energyNext.data, -energyNext.stacks); });
}); await triggers.onDraw.execute(ctx.game, { count: drawNext.stacks });
} }
await next(); await next();
}); });
// drawNext: draw extra cards next turn
triggers.onTurnStart.use(async (ctx, next) => {
if (ctx.entityKey !== "player") {
await next();
return;
}
const drawNext = ctx.game.value.player.effects.drawNext;
if (drawNext && drawNext.stacks > 0) {
await ctx.game.produceAsync(draft => {
addEntityEffect(draft.player, drawNext.data, -drawNext.stacks);
});
await triggers.onDraw.execute(ctx.game, { count: drawNext.stacks });
}
await next();
});
} }

View File

@ -26,20 +26,14 @@ import {
InventoryItem, InventoryItem,
} from "@/samples/slay-the-spire-like/system/grid-inventory/types"; } from "@/samples/slay-the-spire-like/system/grid-inventory/types";
import { GameItemMeta } from "@/samples/slay-the-spire-like/system/grid-inventory/types"; import { GameItemMeta } from "@/samples/slay-the-spire-like/system/grid-inventory/types";
import { ParsedShape } from "@/samples/slay-the-spire-like/system/utils/parse-shape";
import { Transform2D } from "@/samples/slay-the-spire-like/system/utils/shape-collision";
import { import {
CardEffect, CardEffect,
getCards, getCards,
getEffects, getEffects,
getEncounters,
getEnemies, getEnemies,
getItems,
} from "@/samples/slay-the-spire-like/data/desert"; } from "@/samples/slay-the-spire-like/data/desert";
const cards = getCards(); const cards = getCards();
const effects = getEffects(); const effects = getEffects();
const encounters = getEncounters();
const items = getItems();
const enemies = getEnemies(); const enemies = getEnemies();
function createEffect( function createEffect(
@ -298,7 +292,7 @@ describe("desert triggers", () => {
}); });
expect(ctx.value.player.hp).toBe(27); expect(ctx.value.player.hp).toBe(27);
expect(ctx.value.player.effects.defend?.stacks).toBe(2); expect(ctx.value.player.effects.defend?.stacks).toBe(undefined);
}); });
it("should reduce damage with damageReduce", async () => { it("should reduce damage with damageReduce", async () => {