refactor: update damage triggers and combat start logic
- Update `defend` effect lifecycle to `temporary` in desert data - Refactor `onDamage` triggers to improve readability and logic flow - Implement shuffle and draw actions on `onCombatStart` trigger
This commit is contained in:
parent
5235ba7def
commit
2eec668851
|
|
@ -14,7 +14,7 @@
|
|||
id, name, description, lifecycle
|
||||
string, string, string, 'instant'|'temporary'|'lingering'|'permanent'|'posture'|'item'|'itemTemporary'|'itemUntilPlay'|'itemUntilDiscard'|'itemPermanent'
|
||||
attack, 攻击, 对对手造成伤害, instant
|
||||
defend, 防御, 抵消下次行动前受到的伤害, posture
|
||||
defend, 防御, 抵消下次行动前受到的伤害, temporary
|
||||
spike, 尖刺, 对攻击者造成X点伤害, permanent
|
||||
venom, 蛇毒, 同名状态牌/1费:打出时移除此牌。弃掉时受到3点伤害, instant
|
||||
curse, 诅咒, 受攻击时物品攻击-1,直到弃掉一张该物品的牌, lingering
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 14.
|
|
|
@ -3,7 +3,6 @@ import {
|
|||
addEntityEffect,
|
||||
getCombatEntity,
|
||||
} from "@/samples/slay-the-spire-like/system/combat/effects";
|
||||
import { CombatGameContext } from "@/samples/slay-the-spire-like/system/combat/types";
|
||||
import { EffectData } from "@/samples/slay-the-spire-like/system/types";
|
||||
import getEffects from "../effect.csv";
|
||||
|
||||
|
|
@ -13,7 +12,12 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
function findEffect(id: string): EffectData {
|
||||
const found = effects.find((e: EffectData) => e.id === id);
|
||||
if (found) return found;
|
||||
return { id, name: id, description: "", lifecycle: "instant" } as EffectData;
|
||||
return {
|
||||
id,
|
||||
name: id,
|
||||
description: "",
|
||||
lifecycle: "instant",
|
||||
} as EffectData;
|
||||
}
|
||||
|
||||
// block / damage prevention
|
||||
|
|
@ -23,13 +27,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
|
||||
let preventable = ctx.amount - (ctx.prevented ?? 0);
|
||||
|
||||
const blocks = entity.effects.defend?.stacks ?? 0;
|
||||
const blocked = Math.min(blocks, preventable);
|
||||
if (blocked) {
|
||||
ctx.prevented = (ctx.prevented ?? 0) + blocked;
|
||||
preventable -= blocked;
|
||||
}
|
||||
|
||||
// 1. apply damageReduce before block
|
||||
const damageReduce = entity.effects.damageReduce?.stacks ?? 0;
|
||||
if (damageReduce > 0) {
|
||||
const reduced = Math.min(damageReduce, preventable);
|
||||
|
|
@ -37,6 +35,18 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
preventable -= reduced;
|
||||
}
|
||||
|
||||
// 2. consume defend for damage prevented
|
||||
const blocks = entity.effects.defend?.stacks ?? 0;
|
||||
const blocked = Math.min(blocks, preventable);
|
||||
if (blocked > 0) {
|
||||
ctx.prevented = (ctx.prevented ?? 0) + blocked;
|
||||
preventable -= blocked;
|
||||
await ctx.game.produceAsync((draft) => {
|
||||
const e = getCombatEntity(draft, ctx.entityKey);
|
||||
if (e) addEntityEffect(e, findEffect("defend"), -blocked);
|
||||
});
|
||||
}
|
||||
|
||||
const expose = entity.effects.expose?.stacks ?? 0;
|
||||
if (expose > 0) {
|
||||
ctx.amount += expose;
|
||||
|
|
@ -71,9 +81,12 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
|
||||
const energyDrain = entity.effects.energyDrain?.stacks ?? 0;
|
||||
if (energyDrain > 0 && ctx.entityKey !== "player") {
|
||||
const dealt = Math.min(Math.max(0, entity.hp), ctx.amount - (ctx.prevented ?? 0));
|
||||
const dealt = Math.min(
|
||||
Math.max(0, entity.hp),
|
||||
ctx.amount - (ctx.prevented ?? 0),
|
||||
);
|
||||
if (dealt > 0) {
|
||||
await ctx.game.produceAsync(draft => {
|
||||
await ctx.game.produceAsync((draft) => {
|
||||
draft.player.energy = Math.max(0, draft.player.energy - energyDrain);
|
||||
});
|
||||
}
|
||||
|
|
@ -92,13 +105,15 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
|
||||
const molt = entity.effects.molt?.stacks ?? 0;
|
||||
if (molt >= entity.maxHp) {
|
||||
await ctx.game.produceAsync(draft => {
|
||||
const e = draft.enemies.find(en => en.id === ctx.entityKey);
|
||||
await ctx.game.produceAsync((draft) => {
|
||||
const e = draft.enemies.find((en) => en.id === ctx.entityKey);
|
||||
if (e) {
|
||||
e.isAlive = false;
|
||||
e.hp = 0;
|
||||
}
|
||||
draft.result = draft.enemies.every(en => !en.isAlive) ? "victory" : null;
|
||||
draft.result = draft.enemies.every((en) => !en.isAlive)
|
||||
? "victory"
|
||||
: null;
|
||||
});
|
||||
if (ctx.game.value.result) throw ctx.game.value;
|
||||
return;
|
||||
|
|
@ -127,7 +142,7 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
if (roll >= 10) {
|
||||
const rollDamage = Math.floor(roll / 10) * 10;
|
||||
ctx.amount += rollDamage;
|
||||
await ctx.game.produceAsync(draft => {
|
||||
await ctx.game.produceAsync((draft) => {
|
||||
addEntityEffect(draft.player, findEffect("roll"), -rollDamage);
|
||||
});
|
||||
}
|
||||
|
|
@ -155,11 +170,14 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
if (entity) {
|
||||
const charge = entity.effects.charge?.stacks ?? 0;
|
||||
if (charge > 0) {
|
||||
const dealt = Math.min(Math.max(0, entity.hp), ctx.amount - (ctx.prevented ?? 0));
|
||||
const dealt = Math.min(
|
||||
Math.max(0, entity.hp),
|
||||
ctx.amount - (ctx.prevented ?? 0),
|
||||
);
|
||||
const consumed = Math.min(charge, dealt);
|
||||
ctx.amount += dealt;
|
||||
if (consumed > 0) {
|
||||
await ctx.game.produceAsync(draft => {
|
||||
await ctx.game.produceAsync((draft) => {
|
||||
const e = getCombatEntity(draft, ctx.entityKey);
|
||||
if (e) addEntityEffect(e, findEffect("charge"), -consumed);
|
||||
});
|
||||
|
|
@ -174,11 +192,14 @@ export function addDamageTriggers(triggers: Triggers) {
|
|||
if (charge > 0) {
|
||||
const baseAmount = ctx.amount;
|
||||
const targetEntity = getCombatEntity(ctx.game.value, ctx.entityKey);
|
||||
const dealt = Math.min(Math.max(0, targetEntity?.hp ?? 0), baseAmount - (ctx.prevented ?? 0));
|
||||
const dealt = Math.min(
|
||||
Math.max(0, targetEntity?.hp ?? 0),
|
||||
baseAmount - (ctx.prevented ?? 0),
|
||||
);
|
||||
const consumed = Math.min(charge, dealt);
|
||||
ctx.amount += dealt;
|
||||
if (consumed > 0) {
|
||||
await ctx.game.produceAsync(draft => {
|
||||
await ctx.game.produceAsync((draft) => {
|
||||
const a = getCombatEntity(draft, ctx.sourceEntityKey!);
|
||||
if (a) addEntityEffect(a, findEffect("charge"), -consumed);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -51,7 +51,10 @@ type TriggerTypes = {
|
|||
|
||||
export function createTriggers(run: IRunContext) {
|
||||
const triggers = {
|
||||
onCombatStart: createTrigger("onCombatStart"),
|
||||
onCombatStart: createTrigger("onCombatStart", async (ctx) => {
|
||||
await triggers.onShuffle.execute(ctx.game, {});
|
||||
await triggers.onDraw.execute(ctx.game, { count: 5 });
|
||||
}),
|
||||
onTurnStart: createTrigger("onTurnStart", async (ctx) => {
|
||||
await ctx.game.produceAsync((draft) => {
|
||||
const entity = getCombatEntity(draft, ctx.entityKey);
|
||||
|
|
|
|||
Loading…
Reference in New Issue