feat(slay-the-spire-like): support source entity in effect targeting

Update `getEffectTargets` to accept a `sourceEntityKey`. This allows
"self" targets to correctly resolve to the entity triggering the
effect (e.g., a player or a specific enemy) rather than defaulting
to a hardcoded player reference.
This commit is contained in:
hypercross 2026-04-22 08:56:06 +08:00
parent 6cb0626f05
commit 5235ba7def
3 changed files with 28 additions and 10 deletions

View File

@ -107,12 +107,16 @@ export function* getEffectTargets(
target: CardEffectTarget | EffectTarget, target: CardEffectTarget | EffectTarget,
game: CombatGameContext, game: CombatGameContext,
targetId?: string, targetId?: string,
sourceEntityKey: "player" | string = "player",
) { ) {
if (target === "all" || target === "team") { if (target === "all" || target === "team") {
for (const enemy of getAliveEnemies(game.value)) { for (const enemy of getAliveEnemies(game.value)) {
yield enemy; yield enemy;
} }
} else if (target === "self") { } else if (target === "self") {
const entity = getCombatEntity(game.value, sourceEntityKey);
if (entity) yield entity;
} else if (target === "player") {
yield game.value.player; yield game.value.player;
} else if (target === "target") { } else if (target === "target") {
if (!targetId) return; if (!targetId) return;

View File

@ -98,7 +98,12 @@ export function createTriggers(run: IRunContext) {
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)
for (const entity of getEffectTargets(target, ctx.game, ctx.targetId)) for (const entity of getEffectTargets(
target,
ctx.game,
ctx.targetId,
source,
))
await triggers.onEffectApplied.execute(ctx.game, { await triggers.onEffectApplied.execute(ctx.game, {
effect, effect,
entityKey: entity.id, entityKey: entity.id,
@ -121,7 +126,12 @@ export function createTriggers(run: IRunContext) {
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)
for (const entity of getEffectTargets(target, ctx.game)) for (const entity of getEffectTargets(
target,
ctx.game,
undefined,
source,
))
await triggers.onEffectApplied.execute(ctx.game, { await triggers.onEffectApplied.execute(ctx.game, {
effect, effect,
entityKey: entity.id, entityKey: entity.id,
@ -142,7 +152,12 @@ export function createTriggers(run: IRunContext) {
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)
for (const entity of getEffectTargets(target, ctx.game)) for (const entity of getEffectTargets(
target,
ctx.game,
undefined,
source,
))
await triggers.onEffectApplied.execute(ctx.game, { await triggers.onEffectApplied.execute(ctx.game, {
effect, effect,
entityKey: entity.id, entityKey: entity.id,
@ -236,7 +251,12 @@ export function createTriggers(run: IRunContext) {
const source = ctx.sourceEntityKey ?? enemy.id; const source = ctx.sourceEntityKey ?? enemy.id;
for (const [target, effect, stacks] of intent.effects) { for (const [target, effect, stacks] of intent.effects) {
for (const entity of getEffectTargets(target, ctx.game)) for (const entity of getEffectTargets(
target,
ctx.game,
undefined,
source,
))
await triggers.onEffectApplied.execute(ctx.game, { await triggers.onEffectApplied.execute(ctx.game, {
effect, effect,
entityKey: entity.id, entityKey: entity.id,

View File

@ -382,12 +382,6 @@ describe("desert triggers", () => {
}), }),
); );
const triggers = getTriggers(); const triggers = getTriggers();
const stormEffect = createEffect("storm", "permanent");
ctx._state.produce((draft) => {
const enemy = draft.enemies[0];
enemy.effects.storm = { data: stormEffect, stacks: 2 };
});
await triggers.onEnemyIntent.execute(ctx, { enemyId: "风暴之灵-0" }); await triggers.onEnemyIntent.execute(ctx, { enemyId: "风暴之灵-0" });