@rpgjs/action-battle 5.0.0-beta.11 → 5.0.0-beta.13

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.
Files changed (111) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/client/ai.server.d.ts +57 -8
  3. package/dist/client/attack-input.d.ts +3 -0
  4. package/dist/client/core/action-use.d.ts +18 -0
  5. package/dist/client/core/ai-behavior-tree.d.ts +99 -0
  6. package/dist/client/core/attack-runtime.d.ts +2 -0
  7. package/dist/client/core/defaults.d.ts +3 -2
  8. package/dist/client/core/equipment.d.ts +1 -0
  9. package/dist/client/core/targets.d.ts +15 -0
  10. package/dist/client/enemies/factory.d.ts +2 -0
  11. package/dist/client/index.d.ts +12 -7
  12. package/dist/client/index.js +16 -11
  13. package/dist/client/index10.js +32 -56
  14. package/dist/client/index11.js +99 -52
  15. package/dist/client/index12.js +76 -103
  16. package/dist/client/index13.js +72 -135
  17. package/dist/client/index14.js +67 -23
  18. package/dist/client/index15.js +197 -63
  19. package/dist/client/index16.js +112 -1337
  20. package/dist/client/index17.js +203 -7
  21. package/dist/client/index18.js +32 -58
  22. package/dist/client/index19.js +70 -8
  23. package/dist/client/index20.js +57 -501
  24. package/dist/client/index21.js +70 -0
  25. package/dist/client/index22.js +226 -0
  26. package/dist/client/index23.js +16 -0
  27. package/dist/client/index24.js +25 -0
  28. package/dist/client/index25.js +107 -0
  29. package/dist/client/index26.js +1949 -0
  30. package/dist/client/index27.js +12 -0
  31. package/dist/client/index28.js +589 -0
  32. package/dist/client/index4.js +79 -38
  33. package/dist/client/index6.js +65 -306
  34. package/dist/client/index7.js +33 -33
  35. package/dist/client/index8.js +24 -100
  36. package/dist/client/index9.js +293 -61
  37. package/dist/client/locomotion.d.ts +16 -0
  38. package/dist/client/movement.d.ts +14 -0
  39. package/dist/client/server.d.ts +7 -3
  40. package/dist/client/ui.d.ts +22 -0
  41. package/dist/client/visual.d.ts +15 -0
  42. package/dist/server/ai.server.d.ts +57 -8
  43. package/dist/server/attack-input.d.ts +3 -0
  44. package/dist/server/core/action-use.d.ts +18 -0
  45. package/dist/server/core/ai-behavior-tree.d.ts +99 -0
  46. package/dist/server/core/attack-runtime.d.ts +2 -0
  47. package/dist/server/core/defaults.d.ts +3 -2
  48. package/dist/server/core/equipment.d.ts +1 -0
  49. package/dist/server/core/targets.d.ts +15 -0
  50. package/dist/server/enemies/factory.d.ts +2 -0
  51. package/dist/server/index.d.ts +12 -7
  52. package/dist/server/index.js +14 -9
  53. package/dist/server/index10.js +64 -1336
  54. package/dist/server/index11.js +33 -33
  55. package/dist/server/index13.js +67 -11
  56. package/dist/server/index14.js +207 -484
  57. package/dist/server/index15.js +15 -9
  58. package/dist/server/index16.js +26 -0
  59. package/dist/server/index17.js +25 -0
  60. package/dist/server/index18.js +107 -0
  61. package/dist/server/index19.js +1949 -0
  62. package/dist/server/index2.js +10 -2
  63. package/dist/server/index20.js +37 -0
  64. package/dist/server/index21.js +588 -0
  65. package/dist/server/index22.js +78 -0
  66. package/dist/server/index23.js +12 -0
  67. package/dist/server/index5.js +79 -38
  68. package/dist/server/index6.js +192 -129
  69. package/dist/server/index7.js +208 -24
  70. package/dist/server/index8.js +28 -66
  71. package/dist/server/index9.js +68 -51
  72. package/dist/server/locomotion.d.ts +16 -0
  73. package/dist/server/movement.d.ts +14 -0
  74. package/dist/server/server.d.ts +7 -3
  75. package/dist/server/ui.d.ts +22 -0
  76. package/dist/server/visual.d.ts +15 -0
  77. package/package.json +5 -5
  78. package/src/ai.server.spec.ts +380 -1
  79. package/src/ai.server.ts +963 -137
  80. package/src/animations.spec.ts +40 -0
  81. package/src/animations.ts +31 -9
  82. package/src/attack-input.spec.ts +51 -0
  83. package/src/attack-input.ts +59 -0
  84. package/src/client.ts +75 -62
  85. package/src/config.ts +84 -37
  86. package/src/core/action-use.spec.ts +317 -0
  87. package/src/core/action-use.ts +387 -0
  88. package/src/core/ai-behavior-tree.spec.ts +116 -0
  89. package/src/core/ai-behavior-tree.ts +272 -0
  90. package/src/core/attack-profile.spec.ts +46 -0
  91. package/src/core/attack-runtime.spec.ts +35 -0
  92. package/src/core/attack-runtime.ts +32 -0
  93. package/src/core/context.ts +9 -0
  94. package/src/core/contracts.ts +146 -1
  95. package/src/core/defaults.ts +72 -1
  96. package/src/core/equipment.ts +9 -5
  97. package/src/core/hit.spec.ts +21 -0
  98. package/src/core/targets.spec.ts +124 -0
  99. package/src/core/targets.ts +150 -0
  100. package/src/enemies/factory.ts +8 -0
  101. package/src/index.ts +111 -2
  102. package/src/locomotion.spec.ts +51 -0
  103. package/src/locomotion.ts +48 -0
  104. package/src/movement.spec.ts +78 -0
  105. package/src/movement.ts +46 -0
  106. package/src/server.ts +242 -66
  107. package/src/types.ts +105 -35
  108. package/src/ui.ts +113 -0
  109. package/src/visual.spec.ts +166 -0
  110. package/src/visual.ts +285 -0
  111. package/README.md +0 -1242
