Compare commits

..

No commits in common. "5235ba7def516639de117b8167d1665e58ec5658" and "270b9b744e17a731d305b3f8301fd149db3c8ceb" have entirely different histories.

5 changed files with 22 additions and 43 deletions

View File

@ -15,8 +15,8 @@ import { Mulberry32RNG, ReadonlyRNG, RNG } from "@/utils/rng";
export interface IGameContext<TState extends Record<string, unknown> = {}> { export interface IGameContext<TState extends Record<string, unknown> = {}> {
get value(): TState; get value(): TState;
get rng(): ReadonlyRNG; get rng(): ReadonlyRNG;
produce(fn: (draft: TState) => undefined): void; produce(fn: (draft: TState) => void): void;
produceAsync(fn: (draft: TState) => undefined): Promise<void>; produceAsync(fn: (draft: TState) => void): Promise<void>;
run<T>(input: string): Promise<CommandResult<T>>; run<T>(input: string): Promise<CommandResult<T>>;
runParsed<T>(command: Command): Promise<CommandResult<T>>; runParsed<T>(command: Command): Promise<CommandResult<T>>;
prompt: <TResult, TArgs extends any[] = any[]>( prompt: <TResult, TArgs extends any[] = any[]>(
@ -51,10 +51,10 @@ export function createGameContext<TState extends Record<string, unknown> = {}>(
get rng() { get rng() {
return this._rng; return this._rng;
}, },
produce(fn: (draft: TState) => undefined) { produce(fn) {
return state.produce(fn); return state.produce(fn);
}, },
produceAsync(fn: (draft: TState) => undefined) { produceAsync(fn) {
return state.produceAsync(fn); return state.produceAsync(fn);
}, },
run<T>(input: string) { run<T>(input: string) {

View File

@ -107,16 +107,12 @@ 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

@ -65,9 +65,9 @@ export function createTriggers(run: IRunContext) {
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 });
} }
await ctx.game.produceAsync((draft) => { await ctx.game.produceAsync(
draft.player.energy = draft.player.maxEnergy; (draft) => (draft.player.energy = draft.player.maxEnergy),
}); );
await triggers.onDraw.execute(ctx.game, { count: 5 }); await triggers.onDraw.execute(ctx.game, { count: 5 });
}), }),
onShuffle: createTrigger("onShuffle", async (ctx) => { onShuffle: createTrigger("onShuffle", async (ctx) => {
@ -98,12 +98,7 @@ 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( for (const entity of getEffectTargets(target, ctx.game, ctx.targetId))
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,
@ -126,12 +121,7 @@ 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( for (const entity of getEffectTargets(target, ctx.game))
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,
@ -152,12 +142,7 @@ 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( for (const entity of getEffectTargets(target, ctx.game))
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,
@ -251,12 +236,7 @@ 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( for (const entity of getEffectTargets(target, ctx.game))
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

@ -1,5 +1,5 @@
import { Signal, SignalOptions } from "@preact/signals-core"; import {Signal, SignalOptions} from '@preact/signals-core';
import { create } from "mutative"; import {create} from 'mutative';
export class MutableSignal<T> extends Signal<T> { export class MutableSignal<T> extends Signal<T> {
private _interruptions: Promise<void>[] = []; private _interruptions: Promise<void>[] = [];
@ -7,7 +7,7 @@ export class MutableSignal<T> extends Signal<T> {
public constructor(t?: T, options?: SignalOptions<T>) { public constructor(t?: T, options?: SignalOptions<T>) {
super(t, options); super(t, options);
} }
produce(fn: (draft: T) => undefined) { produce(fn: (draft: T) => void) {
this.value = create(this.value, fn); this.value = create(this.value, fn);
} }
@ -30,16 +30,13 @@ export class MutableSignal<T> extends Signal<T> {
* produce `addInterruption` Promise * produce `addInterruption` Promise
* *
*/ */
async produceAsync(fn: (draft: T) => undefined): Promise<void> { async produceAsync(fn: (draft: T) => void): Promise<void> {
await Promise.allSettled(this._interruptions); await Promise.allSettled(this._interruptions);
this._interruptions = []; this._interruptions = [];
this.produce(fn); this.produce(fn);
} }
} }
export function mutableSignal<T>( export function mutableSignal<T>(initial?: T, options?: SignalOptions<T>): MutableSignal<T> {
initial?: T,
options?: SignalOptions<T>,
): MutableSignal<T> {
return new MutableSignal<T>(initial, options); return new MutableSignal<T>(initial, options);
} }

View File

@ -382,6 +382,12 @@ 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" });