@rpgjs/action-battle 5.0.0-beta.1 → 5.0.0-beta.10

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 (103) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +19 -0
  3. package/README.md +392 -22
  4. package/dist/{ai.server.d.ts → client/ai.server.d.ts} +90 -28
  5. package/dist/client/animations.d.ts +16 -0
  6. package/dist/{client.d.ts → client/client.d.ts} +3 -2
  7. package/dist/{config.d.ts → client/config.d.ts} +2 -0
  8. package/dist/client/core/attack-profile.d.ts +9 -0
  9. package/dist/client/core/attack-runtime.d.ts +20 -0
  10. package/dist/client/core/context.d.ts +5 -0
  11. package/dist/client/core/defaults.d.ts +81 -0
  12. package/dist/client/core/enemy-attack-profiles.d.ts +6 -0
  13. package/dist/client/core/equipment.d.ts +2 -0
  14. package/dist/client/core/hit-reaction.d.ts +5 -0
  15. package/dist/client/core/hit.d.ts +2 -0
  16. package/dist/client/enemies/factory.d.ts +7 -0
  17. package/dist/client/index.d.ts +21 -0
  18. package/dist/client/index.js +24 -31
  19. package/dist/client/index10.js +61 -0
  20. package/dist/client/index11.js +55 -0
  21. package/dist/client/index12.js +106 -0
  22. package/dist/client/index13.js +143 -0
  23. package/dist/client/index14.js +25 -0
  24. package/dist/client/index15.js +72 -0
  25. package/dist/client/index16.js +1343 -0
  26. package/dist/client/index17.js +13 -0
  27. package/dist/client/index18.js +60 -0
  28. package/dist/client/index19.js +10 -0
  29. package/dist/client/index2.js +30 -45
  30. package/dist/client/index20.js +504 -0
  31. package/dist/client/index3.js +45 -1288
  32. package/dist/client/index4.js +105 -330
  33. package/dist/client/index5.js +84 -291
  34. package/dist/client/index6.js +309 -95
  35. package/dist/client/index7.js +35 -59
  36. package/dist/client/index8.js +101 -54
  37. package/dist/client/index9.js +79 -30
  38. package/dist/{server.d.ts → client/server.d.ts} +12 -4
  39. package/dist/client/ui/state.d.ts +35 -0
  40. package/dist/server/ai.server.d.ts +569 -0
  41. package/dist/server/animations.d.ts +16 -0
  42. package/dist/server/config.d.ts +5 -0
  43. package/dist/server/core/attack-profile.d.ts +9 -0
  44. package/dist/server/core/attack-runtime.d.ts +20 -0
  45. package/dist/server/core/context.d.ts +5 -0
  46. package/dist/server/core/defaults.d.ts +81 -0
  47. package/dist/server/core/enemy-attack-profiles.d.ts +6 -0
  48. package/dist/server/core/equipment.d.ts +2 -0
  49. package/dist/server/core/hit-reaction.d.ts +5 -0
  50. package/dist/server/core/hit.d.ts +2 -0
  51. package/dist/server/enemies/factory.d.ts +7 -0
  52. package/dist/server/index.d.ts +21 -0
  53. package/dist/server/index.js +23 -31
  54. package/dist/server/index10.js +1342 -0
  55. package/dist/server/index11.js +37 -0
  56. package/dist/server/index12.js +60 -0
  57. package/dist/server/index13.js +13 -0
  58. package/dist/server/index14.js +503 -0
  59. package/dist/server/index15.js +10 -0
  60. package/dist/server/index2.js +59 -332
  61. package/dist/server/index3.js +29 -1286
  62. package/dist/server/index4.js +45 -53
  63. package/dist/server/index5.js +107 -29
  64. package/dist/server/index6.js +143 -0
  65. package/dist/server/index7.js +25 -0
  66. package/dist/server/index8.js +72 -0
  67. package/dist/server/index9.js +55 -0
  68. package/dist/server/server.d.ts +106 -0
  69. package/dist/server/targeting.d.ts +19 -0
  70. package/package.json +12 -12
  71. package/src/ai.server.spec.ts +120 -0
  72. package/src/ai.server.ts +515 -91
  73. package/src/animations.ts +149 -0
  74. package/src/canvas-engine-shim.ts +4 -0
  75. package/src/client.ts +130 -2
  76. package/src/components/action-bar.ce +5 -3
  77. package/src/components/attack-preview.ce +90 -0
  78. package/src/config.ts +61 -0
  79. package/src/core/attack-profile.spec.ts +118 -0
  80. package/src/core/attack-profile.ts +100 -0
  81. package/src/core/attack-runtime.spec.ts +103 -0
  82. package/src/core/attack-runtime.ts +83 -0
  83. package/src/core/context.ts +35 -0
  84. package/src/core/contracts.ts +126 -0
  85. package/src/core/defaults.ts +162 -0
  86. package/src/core/enemy-attack-profiles.spec.ts +35 -0
  87. package/src/core/enemy-attack-profiles.ts +103 -0
  88. package/src/core/equipment.spec.ts +37 -0
  89. package/src/core/equipment.ts +17 -0
  90. package/src/core/hit-reaction.spec.ts +43 -0
  91. package/src/core/hit-reaction.ts +70 -0
  92. package/src/core/hit.spec.ts +111 -0
  93. package/src/core/hit.ts +92 -0
  94. package/src/enemies/factory.ts +25 -0
  95. package/src/index.ts +94 -1
  96. package/src/server.ts +427 -93
  97. package/src/targeting.spec.ts +24 -0
  98. package/src/types/canvas-engine.d.ts +4 -0
  99. package/src/types.ts +148 -0
  100. package/src/ui/state.ts +57 -0
  101. package/dist/index.d.ts +0 -11
  102. package/dist/ui/state.d.ts +0 -18
  103. /package/dist/{targeting.d.ts → client/targeting.d.ts} +0 -0