@@ -1,102 +1,26 @@
1
- import { actionBattleTargetingState, actionBattleUiOptions } from "./index5.js";
2
- import { parseAoeMask } from "./index7.js";
3
- import { RpgClientEngine, inject } from "@rpgjs/client";
4
- import { Container, Graphics, computed, cond, h, useDefineProps, useProps } from "canvasengine";
5
- //#region src/components/targeting-overlay.ce
6
- function component($$props) {
7
- useProps($$props);
8
- const { object } = useDefineProps($$props)();
9
- const engine = inject(RpgClientEngine);
10
- const isCurrentPlayer = computed(() => {
11
- if (!object?.id) return false;
12
- return (typeof object.id === "function" ? object.id() : object.id) === engine.playerId;
1
+ //#region src/locomotion.ts
2
+ var withActionBattleAnimationUnlocked = (entity, callback) => {
3
+ if (!entity) return callback();
4
+ const previousAnimationFixed = entity.animationFixed;
5
+ entity.animationFixed = false;
6
+ try {
7
+ return callback();
8
+ } finally {
9
+ entity.animationFixed = previousAnimationFixed;
10
+ }
11
+ };
12
+ /**
13
+ * Force a locomotion animation even when an action lock temporarily froze
14
+ * animation changes. This keeps server state and local rendering coherent
15
+ * after attack recovery interrupts movement.
16
+ */
17
+ var forceActionBattleLocomotionAnimation = (entity, animationName) => {
18
+ if (!entity) return;
19
+ withActionBattleAnimationUnlocked(entity, () => {
20
+ if (typeof entity.resetAnimationState === "function") entity.resetAnimationState();
21
+ if (typeof entity.setGraphicAnimation === "function") entity.setGraphicAnimation(animationName);
22
+ else if (typeof entity.animationName?.set === "function") entity.animationName.set(animationName);
13
23
  });
14
- const uiOptions = computed(() => actionBattleUiOptions());
15
- const targetingState = computed(() => actionBattleTargetingState());
16
- const shouldRender = computed(() => {
17
- if (!isCurrentPlayer()) return false;
18
- if (!uiOptions().targeting?.enabled) return false;
19
- return targetingState().active;
20
- });
21
- const getTileSize = () => {
22
- const uiTile = uiOptions().targeting?.tileSize;
23
- if (uiTile?.width && uiTile?.height) return uiTile;
24
- const hitbox = object.hitbox?.() || {
25
- w: 32,
26
- h: 32
27
- };
28
- return {
29
- width: hitbox.w || 32,
30
- height: hitbox.h || 32
31
- };
32
- };
33
- const getOriginTile = () => {
34
- const hitbox = object.hitbox?.() || {
35
- w: 32,
36
- h: 32
37
- };
38
- const tileSize = getTileSize();
39
- return {
40
- x: Math.floor((object.x() + hitbox.w / 2) / tileSize.width),
41
- y: Math.floor((object.y() + hitbox.h / 2) / tileSize.height)
42
- };
43
- };
44
- const toColor = (value, fallback) => {
45
- if (typeof value === "number") return value;
46
- return fallback;
47
- };
48
- const drawGrid = (g) => {
49
- const state = targetingState();
50
- if (!state.active) return;
51
- const tileSize = getTileSize();
52
- const origin = getOriginTile();
53
- const target = {
54
- x: origin.x + state.offset.x,
55
- y: origin.y + state.offset.y
56
- };
57
- const mask = parseAoeMask(state.aoeMask);
58
- const colors = uiOptions().targeting?.colors || {};
59
- const areaColor = toColor(colors.area, 3120887);
60
- const edgeColor = toColor(colors.edge, 1796760);
61
- const cursorColor = toColor(colors.cursor, 16765286);
62
- const showGrid = uiOptions().targeting?.showGrid !== false;
63
- const playerX = object.x();
64
- const playerY = object.y();
65
- g.clear();
66
- mask.cells.forEach((cell) => {
67
- const tileX = target.x + cell.dx;
68
- const tileY = target.y + cell.dy;
69
- const worldX = tileX * tileSize.width;
70
- const worldY = tileY * tileSize.height;
71
- const relX = worldX - playerX;
72
- const relY = worldY - playerY;
73
- g.rect(relX, relY, tileSize.width, tileSize.height);
74
- g.fill({
75
- color: areaColor,
76
- alpha: .35
77
- });
78
- if (showGrid) {
79
- g.rect(relX, relY, tileSize.width, tileSize.height);
80
- g.stroke({
81
- color: edgeColor,
82
- alpha: .9,
83
- width: 1
84
- });
85
- }
86
- });
87
- const cursorWorldX = target.x * tileSize.width;
88
- const cursorWorldY = target.y * tileSize.height;
89
- const cursorRelX = cursorWorldX - playerX;
90
- const cursorRelY = cursorWorldY - playerY;
91
- g.rect(cursorRelX, cursorRelY, tileSize.width, tileSize.height);
92
- g.stroke({
93
- color: cursorColor,
94
- alpha: 1,
95
- width: 2
96
- });
97
- };
98
- return h(Container, null, cond(shouldRender, () => h(Graphics, { draw: drawGrid })));
99
- }
100
- var __ce_component = component;
24
+ };
101
25
  //#endregion
102
- export { __ce_component as default };
26
+ export { forceActionBattleLocomotionAnimation, withActionBattleAnimationUnlocked };
@@ -1,78 +1,310 @@
1
- import { actionBattleAttackPreviewState } from "./index5.js";
2
- import { RpgClientEngine, inject } from "@rpgjs/client";
3
- import { Container, Graphics, computed, cond, h, signal, tick, useDefineProps, useProps } from "canvasengine";
4
- //#region src/components/attack-preview.ce
1
+ import { actionBattleTargetingState, actionBattleUiOptions, moveTargetingOffset, startTargeting, stopTargeting } from "./index5.js";
2
+ import { RpgClientEngine, getKeyboardControlBind, inject } from "@rpgjs/client";
3
+ import { DOMContainer, DOMElement, DOMSprite, computed, cond, effect, h, loop, signal, useDefineProps, useProps } from "canvasengine";
4
+ //#region src/components/action-bar.ce
5
+ if (typeof document !== "undefined") {
6
+ let styleElement = document.getElementById("ce-style--home-runner-work-RPG-JS-RPG-JS-packages-action-battle-src-components-action-bar-ce");
7
+ if (!styleElement) {
8
+ styleElement = document.createElement("style");
9
+ styleElement.id = "ce-style--home-runner-work-RPG-JS-RPG-JS-packages-action-battle-src-components-action-bar-ce";
10
+ document.head.appendChild(styleElement);
11
+ }
12
+ styleElement.textContent = ".action-battle-actionbar-root {\n pointer-events: none;\n }\n\n .action-battle-actionbar {\n position: absolute;\n left: 12px;\n right: 12px;\n bottom: 12px;\n pointer-events: auto;\n display: flex;\n justify-content: center;\n }\n\n .action-battle-actionbar-plate {\n width: min(760px, 100%);\n --rpg-ui-hotbar-size: clamp(38px, 8vw, 52px);\n }\n\n .action-battle-actionbar-track {\n --rpg-ui-hotbar-slots: 10;\n }";
13
+ }
5
14
  function component($$props) {
6
15
  useProps($$props);
7
- const { object } = useDefineProps($$props)();
16
+ const defineProps = useDefineProps($$props);
8
17
  const engine = inject(RpgClientEngine);
9
- const now = signal(Date.now());
10
- tick(() => {
11
- if (actionBattleAttackPreviewState().active) now.set(Date.now());
18
+ const keyboardControls = engine.globalConfig.keyboardControls;
19
+ const { data, onInteraction, onBack } = defineProps();
20
+ const ACTION_BAR_SIZE = 10;
21
+ const SLOT_LABELS = [
22
+ "1",
23
+ "2",
24
+ "3",
25
+ "4",
26
+ "5",
27
+ "6",
28
+ "7",
29
+ "8",
30
+ "9",
31
+ "0"
32
+ ];
33
+ const SLOT_CONFIG_KEYS = [
34
+ "hotbar1",
35
+ "hotbar2",
36
+ "hotbar3",
37
+ "hotbar4",
38
+ "hotbar5",
39
+ "hotbar6",
40
+ "hotbar7",
41
+ "hotbar8",
42
+ "hotbar9",
43
+ "hotbar0"
44
+ ];
45
+ const selectedSlotIndex = signal(-1);
46
+ const uiOptions = computed(() => actionBattleUiOptions());
47
+ const showItems = computed(() => {
48
+ const mode = uiOptions().actionBar?.mode || "both";
49
+ return mode === "items" || mode === "both";
12
50
  });
13
- const isCurrentPlayer = computed(() => {
14
- if (!object?.id) return false;
15
- return (typeof object.id === "function" ? object.id() : object.id) === engine.playerId;
51
+ const showSkills = computed(() => {
52
+ const mode = uiOptions().actionBar?.mode || "both";
53
+ return mode === "skills" || mode === "both";
16
54
  });
17
- const preview = computed(() => actionBattleAttackPreviewState());
18
- const progress = computed(() => {
19
- const state = preview();
20
- if (!state.active) return 1;
21
- const elapsed = now() - state.startedAt;
22
- return Math.max(0, Math.min(1, elapsed / state.durationMs));
55
+ const isTargeting = computed(() => actionBattleTargetingState().active);
56
+ const iconSheet = (iconId) => ({
57
+ definition: engine.getSpriteSheet(iconId),
58
+ playing: "default"
23
59
  });
24
- const shouldRender = computed(() => {
25
- const state = preview();
26
- return isCurrentPlayer() && state.active && progress() < 1;
60
+ const resolveProp = (value) => typeof value === "function" ? value() : value;
61
+ const actionBarData = computed(() => resolveProp(data) || {
62
+ items: [],
63
+ skills: []
27
64
  });
28
- const getHitbox = () => object.hitbox?.() || {
29
- w: 32,
30
- h: 32
31
- };
32
- const drawRect = (g, x, y, width, height, color, alpha) => {
33
- g.rect(x, y, width, height);
34
- g.fill({
35
- color,
36
- alpha
65
+ const actionBarSlots = computed(() => {
66
+ const entries = [];
67
+ if (showSkills()) (actionBarData().skills || []).forEach((skill, index) => {
68
+ entries.push({
69
+ type: "skill",
70
+ skill,
71
+ item: null,
72
+ sourceIndex: index
73
+ });
74
+ });
75
+ if (showItems()) (actionBarData().items || []).forEach((item, index) => {
76
+ entries.push({
77
+ type: "item",
78
+ skill: null,
79
+ item,
80
+ sourceIndex: index
81
+ });
37
82
  });
83
+ const slots = entries.slice(0, ACTION_BAR_SIZE).map((entry, index) => ({
84
+ ...entry,
85
+ label: SLOT_LABELS[index]
86
+ }));
87
+ while (slots.length < ACTION_BAR_SIZE) slots.push({
88
+ type: "empty",
89
+ skill: null,
90
+ item: null,
91
+ sourceIndex: -1,
92
+ label: SLOT_LABELS[slots.length]
93
+ });
94
+ return slots;
95
+ });
96
+ const hasSlotEntry = (slot) => slot.type === "skill" || slot.type === "item";
97
+ const isSlotDisabled = (slot) => {
98
+ if (!hasSlotEntry(slot)) return true;
99
+ const entry = slot.type === "skill" ? slot.skill : slot.item;
100
+ return !entry || !entry.usable;
38
101
  };
39
- const drawSlash = (g) => {
40
- g.clear();
41
- if (!shouldRender()) return;
42
- const state = preview();
43
- const p = progress();
44
- const alpha = Math.sin(Math.PI * p);
45
- if (alpha <= 0) return;
46
- const hitbox = getHitbox();
47
- const width = hitbox.w || 32;
48
- const height = hitbox.h || 32;
49
- const reach = 16 + 18 * p;
50
- const thickness = 4 + 3 * (1 - p);
51
- const color = state.color;
52
- const accent = state.accentColor;
53
- if (state.direction === "left") {
54
- drawRect(g, -reach - 6, height * .24, reach, thickness, accent, alpha * .55);
55
- drawRect(g, -reach - 10, height * .46, reach + 4, thickness + 2, color, alpha);
56
- drawRect(g, -reach - 6, height * .7, reach, thickness, accent, alpha * .4);
57
- return;
58
- }
59
- if (state.direction === "right") {
60
- drawRect(g, width + 6, height * .24, reach, thickness, accent, alpha * .55);
61
- drawRect(g, width + 6, height * .46, reach + 4, thickness + 2, color, alpha);
62
- drawRect(g, width + 6, height * .7, reach, thickness, accent, alpha * .4);
102
+ const getItemQuantity = (item) => {
103
+ if (!item) return 0;
104
+ if (typeof item.quantity === "function") return item.quantity();
105
+ return item.quantity || 0;
106
+ };
107
+ const selectItem = (item) => {
108
+ if (!item || !item.usable) return;
109
+ if (onInteraction) onInteraction("useItem", { id: item.id });
110
+ };
111
+ const selectSkill = (skill) => {
112
+ if (!skill || !skill.usable) return;
113
+ if ((skill.range ?? 0) > 0 || skill.aoeMask) {
114
+ startTargeting(skill);
63
115
  return;
64
116
  }
65
- if (state.direction === "up") {
66
- drawRect(g, width * .24, -reach - 6, thickness, reach, accent, alpha * .55);
67
- drawRect(g, width * .46, -reach - 10, thickness + 2, reach + 4, color, alpha);
68
- drawRect(g, width * .7, -reach - 6, thickness, reach, accent, alpha * .4);
117
+ if (onInteraction) onInteraction("useSkill", { id: skill.id });
118
+ };
119
+ const selectSlot = (index) => {
120
+ const slot = actionBarSlots()[index];
121
+ if (!slot || !hasSlotEntry(slot)) return;
122
+ if (slot.type === "skill") {
123
+ selectSkill(slot.skill);
69
124
  return;
70
125
  }
71
- drawRect(g, width * .24, height + 6, thickness, reach, accent, alpha * .55);
72
- drawRect(g, width * .46, height + 6, thickness + 2, reach + 4, color, alpha);
73
- drawRect(g, width * .7, height + 6, thickness, reach, accent, alpha * .4);
126
+ selectItem(slot.item);
74
127
  };
75
- return h(Container, null, cond(shouldRender, () => h(Graphics, { draw: drawSlash })));
128
+ const onSelectSlot = (index) => () => {
129
+ selectedSlotIndex.set(index);
130
+ selectSlot(index);
131
+ };
132
+ const getPlayerTile = () => {
133
+ const player = engine.scene.getCurrentPlayer();
134
+ if (!player) return null;
135
+ const hitbox = player.hitbox?.() || {
136
+ w: 32,
137
+ h: 32
138
+ };
139
+ const tileWidth = hitbox.w || 32;
140
+ const tileHeight = hitbox.h || 32;
141
+ return {
142
+ x: Math.floor((player.x() + hitbox.w / 2) / tileWidth),
143
+ y: Math.floor((player.y() + hitbox.h / 2) / tileHeight)
144
+ };
145
+ };
146
+ const confirmTargeting = () => {
147
+ const state = actionBattleTargetingState();
148
+ if (!state.skill) return;
149
+ const origin = getPlayerTile();
150
+ if (!origin) return;
151
+ const target = {
152
+ x: origin.x + state.offset.x,
153
+ y: origin.y + state.offset.y
154
+ };
155
+ if (onInteraction) onInteraction("useSkill", {
156
+ id: state.skill.id,
157
+ target
158
+ });
159
+ stopTargeting();
160
+ };
161
+ const resolveKeyBind = (key) => {
162
+ if (!key) return null;
163
+ if (typeof key === "string" && keyboardControls?.[key]) return keyboardControls[key];
164
+ return key;
165
+ };
166
+ const slotBind = (index) => keyboardControls?.[SLOT_CONFIG_KEYS[index]] || SLOT_LABELS[index];
167
+ const buildControls = () => {
168
+ const hotbarControls = {};
169
+ actionBarSlots().forEach((slot, index) => {
170
+ if (!hasSlotEntry(slot)) return;
171
+ const bind = slotBind(index);
172
+ hotbarControls[`slot-${index}`] = {
173
+ bind,
174
+ keyDown() {
175
+ if (isTargeting()) return;
176
+ selectedSlotIndex.set(index);
177
+ selectSlot(index);
178
+ }
179
+ };
180
+ if (slot.type === "skill") {
181
+ const skillBind = resolveKeyBind(slot.skill?.key);
182
+ if (!skillBind || skillBind === bind) return;
183
+ hotbarControls[`skill-${index}`] = {
184
+ bind: skillBind,
185
+ keyDown() {
186
+ if (isTargeting()) return;
187
+ selectedSlotIndex.set(index);
188
+ selectSlot(index);
189
+ }
190
+ };
191
+ }
192
+ });
193
+ return {
194
+ left: {
195
+ repeat: true,
196
+ bind: keyboardControls.left,
197
+ throttle: 150,
198
+ keyDown() {
199
+ if (isTargeting()) moveTargetingOffset(-1, 0);
200
+ }
201
+ },
202
+ right: {
203
+ repeat: true,
204
+ bind: keyboardControls.right,
205
+ throttle: 150,
206
+ keyDown() {
207
+ if (isTargeting()) moveTargetingOffset(1, 0);
208
+ }
209
+ },
210
+ up: {
211
+ repeat: true,
212
+ bind: keyboardControls.up,
213
+ throttle: 150,
214
+ keyDown() {
215
+ if (isTargeting()) moveTargetingOffset(0, -1);
216
+ }
217
+ },
218
+ down: {
219
+ repeat: true,
220
+ bind: keyboardControls.down,
221
+ throttle: 150,
222
+ keyDown() {
223
+ if (isTargeting()) moveTargetingOffset(0, 1);
224
+ }
225
+ },
226
+ action: {
227
+ bind: getKeyboardControlBind(keyboardControls.action),
228
+ keyDown() {
229
+ if (isTargeting()) confirmTargeting();
230
+ }
231
+ },
232
+ escape: {
233
+ bind: keyboardControls.escape,
234
+ keyDown() {
235
+ if (isTargeting()) {
236
+ stopTargeting();
237
+ return;
238
+ }
239
+ if (onBack) onBack();
240
+ }
241
+ },
242
+ ...hotbarControls,
243
+ gamepad: { enabled: true }
244
+ };
245
+ };
246
+ const controls = signal(buildControls());
247
+ effect(() => {
248
+ controls.set(buildControls());
249
+ });
250
+ return h(DOMContainer, {
251
+ width: "100%",
252
+ height: "100%",
253
+ attrs: { class: "action-battle-actionbar-root" },
254
+ controls
255
+ }, h(DOMElement, {
256
+ element: "div",
257
+ attrs: { class: "action-battle-actionbar" }
258
+ }, h(DOMElement, {
259
+ element: "div",
260
+ attrs: { class: "rpg-ui-hotbar action-battle-actionbar-plate" }
261
+ }, h(DOMElement, {
262
+ element: "div",
263
+ attrs: { class: "rpg-ui-hotbar-track action-battle-actionbar-track" }
264
+ }, loop(actionBarSlots, (slot, index) => h(DOMElement, {
265
+ element: "div",
266
+ attrs: {
267
+ class: "rpg-ui-hotbar-slot action-battle-actionbar-slot",
268
+ "data-selected": computed(() => selectedSlotIndex() === index ? "true" : "false"),
269
+ "data-disabled": computed(() => isSlotDisabled(slot) ? "true" : "false"),
270
+ "data-empty": computed(() => hasSlotEntry(slot) ? "false" : "true"),
271
+ "data-type": slot.type,
272
+ tabindex: computed(() => hasSlotEntry(slot) ? index : -1),
273
+ click: hasSlotEntry(slot) ? onSelectSlot(index) : void 0
274
+ }
275
+ }, [
276
+ h(DOMElement, {
277
+ element: "span",
278
+ attrs: { class: "rpg-ui-hotbar-key action-battle-actionbar-key" },
279
+ textContent: slot.label
280
+ }),
281
+ cond(computed(() => slot.type === "skill" && slot.skill?.icon), () => h(DOMSprite, {
282
+ sheet: computed(() => iconSheet(slot.skill.icon)),
283
+ width: "60px",
284
+ height: "60px",
285
+ scale: 2,
286
+ objectFit: "contain"
287
+ }), [computed(() => slot.type === "item" && slot.item?.icon), () => h(DOMSprite, {
288
+ sheet: computed(() => iconSheet(slot.item.icon)),
289
+ width: "60px",
290
+ height: "60px",
291
+ scale: 2,
292
+ objectFit: "contain"
293
+ })], [computed(() => slot.type === "skill" && slot.skill), () => h(DOMElement, {
294
+ element: "span",
295
+ attrs: { class: "rpg-ui-hotbar-text action-battle-actionbar-text" },
296
+ textContent: slot.skill.name
297
+ })], [computed(() => slot.type === "item" && slot.item), () => h(DOMElement, {
298
+ element: "span",
299
+ attrs: { class: "rpg-ui-hotbar-text action-battle-actionbar-text" },
300
+ textContent: slot.item.name
301
+ })]),
302
+ cond(computed(() => slot.type === "item" && slot.item), () => h(DOMElement, {
303
+ element: "span",
304
+ attrs: { class: "rpg-ui-hotbar-count action-battle-actionbar-count" },
305
+ textContent: "x" + getItemQuantity(slot.item)
306
+ }))
307
+ ]))))));
76
308
  }
77
309
  var __ce_component = component;
78
310
  //#endregion
@@ -0,0 +1,16 @@
1
+ type LocomotionEntity = {
2
+ animationFixed?: boolean;
3
+ setGraphicAnimation?: (...args: any[]) => unknown;
4
+ animationName?: {
5
+ set?: (animationName: string) => unknown;
6
+ };
7
+ resetAnimationState?: () => unknown;
8
+ };
9
+ export declare const withActionBattleAnimationUnlocked: <T>(entity: LocomotionEntity | undefined, callback: () => T) => T;
10
+ /**
11
+ * Force a locomotion animation even when an action lock temporarily froze
12
+ * animation changes. This keeps server state and local rendering coherent
13
+ * after attack recovery interrupts movement.
14
+ */
15
+ export declare const forceActionBattleLocomotionAnimation: (entity: LocomotionEntity | undefined, animationName: "stand" | "walk") => void;
16
+ export {};
@@ -0,0 +1,14 @@
1
+ export type ActionBattleDashEntity = {
2
+ id?: string;
3
+ getCurrentMap?: () => any;
4
+ dash?: (direction: {
5
+ x: number;
6
+ y: number;
7
+ }, additionalSpeed?: number, duration?: number) => unknown;
8
+ };
9
+ export declare const isActionBattleMovementResolutionError: (error: unknown) => boolean;
10
+ export declare const hasActionBattlePhysicsBody: (entity: ActionBattleDashEntity | null | undefined) => boolean;
11
+ export declare const safeActionBattleDash: (entity: ActionBattleDashEntity | null | undefined, direction: {
12
+ x: number;
13
+ y: number;
14
+ }, additionalSpeed?: number, duration?: number) => boolean;
@@ -91,16 +91,20 @@ export declare function getPlayerWeaponKnockbackForce(player: RpgPlayer): number
91
91
  * ```
92
92
  */
93
93
  export declare function applyPlayerHitToEvent(player: RpgPlayer, target: RpgEvent, hooks?: ApplyHitHooks, metadata?: Record<string, any>): HitResult | undefined;
94
+ export declare function applyActionBattleEntityHit(attacker: RpgPlayer | RpgEvent, target: RpgPlayer | RpgEvent, hooks?: ApplyHitHooks, metadata?: Record<string, any>): HitResult | undefined;
94
95
  export declare const openActionBattleActionBar: (player: RpgPlayer, rawOptions?: ActionBattleOptions) => void;
95
96
  export declare const updateActionBattleActionBar: (player: RpgPlayer, rawOptions?: ActionBattleOptions) => void;
96
97
  export declare const createActionBattleServer: (rawOptions?: ActionBattleOptions) => RpgServer;
97
98
  declare const _default: RpgServer;
98
99
  export default _default;
99
- export { ACTION_BATTLE_HITBOX_FRAME_MS, ActionBattleHitTracker, createActionBattleAttackId, getNormalizedActionBattleAttackProfile, resolveActionBattleHitboxSpeed, scheduleActionBattleStartup, } from './core/attack-runtime';
100
+ export { ACTION_BATTLE_HITBOX_FRAME_MS, ActionBattleHitTracker, createActionBattleAttackId, getNormalizedActionBattleAttackProfile, resolveActionBattleHitboxSpeed, runActionBattleActiveHitbox, scheduleActionBattleStartup, } from './core/attack-runtime';
100
101
  export { DEFAULT_ACTION_BATTLE_ATTACK_PROFILE, normalizeActionBattleAttackProfile, type ActionBattleAttackProfileFallbacks, } from './core/attack-profile';
101
- export type { ActionBattleAttackDirection, ActionBattleAttackHitboxConfig, ActionBattleAttackHitboxMap, ActionBattleAttackHitPolicy, ActionBattleAttackProfile, ActionBattleDebugOptions, ActionBattleHitReactionProfile, NormalizedActionBattleHitReactionProfile, NormalizedActionBattleAttackProfile, } from './types';
102
+ export type { ActionBattleAttackDirection, ActionBattleAttackHitboxConfig, ActionBattleAttackHitboxMap, ActionBattleAttackHitPolicy, ActionBattleAttackProfile, ActionBattleHitReactionProfile, NormalizedActionBattleHitReactionProfile, NormalizedActionBattleAttackProfile, } from './types';
103
+ export type { ActionBattleActionConfig, ActionBattleActionMode, ActionBattleActionTarget, ActionBattleProjectileImpactContext, ActionBattleProjectileOptions, ActionBattleTargetContext, ActionBattleTargetOptions, ActionBattleTargetSelector, ActionBattleUsable, ActionBattleUseContext, } from './core/contracts';
104
+ export { canActionBattleUseTarget, executeActionBattleUse, getActionBattleActionConfig, getActionBattleActionRange, handleActionBattleProjectileDestroy, handleActionBattleProjectileImpact, shouldUseActionBattleUsable, } from './core/action-use';
102
105
  export { DEFAULT_ACTION_BATTLE_HIT_REACTION, isActionBattleEntityInvincible, normalizeActionBattleHitReaction, setActionBattleInvincibility, } from './core/hit-reaction';
103
106
  export { DEFAULT_ACTION_BATTLE_ENEMY_ATTACK_PROFILES, normalizeActionBattleEnemyAttackProfiles, type ActionBattleEnemyAttackProfileKey, type ActionBattleEnemyAttackProfileMap, type NormalizedActionBattleEnemyAttackProfileMap, } from './core/enemy-attack-profiles';
104
- export { resolveActionBattleWeaponAttackProfile } from './core/equipment';
107
+ export { resolveActionBattleWeapon, resolveActionBattleWeaponAttackProfile, } from './core/equipment';
108
+ export { ACTION_BATTLE_ENEMY_FACTION, ACTION_BATTLE_PLAYER_FACTION, canActionBattleTarget, getActionBattleFaction, getActionBattleTargets, isActionBattleCombatEntity, isActionBattleEvent, isActionBattlePlayer, matchesActionBattleTargetSelector, } from './core/targets';
105
109
  export { AiDebug, AiState, AttackPattern, BattleAi, DEFAULT_KNOCKBACK, EnemyType, } from './ai.server';
106
110
  export type { ApplyHitHooks, BattleAiDefeatedCallback, BattleAiDefeatedContext, BattleAiDefeatReward, BattleAiLegacyDefeatedCallback, BattleAiLegacyOptions, BattleAiOptions, BattleAiRewardItem, BattleAiRewards, HitResult, } from './ai.server';
@@ -0,0 +1,22 @@
1
+ import { ActionBattleUiActionBarOptions, ActionBattleUiAttackPreviewOptions, ActionBattleUiOptions, ActionBattleUiTargetingOptions } from './types';
2
+ export declare const ActionBattleUi: {
3
+ ActionBar: any;
4
+ TargetingOverlay: any;
5
+ AttackPreview: any;
6
+ };
7
+ export interface ResolvedActionBattleUi {
8
+ gui: Array<{
9
+ id: string;
10
+ component: any;
11
+ dependencies?: Function;
12
+ }>;
13
+ sprite: {
14
+ componentsInFront: any[];
15
+ componentsBehind: any[];
16
+ };
17
+ actionBar: ActionBattleUiActionBarOptions;
18
+ targeting: ActionBattleUiTargetingOptions;
19
+ attackPreview: ActionBattleUiAttackPreviewOptions;
20
+ }
21
+ export declare function createActionBattleUi(input?: "classic" | ActionBattleUiOptions): ActionBattleUiOptions;
22
+ export declare function resolveActionBattleUi(options?: ActionBattleUiOptions): ResolvedActionBattleUi;
@@ -0,0 +1,15 @@
1
+ import { ActionBattleVisualComposer, ActionBattleVisualContext, ActionBattleVisualInput } from './types';
2
+ export declare const ACTION_BATTLE_CLIENT_VISUAL_ID = "action-battle.visual";
3
+ export declare const ACTION_BATTLE_HIT_FX_COMPONENT_ID = "action-battle-hit-fx";
4
+ type PreviewStarter = (entity: any, options?: Record<string, any>) => void;
5
+ export declare function setActionBattlePreviewStarter(starter?: PreviewStarter): void;
6
+ export declare function emitActionBattleClientVisual(context: ActionBattleVisualContext): void;
7
+ export declare function createActionBattleClientVisuals(options?: import('./types').ActionBattleOptions): {
8
+ "action-battle.visual": (context: any) => void;
9
+ };
10
+ export declare function createActionBattleVisual(input?: ActionBattleVisualInput): ActionBattleVisualComposer;
11
+ export declare const createClassicActionBattleVisual: () => ActionBattleVisualComposer;
12
+ export declare const createFxActionBattleVisual: () => ActionBattleVisualComposer;
13
+ export declare function playActionBattleVisual(visual: ActionBattleVisualInput | ActionBattleVisualComposer | undefined, context: ActionBattleVisualContext): void;
14
+ export declare function usesActionBattleFxVisual(visual: ActionBattleVisualInput | undefined): boolean;
15
+ export {};