Compare commits
2 Commits
270b9b744e
...
5235ba7def
| Author | SHA1 | Date |
|---|---|---|
|
|
5235ba7def | |
|
|
6cb0626f05 |
|
|
@ -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) => void): void;
|
produce(fn: (draft: TState) => undefined): void;
|
||||||
produceAsync(fn: (draft: TState) => void): Promise<void>;
|
produceAsync(fn: (draft: TState) => undefined): 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) {
|
produce(fn: (draft: TState) => undefined) {
|
||||||
return state.produce(fn);
|
return state.produce(fn);
|
||||||
},
|
},
|
||||||
produceAsync(fn) {
|
produceAsync(fn: (draft: TState) => undefined) {
|
||||||
return state.produceAsync(fn);
|
return state.produceAsync(fn);
|
||||||
},
|
},
|
||||||
run<T>(input: string) {
|
run<T>(input: string) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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(
|
await ctx.game.produceAsync((draft) => {
|
||||||
(draft) => (draft.player.energy = draft.player.maxEnergy),
|
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,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,
|
||||||
|
|
|
||||||
|
|
@ -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) => void) {
|
produce(fn: (draft: T) => undefined) {
|
||||||
this.value = create(this.value, fn);
|
this.value = create(this.value, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,13 +30,16 @@ export class MutableSignal<T> extends Signal<T> {
|
||||||
* 异步版本的 produce。会先等待所有通过 `addInterruption` 添加的 Promise 完成,
|
* 异步版本的 produce。会先等待所有通过 `addInterruption` 添加的 Promise 完成,
|
||||||
* 然后再更新状态。适用于需要在状态更新前播放动画的场景。
|
* 然后再更新状态。适用于需要在状态更新前播放动画的场景。
|
||||||
*/
|
*/
|
||||||
async produceAsync(fn: (draft: T) => void): Promise<void> {
|
async produceAsync(fn: (draft: T) => undefined): 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>(initial?: T, options?: SignalOptions<T>): MutableSignal<T> {
|
export function mutableSignal<T>(
|
||||||
|
initial?: T,
|
||||||
|
options?: SignalOptions<T>,
|
||||||
|
): MutableSignal<T> {
|
||||||
return new MutableSignal<T>(initial, options);
|
return new MutableSignal<T>(initial, options);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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" });
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue