@rpgjs/action-battle 5.0.0-beta.12 → 5.0.0-beta.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -117,9 +117,10 @@ const applyDamageEffect = (
117
117
 
118
118
  if (!result.cancelled) {
119
119
  emitActionBattleClientVisual({
120
- moment: "hit",
120
+ moment: "hurt",
121
121
  entity: attacker,
122
122
  target,
123
+ attacker,
123
124
  damage: result.damage,
124
125
  result,
125
126
  skill,
@@ -85,9 +85,24 @@ export const defaultRpgjsDamageResolver = (
85
85
  context: ActionBattleDamageContext
86
86
  ) => {
87
87
  const target = context.target as any;
88
+ const previousHp =
89
+ typeof target.hp === "number" && Number.isFinite(target.hp)
90
+ ? target.hp
91
+ : undefined;
88
92
  const raw = target.applyDamage(context.attacker as any, context.skill);
93
+ const resolvedDamage = Number(raw?.damage ?? 0);
94
+ if (!Number.isFinite(resolvedDamage)) {
95
+ if (previousHp !== undefined) {
96
+ target.hp = previousHp;
97
+ }
98
+ return {
99
+ damage: 0,
100
+ defeated: false,
101
+ raw,
102
+ };
103
+ }
89
104
  return {
90
- damage: raw?.damage ?? 0,
105
+ damage: resolvedDamage,
91
106
  defeated: target.hp <= 0,
92
107
  raw,
93
108
  };
@@ -1,5 +1,6 @@
1
1
  import { afterEach, describe, expect, test, vi } from "vitest";
2
2
  import { applyActionBattleHit } from "./hit";
3
+ import { defaultRpgjsDamageResolver } from "./defaults";
3
4
  import type { ActionBattleCombatSystem } from "./contracts";
4
5
  import { setActionBattleInvincibility } from "./hit-reaction";
5
6
 
@@ -108,4 +109,24 @@ describe("applyActionBattleHit", () => {
108
109
  target: target as any,
109
110
  }).cancelled).toBe(true);
110
111
  });
112
+
113
+ test("normalizes invalid RPGJS damage without poisoning target hp", () => {
114
+ const attacker = entity();
115
+ const target = {
116
+ ...entity(100),
117
+ applyDamage() {
118
+ this.hp = Number.NaN;
119
+ return { damage: Number.NaN };
120
+ },
121
+ };
122
+
123
+ const result = defaultRpgjsDamageResolver({
124
+ attacker: attacker as any,
125
+ target: target as any,
126
+ });
127
+
128
+ expect(result.damage).toBe(0);
129
+ expect(result.defeated).toBe(false);
130
+ expect(target.hp).toBe(100);
131
+ });
111
132
  });
@@ -52,6 +52,18 @@ describe("action battle targets", () => {
52
52
  expect(canActionBattleTarget(attacker, target, "players")).toBe(false);
53
53
  });
54
54
 
55
+ test("classifies runtime players with shape helpers as players", () => {
56
+ const attacker = battleEvent("enemy-1", "enemies");
57
+ const target = {
58
+ ...player("player-1"),
59
+ attachShape() {},
60
+ isEvent: () => false,
61
+ };
62
+
63
+ expect(getActionBattleEntityKind(target as any)).toBe("player");
64
+ expect(canActionBattleTarget(attacker, target as any, "players")).toBe(true);
65
+ });
66
+
55
67
  test("supports player targets explicitly", () => {
56
68
  const attacker = player("player-1");
57
69
  const target = player("player-2");
@@ -17,9 +17,12 @@ export const getActionBattleEntityKind = (
17
17
  entity: ActionBattleEntity
18
18
  ): EntityKind => {
19
19
  if (getBattleAi(entity)) return "event";
20
+ if (typeof (entity as any)?.isEvent === "function") {
21
+ return (entity as any).isEvent() ? "event" : "player";
22
+ }
20
23
  if ((entity as any) instanceof RpgEvent) return "event";
21
- if (typeof (entity as any)?.attachShape === "function") return "event";
22
24
  if ((entity as any) instanceof RpgPlayer) return "player";
25
+ if (typeof (entity as any)?.attachShape === "function") return "event";
23
26
  return "player";
24
27
  };
25
28
 
package/src/visual.ts CHANGED
@@ -112,7 +112,7 @@ const callGraphic = (
112
112
  if (!entity || keyOrOptions == null) return;
113
113
 
114
114
  if (typeof keyOrOptions === "string") {
115
- playActionBattleAnimation(
115
+ const animation = playActionBattleAnimation(
116
116
  keyOrOptions as ActionBattleAnimationKey,
117
117
  entity,
118
118
  context?.animations ?? getActionBattleOptions().animations,