@@ -1,292 +1,85 @@
1
- import { useProps, useDefineProps, signal, computed, effect, h, DOMContainer, DOMElement, loop, cond, DOMSprite } from "canvasengine";
2
- import { inject, RpgClientEngine } from "@rpgjs/client";
3
- import { actionBattleUiOptions, actionBattleTargetingState, stopTargeting, moveTargetingOffset, startTargeting } from "./index7.js";
4
- if (typeof document !== "undefined" && !document.getElementById("ce-style--home-runner-work-RPG-JS-RPG-JS-packages-action-battle-src-components-action-bar-ce")) {
5
- const styleElement = document.createElement("style");
6
- styleElement.id = "ce-style--home-runner-work-RPG-JS-RPG-JS-packages-action-battle-src-components-action-bar-ce";
7
- 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 }";
8
- document.head.appendChild(styleElement);
9
- }
10
- function component($$props) {
11
- useProps($$props);
12
- const defineProps = useDefineProps($$props);
13
- var __assign = this && this.__assign || function() {
14
- __assign = Object.assign || function(t) {
15
- for (var s, i = 1, n = arguments.length; i < n; i++) {
16
- s = arguments[i];
17
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
18
- t[p] = s[p];
19
- }
20
- return t;
21
- };
22
- return __assign.apply(this, arguments);
23
- };
24
- var engine = inject(RpgClientEngine);
25
- var keyboardControls = engine.globalConfig.keyboardControls;
26
- var _a = defineProps();
27
- _a.data;
28
- var onInteraction = _a.onInteraction, onBack = _a.onBack;
29
- var currentPlayer = engine.getCurrentPlayer();
30
- var ACTION_BAR_SIZE = 10;
31
- var SLOT_LABELS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
32
- var SLOT_CONFIG_KEYS = [
33
- "hotbar1",
34
- "hotbar2",
35
- "hotbar3",
36
- "hotbar4",
37
- "hotbar5",
38
- "hotbar6",
39
- "hotbar7",
40
- "hotbar8",
41
- "hotbar9",
42
- "hotbar0"
43
- ];
44
- var selectedSlotIndex = signal(-1);
45
- var uiOptions = computed(function() {
46
- return actionBattleUiOptions();
47
- });
48
- var showItems = computed(function() {
49
- var _a2;
50
- var mode = ((_a2 = uiOptions().actionBar) === null || _a2 === void 0 ? void 0 : _a2.mode) || "both";
51
- return mode === "items" || mode === "both";
52
- });
53
- var showSkills = computed(function() {
54
- var _a2;
55
- var mode = ((_a2 = uiOptions().actionBar) === null || _a2 === void 0 ? void 0 : _a2.mode) || "both";
56
- return mode === "skills" || mode === "both";
57
- });
58
- var isTargeting = computed(function() {
59
- return actionBattleTargetingState().active;
60
- });
61
- var iconSheet = function(iconId) {
62
- return {
63
- definition: engine.getSpriteSheet(iconId),
64
- playing: "default"
65
- };
66
- };
67
- var actionBarSlots = computed(function() {
68
- var entries = [];
69
- if (showSkills()) {
70
- currentPlayer.skills().forEach(function(skill, index) {
71
- entries.push({
72
- type: "skill",
73
- skill,
74
- item: null,
75
- sourceIndex: index
76
- });
77
- });
78
- }
79
- if (showItems()) {
80
- currentPlayer.items().forEach(function(item, index) {
81
- entries.push({
82
- type: "item",
83
- skill: null,
84
- item,
85
- sourceIndex: index
86
- });
87
- });
88
- }
89
- var slots = entries.slice(0, ACTION_BAR_SIZE).map(function(entry, index) {
90
- return __assign(__assign({}, entry), { label: SLOT_LABELS[index] });
91
- });
92
- while (slots.length < ACTION_BAR_SIZE) {
93
- slots.push({
94
- type: "empty",
95
- skill: null,
96
- item: null,
97
- sourceIndex: -1,
98
- label: SLOT_LABELS[slots.length]
99
- });
100
- }
101
- return slots;
102
- });
103
- var hasSlotEntry = function(slot) {
104
- return slot.type === "skill" || slot.type === "item";
105
- };
106
- var isSlotDisabled = function(slot) {
107
- if (!hasSlotEntry(slot))
108
- return true;
109
- var entry = slot.type === "skill" ? slot.skill : slot.item;
110
- return !entry || !entry.usable;
111
- };
112
- var getItemQuantity = function(item) {
113
- if (!item)
114
- return 0;
115
- if (typeof item.quantity === "function")
116
- return item.quantity();
117
- return item.quantity || 0;
118
- };
119
- var selectItem = function(item) {
120
- if (!item || !item.usable)
121
- return;
122
- if (onInteraction)
123
- onInteraction("useItem", { id: item.id });
124
- };
125
- var selectSkill = function(skill) {
126
- var _a2;
127
- if (!skill || !skill.usable)
128
- return;
129
- var range = (_a2 = skill.range) !== null && _a2 !== void 0 ? _a2 : 0;
130
- if (range > 0 || skill.aoeMask) {
131
- startTargeting(skill);
132
- return;
133
- }
134
- if (onInteraction)
135
- onInteraction("useSkill", { id: skill.id });
136
- };
137
- var selectSlot = function(index) {
138
- var slot = actionBarSlots()[index];
139
- if (!slot || !hasSlotEntry(slot))
140
- return;
141
- if (slot.type === "skill") {
142
- selectSkill(slot.skill);
143
- return;
144
- }
145
- selectItem(slot.item);
146
- };
147
- var onSelectSlot = function(index) {
148
- return function() {
149
- selectedSlotIndex.set(index);
150
- selectSlot(index);
151
- };
152
- };
153
- var getPlayerTile = function() {
154
- var _a2;
155
- var player = engine.scene.getCurrentPlayer();
156
- if (!player)
157
- return null;
158
- var hitbox = ((_a2 = player.hitbox) === null || _a2 === void 0 ? void 0 : _a2.call(player)) || { w: 32, h: 32 };
159
- var tileWidth = hitbox.w || 32;
160
- var tileHeight = hitbox.h || 32;
161
- var x = Math.floor((player.x() + hitbox.w / 2) / tileWidth);
162
- var y = Math.floor((player.y() + hitbox.h / 2) / tileHeight);
163
- return { x, y };
164
- };
165
- var confirmTargeting = function() {
166
- var state = actionBattleTargetingState();
167
- if (!state.skill)
168
- return;
169
- var origin = getPlayerTile();
170
- if (!origin)
171
- return;
172
- var target = {
173
- x: origin.x + state.offset.x,
174
- y: origin.y + state.offset.y
175
- };
176
- if (onInteraction) {
177
- onInteraction("useSkill", {
178
- id: state.skill.id,
179
- target
180
- });
181
- }
182
- stopTargeting();
183
- };
184
- var resolveKeyBind = function(key) {
185
- if (!key)
186
- return null;
187
- if (typeof key === "string" && (keyboardControls === null || keyboardControls === void 0 ? void 0 : keyboardControls[key])) {
188
- return keyboardControls[key];
189
- }
190
- return key;
191
- };
192
- var slotBind = function(index) {
193
- return (keyboardControls === null || keyboardControls === void 0 ? void 0 : keyboardControls[SLOT_CONFIG_KEYS[index]]) || SLOT_LABELS[index];
194
- };
195
- var buildControls = function() {
196
- var hotbarControls = {};
197
- actionBarSlots().forEach(function(slot, index) {
198
- var _a2;
199
- if (!hasSlotEntry(slot))
200
- return;
201
- var bind = slotBind(index);
202
- hotbarControls["slot-".concat(index)] = {
203
- bind,
204
- keyDown: function() {
205
- if (isTargeting())
206
- return;
207
- selectedSlotIndex.set(index);
208
- selectSlot(index);
209
- }
210
- };
211
- if (slot.type === "skill") {
212
- var skillBind = resolveKeyBind((_a2 = slot.skill) === null || _a2 === void 0 ? void 0 : _a2.key);
213
- if (!skillBind || skillBind === bind)
214
- return;
215
- hotbarControls["skill-".concat(index)] = {
216
- bind: skillBind,
217
- keyDown: function() {
218
- if (isTargeting())
219
- return;
220
- selectedSlotIndex.set(index);
221
- selectSlot(index);
222
- }
223
- };
224
- }
225
- });
226
- return __assign(__assign({ left: {
227
- repeat: true,
228
- bind: keyboardControls.left,
229
- throttle: 150,
230
- keyDown: function() {
231
- if (isTargeting()) {
232
- moveTargetingOffset(-1, 0);
233
- }
234
- }
235
- }, right: {
236
- repeat: true,
237
- bind: keyboardControls.right,
238
- throttle: 150,
239
- keyDown: function() {
240
- if (isTargeting()) {
241
- moveTargetingOffset(1, 0);
242
- }
243
- }
244
- }, up: {
245
- repeat: true,
246
- bind: keyboardControls.up,
247
- throttle: 150,
248
- keyDown: function() {
249
- if (isTargeting()) {
250
- moveTargetingOffset(0, -1);
251
- }
252
- }
253
- }, down: {
254
- repeat: true,
255
- bind: keyboardControls.down,
256
- throttle: 150,
257
- keyDown: function() {
258
- if (isTargeting()) {
259
- moveTargetingOffset(0, 1);
260
- }
261
- }
262
- }, action: {
263
- bind: keyboardControls.action,
264
- keyDown: function() {
265
- if (isTargeting()) {
266
- confirmTargeting();
267
- }
268
- }
269
- }, escape: {
270
- bind: keyboardControls.escape,
271
- keyDown: function() {
272
- if (isTargeting()) {
273
- stopTargeting();
274
- return;
275
- }
276
- if (onBack)
277
- onBack();
278
- }
279
- } }, hotbarControls), { gamepad: {
280
- enabled: true
281
- } });
282
- };
283
- var controls = signal(buildControls());
284
- effect(function() {
285
- controls.set(buildControls());
286
- });
287
- let $this = h(DOMContainer, { width: "100%", height: "100%", attrs: { class: "action-battle-actionbar-root" }, controls }, h(DOMElement, { element: "div", attrs: { class: "action-battle-actionbar" } }, h(DOMElement, { element: "div", attrs: { class: "rpg-ui-hotbar action-battle-actionbar-plate" } }, h(DOMElement, { element: "div", attrs: { class: "rpg-ui-hotbar-track action-battle-actionbar-track" } }, loop(actionBarSlots, (slot, index) => h(DOMElement, { element: "div", attrs: { class: "rpg-ui-hotbar-slot action-battle-actionbar-slot", "data-selected": computed(() => selectedSlotIndex() === index ? "true" : "false"), "data-disabled": computed(() => isSlotDisabled(slot) ? "true" : "false"), "data-empty": computed(() => hasSlotEntry(slot) ? "false" : "true"), "data-type": slot.type, tabindex: computed(() => hasSlotEntry(slot) ? index : -1), click: hasSlotEntry(slot) ? onSelectSlot(index) : void 0 } }, [h(DOMElement, { element: "span", attrs: { class: "rpg-ui-hotbar-key action-battle-actionbar-key" }, textContent: slot.label }), cond(computed(() => slot.type === "skill" && slot.skill?.icon), () => h(DOMSprite, { sheet: computed(() => iconSheet(slot.skill.icon)), width: "60px", height: "60px", scale: 2, objectFit: "contain" }), [computed(() => slot.type === "item" && slot.item?.icon), () => h(DOMSprite, { sheet: computed(() => iconSheet(slot.item.icon)), width: "60px", height: "60px", scale: 2, objectFit: "contain" })], [computed(() => slot.type === "skill" && slot.skill), () => h(DOMElement, { element: "span", attrs: { class: "rpg-ui-hotbar-text action-battle-actionbar-text" }, textContent: slot.skill.name })], [computed(() => slot.type === "item" && slot.item), () => h(DOMElement, { element: "span", attrs: { class: "rpg-ui-hotbar-text action-battle-actionbar-text" }, textContent: slot.item.name })]), cond(computed(() => slot.type === "item" && slot.item), () => h(DOMElement, { element: "span", attrs: { class: "rpg-ui-hotbar-count action-battle-actionbar-count" }, textContent: "x" + getItemQuantity(slot.item) }))]))))));
288
- return $this;
289
- }
290
- export {
291
- component as default
1
+ import { DEFAULT_ACTION_BATTLE_OPTIONS, normalizeActionBattleOptions } from "./index4.js";
2
+ import { signal } from "canvasengine";
3
+ //#region src/ui/state.ts
4
+ var defaultTargetingState = {
5
+ active: false,
6
+ skill: null,
7
+ range: 0,
8
+ offset: {
9
+ x: 0,
10
+ y: 0
11
+ },
12
+ aoeMask: DEFAULT_ACTION_BATTLE_OPTIONS.skills?.defaultAoeMask || ["#"]
292
13
  };
14
+ var defaultAttackPreviewState = {
15
+ active: false,
16
+ id: 0,
17
+ direction: "down",
18
+ startedAt: 0,
19
+ durationMs: 180,
20
+ color: 16774064,
21
+ accentColor: 16777215
22
+ };
23
+ var actionBattleUiOptions = signal(normalizeActionBattleOptions({}).ui || {});
24
+ var actionBattleSkillOptions = signal(normalizeActionBattleOptions({}).skills || {});
25
+ var actionBattleTargetingState = signal({ ...defaultTargetingState });
26
+ var actionBattleAttackPreviewState = signal({ ...defaultAttackPreviewState });
27
+ var setActionBattleOptions = (options = {}) => {
28
+ const normalized = normalizeActionBattleOptions(options);
29
+ actionBattleUiOptions.set(normalized.ui || {});
30
+ actionBattleSkillOptions.set(normalized.skills || {});
31
+ };
32
+ var startTargeting = (skill) => {
33
+ const skillsOptions = actionBattleSkillOptions();
34
+ const mask = skill.aoeMask || skillsOptions.defaultAoeMask || ["#"];
35
+ actionBattleTargetingState.set({
36
+ active: true,
37
+ skill,
38
+ range: skill.range ?? 0,
39
+ offset: {
40
+ x: 0,
41
+ y: 0
42
+ },
43
+ aoeMask: mask
44
+ });
45
+ };
46
+ var stopTargeting = () => {
47
+ actionBattleTargetingState.set({ ...defaultTargetingState });
48
+ };
49
+ var moveTargetingOffset = (dx, dy) => {
50
+ const state = actionBattleTargetingState();
51
+ if (!state.active) return;
52
+ const next = {
53
+ x: state.offset.x + dx,
54
+ y: state.offset.y + dy
55
+ };
56
+ if (Math.abs(next.x) + Math.abs(next.y) > state.range) return;
57
+ actionBattleTargetingState.set({
58
+ ...state,
59
+ offset: next
60
+ });
61
+ };
62
+ var startAttackPreview = (options) => {
63
+ const id = actionBattleAttackPreviewState().id + 1;
64
+ const durationMs = Math.max(1, options.durationMs ?? defaultAttackPreviewState.durationMs);
65
+ actionBattleAttackPreviewState.set({
66
+ active: true,
67
+ id,
68
+ direction: options.direction,
69
+ startedAt: Date.now(),
70
+ durationMs,
71
+ color: options.color ?? defaultAttackPreviewState.color,
72
+ accentColor: options.accentColor ?? defaultAttackPreviewState.accentColor
73
+ });
74
+ return id;
75
+ };
76
+ var stopAttackPreview = (id) => {
77
+ const current = actionBattleAttackPreviewState();
78
+ if (id !== void 0 && current.id !== id) return;
79
+ actionBattleAttackPreviewState.set({
80
+ ...current,
81
+ active: false
82
+ });
83
+ };
84
+ //#endregion
85
+ export { actionBattleAttackPreviewState, actionBattleTargetingState, actionBattleUiOptions, moveTargetingOffset, setActionBattleOptions, startAttackPreview, startTargeting, stopAttackPreview, stopTargeting };