@rpgjs/action-battle 5.0.0-alpha.33 → 5.0.0-alpha.36
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.
- package/README.md +112 -24
- package/dist/ai.server.d.ts +1 -1
- package/dist/client/index.js +16 -6
- package/dist/client/index2.js +42 -8
- package/dist/client/index3.js +3 -3
- package/dist/client/index4.js +267 -71
- package/dist/client/index5.js +292 -0
- package/dist/client/index6.js +97 -0
- package/dist/client/index7.js +61 -0
- package/dist/client/index8.js +55 -0
- package/dist/client/index9.js +30 -0
- package/dist/client.d.ts +2 -0
- package/dist/config.d.ts +3 -0
- package/dist/index.d.ts +9 -2
- package/dist/server/index.js +16 -6
- package/dist/server/index2.js +267 -71
- package/dist/server/index3.js +3 -3
- package/dist/server/index4.js +55 -0
- package/dist/server/index5.js +30 -0
- package/dist/server.d.ts +5 -0
- package/dist/targeting.d.ts +19 -0
- package/dist/ui/state.d.ts +18 -0
- package/package.json +7 -7
- package/src/ai.server.ts +5 -5
- package/src/client.ts +49 -8
- package/src/components/action-bar.ce +329 -0
- package/src/components/targeting-overlay.ce +99 -0
- package/src/config.ts +56 -0
- package/src/index.ts +32 -7
- package/src/server.ts +356 -87
- package/src/targeting.ts +45 -0
- package/src/types.ts +78 -0
- package/src/ui/state.ts +68 -0
|
@@ -0,0 +1,292 @@
|
|
|
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
|
|
292
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useProps, useDefineProps, computed, h, Container, cond, Graphics } from "canvasengine";
|
|
2
|
+
import { inject, RpgClientEngine } from "@rpgjs/client";
|
|
3
|
+
import { actionBattleUiOptions, actionBattleTargetingState } from "./index7.js";
|
|
4
|
+
import { parseAoeMask } from "./index9.js";
|
|
5
|
+
function component($$props) {
|
|
6
|
+
useProps($$props);
|
|
7
|
+
const defineProps = useDefineProps($$props);
|
|
8
|
+
var object = defineProps().object;
|
|
9
|
+
var engine = inject(RpgClientEngine);
|
|
10
|
+
var isCurrentPlayer = computed(function() {
|
|
11
|
+
if (!(object === null || object === void 0 ? void 0 : object.id))
|
|
12
|
+
return false;
|
|
13
|
+
var idValue = typeof object.id === "function" ? object.id() : object.id;
|
|
14
|
+
return idValue === engine.playerId;
|
|
15
|
+
});
|
|
16
|
+
var uiOptions = computed(function() {
|
|
17
|
+
return actionBattleUiOptions();
|
|
18
|
+
});
|
|
19
|
+
var targetingState = computed(function() {
|
|
20
|
+
return actionBattleTargetingState();
|
|
21
|
+
});
|
|
22
|
+
var shouldRender = computed(function() {
|
|
23
|
+
var _a;
|
|
24
|
+
if (!isCurrentPlayer())
|
|
25
|
+
return false;
|
|
26
|
+
if (!((_a = uiOptions().targeting) === null || _a === void 0 ? void 0 : _a.enabled))
|
|
27
|
+
return false;
|
|
28
|
+
return targetingState().active;
|
|
29
|
+
});
|
|
30
|
+
var getTileSize = function() {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
var uiTile = (_a = uiOptions().targeting) === null || _a === void 0 ? void 0 : _a.tileSize;
|
|
33
|
+
if ((uiTile === null || uiTile === void 0 ? void 0 : uiTile.width) && (uiTile === null || uiTile === void 0 ? void 0 : uiTile.height))
|
|
34
|
+
return uiTile;
|
|
35
|
+
var hitbox = ((_b = object.hitbox) === null || _b === void 0 ? void 0 : _b.call(object)) || { w: 32, h: 32 };
|
|
36
|
+
return { width: hitbox.w || 32, height: hitbox.h || 32 };
|
|
37
|
+
};
|
|
38
|
+
var getOriginTile = function() {
|
|
39
|
+
var _a;
|
|
40
|
+
var hitbox = ((_a = object.hitbox) === null || _a === void 0 ? void 0 : _a.call(object)) || { w: 32, h: 32 };
|
|
41
|
+
var tileSize = getTileSize();
|
|
42
|
+
var x = Math.floor((object.x() + hitbox.w / 2) / tileSize.width);
|
|
43
|
+
var y = Math.floor((object.y() + hitbox.h / 2) / tileSize.height);
|
|
44
|
+
return { x, y };
|
|
45
|
+
};
|
|
46
|
+
var toColor = function(value, fallback) {
|
|
47
|
+
if (typeof value === "number")
|
|
48
|
+
return value;
|
|
49
|
+
return fallback;
|
|
50
|
+
};
|
|
51
|
+
var drawGrid = function(g) {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
var state = targetingState();
|
|
54
|
+
if (!state.active)
|
|
55
|
+
return;
|
|
56
|
+
var tileSize = getTileSize();
|
|
57
|
+
var origin = getOriginTile();
|
|
58
|
+
var target = {
|
|
59
|
+
x: origin.x + state.offset.x,
|
|
60
|
+
y: origin.y + state.offset.y
|
|
61
|
+
};
|
|
62
|
+
var mask = parseAoeMask(state.aoeMask);
|
|
63
|
+
var colors = ((_a = uiOptions().targeting) === null || _a === void 0 ? void 0 : _a.colors) || {};
|
|
64
|
+
var areaColor = toColor(colors.area, 3120887);
|
|
65
|
+
var edgeColor = toColor(colors.edge, 1796760);
|
|
66
|
+
var cursorColor = toColor(colors.cursor, 16765286);
|
|
67
|
+
var showGrid = ((_b = uiOptions().targeting) === null || _b === void 0 ? void 0 : _b.showGrid) !== false;
|
|
68
|
+
var playerX = object.x();
|
|
69
|
+
var playerY = object.y();
|
|
70
|
+
g.clear();
|
|
71
|
+
mask.cells.forEach(function(cell) {
|
|
72
|
+
var tileX = target.x + cell.dx;
|
|
73
|
+
var tileY = target.y + cell.dy;
|
|
74
|
+
var worldX = tileX * tileSize.width;
|
|
75
|
+
var worldY = tileY * tileSize.height;
|
|
76
|
+
var relX = worldX - playerX;
|
|
77
|
+
var relY = worldY - playerY;
|
|
78
|
+
g.rect(relX, relY, tileSize.width, tileSize.height);
|
|
79
|
+
g.fill({ color: areaColor, alpha: 0.35 });
|
|
80
|
+
if (showGrid) {
|
|
81
|
+
g.rect(relX, relY, tileSize.width, tileSize.height);
|
|
82
|
+
g.stroke({ color: edgeColor, alpha: 0.9, width: 1 });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
var cursorWorldX = target.x * tileSize.width;
|
|
86
|
+
var cursorWorldY = target.y * tileSize.height;
|
|
87
|
+
var cursorRelX = cursorWorldX - playerX;
|
|
88
|
+
var cursorRelY = cursorWorldY - playerY;
|
|
89
|
+
g.rect(cursorRelX, cursorRelY, tileSize.width, tileSize.height);
|
|
90
|
+
g.stroke({ color: cursorColor, alpha: 1, width: 2 });
|
|
91
|
+
};
|
|
92
|
+
let $this = h(Container, null, cond(shouldRender, () => h(Graphics, { draw: drawGrid })));
|
|
93
|
+
return $this;
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
component as default
|
|
97
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { signal } from "canvasengine";
|
|
2
|
+
import { normalizeActionBattleOptions, DEFAULT_ACTION_BATTLE_OPTIONS } from "./index8.js";
|
|
3
|
+
const defaultTargetingState = {
|
|
4
|
+
active: false,
|
|
5
|
+
skill: null,
|
|
6
|
+
range: 0,
|
|
7
|
+
offset: { x: 0, y: 0 },
|
|
8
|
+
aoeMask: DEFAULT_ACTION_BATTLE_OPTIONS.skills?.defaultAoeMask || ["#"]
|
|
9
|
+
};
|
|
10
|
+
const actionBattleUiOptions = signal(
|
|
11
|
+
normalizeActionBattleOptions({}).ui || {}
|
|
12
|
+
);
|
|
13
|
+
const actionBattleSkillOptions = signal(
|
|
14
|
+
normalizeActionBattleOptions({}).skills || {}
|
|
15
|
+
);
|
|
16
|
+
const actionBattleTargetingState = signal({
|
|
17
|
+
...defaultTargetingState
|
|
18
|
+
});
|
|
19
|
+
const setActionBattleOptions = (options = {}) => {
|
|
20
|
+
const normalized = normalizeActionBattleOptions(options);
|
|
21
|
+
actionBattleUiOptions.set(normalized.ui || {});
|
|
22
|
+
actionBattleSkillOptions.set(normalized.skills || {});
|
|
23
|
+
};
|
|
24
|
+
const startTargeting = (skill) => {
|
|
25
|
+
const skillsOptions = actionBattleSkillOptions();
|
|
26
|
+
const mask = skill.aoeMask || skillsOptions.defaultAoeMask || ["#"];
|
|
27
|
+
actionBattleTargetingState.set({
|
|
28
|
+
active: true,
|
|
29
|
+
skill,
|
|
30
|
+
range: skill.range ?? 0,
|
|
31
|
+
offset: { x: 0, y: 0 },
|
|
32
|
+
aoeMask: mask
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const stopTargeting = () => {
|
|
36
|
+
actionBattleTargetingState.set({ ...defaultTargetingState });
|
|
37
|
+
};
|
|
38
|
+
const moveTargetingOffset = (dx, dy) => {
|
|
39
|
+
const state = actionBattleTargetingState();
|
|
40
|
+
if (!state.active) return;
|
|
41
|
+
const next = {
|
|
42
|
+
x: state.offset.x + dx,
|
|
43
|
+
y: state.offset.y + dy
|
|
44
|
+
};
|
|
45
|
+
if (Math.abs(next.x) + Math.abs(next.y) > state.range) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
actionBattleTargetingState.set({
|
|
49
|
+
...state,
|
|
50
|
+
offset: next
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
export {
|
|
54
|
+
actionBattleSkillOptions,
|
|
55
|
+
actionBattleTargetingState,
|
|
56
|
+
actionBattleUiOptions,
|
|
57
|
+
moveTargetingOffset,
|
|
58
|
+
setActionBattleOptions,
|
|
59
|
+
startTargeting,
|
|
60
|
+
stopTargeting
|
|
61
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const DEFAULT_ACTION_BATTLE_OPTIONS = {
|
|
2
|
+
ui: {
|
|
3
|
+
actionBar: {
|
|
4
|
+
enabled: false,
|
|
5
|
+
autoOpen: false,
|
|
6
|
+
mode: "both"
|
|
7
|
+
},
|
|
8
|
+
targeting: {
|
|
9
|
+
enabled: true,
|
|
10
|
+
showGrid: true,
|
|
11
|
+
colors: {
|
|
12
|
+
area: 3120887,
|
|
13
|
+
edge: 1796760,
|
|
14
|
+
cursor: 16765286
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
skills: {
|
|
19
|
+
defaultAoeMask: ["#"]
|
|
20
|
+
},
|
|
21
|
+
targeting: {
|
|
22
|
+
affects: "events",
|
|
23
|
+
allowEmptyTarget: true
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
function normalizeActionBattleOptions(options = {}) {
|
|
27
|
+
return {
|
|
28
|
+
ui: {
|
|
29
|
+
actionBar: {
|
|
30
|
+
...DEFAULT_ACTION_BATTLE_OPTIONS.ui?.actionBar,
|
|
31
|
+
...options.ui?.actionBar
|
|
32
|
+
},
|
|
33
|
+
targeting: {
|
|
34
|
+
...DEFAULT_ACTION_BATTLE_OPTIONS.ui?.targeting,
|
|
35
|
+
...options.ui?.targeting,
|
|
36
|
+
colors: {
|
|
37
|
+
...DEFAULT_ACTION_BATTLE_OPTIONS.ui?.targeting?.colors,
|
|
38
|
+
...options.ui?.targeting?.colors
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
skills: {
|
|
43
|
+
...DEFAULT_ACTION_BATTLE_OPTIONS.skills,
|
|
44
|
+
...options.skills
|
|
45
|
+
},
|
|
46
|
+
targeting: {
|
|
47
|
+
...DEFAULT_ACTION_BATTLE_OPTIONS.targeting,
|
|
48
|
+
...options.targeting
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
DEFAULT_ACTION_BATTLE_OPTIONS,
|
|
54
|
+
normalizeActionBattleOptions
|
|
55
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const normalizeMaskRows = (mask) => {
|
|
2
|
+
if (!mask) return ["#"];
|
|
3
|
+
if (Array.isArray(mask)) return mask;
|
|
4
|
+
return mask.trim().split("\n").map((row) => row.replace(/\r/g, ""));
|
|
5
|
+
};
|
|
6
|
+
const parseAoeMask = (mask) => {
|
|
7
|
+
const rows = normalizeMaskRows(mask);
|
|
8
|
+
const height = rows.length;
|
|
9
|
+
const width = rows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
10
|
+
const centerX = Math.floor(width / 2);
|
|
11
|
+
const centerY = Math.floor(height / 2);
|
|
12
|
+
const cells = [];
|
|
13
|
+
rows.forEach((row, y) => {
|
|
14
|
+
for (let x = 0; x < row.length; x++) {
|
|
15
|
+
const char = row[x];
|
|
16
|
+
if (char && char !== "." && char !== " ") {
|
|
17
|
+
cells.push({ dx: x - centerX, dy: y - centerY });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
if (cells.length === 0) {
|
|
22
|
+
cells.push({ dx: 0, dy: 0 });
|
|
23
|
+
}
|
|
24
|
+
return { width, height, centerX, centerY, cells };
|
|
25
|
+
};
|
|
26
|
+
const manhattanDistance = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
27
|
+
export {
|
|
28
|
+
manhattanDistance,
|
|
29
|
+
parseAoeMask
|
|
30
|
+
};
|
package/dist/client.d.ts
CHANGED
package/dist/config.d.ts
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { ActionBattleOptions } from './types';
|
|
1
2
|
export { BattleAi, AiState, EnemyType, AttackPattern, AiDebug, DEFAULT_KNOCKBACK } from './ai.server';
|
|
2
3
|
export type { HitResult, ApplyHitHooks } from './ai.server';
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
4
|
+
export type { ActionBattleOptions, ActionBattleActionBarData, ActionBattleActionBarItem, ActionBattleActionBarSkill, ActionBattleSkillTargeting, ActionBattleSkillTargetingResolver, ActionBattleUiOptions, ActionBattleUiActionBarOptions, ActionBattleUiTargetingOptions, } from './types';
|
|
5
|
+
export { DEFAULT_PLAYER_ATTACK_HITBOXES, getPlayerWeaponKnockbackForce, applyPlayerHitToEvent, ACTION_BATTLE_ACTION_BAR_GUI_ID, openActionBattleActionBar, updateActionBattleActionBar, createActionBattleServer, } from './server';
|
|
6
|
+
export declare function provideActionBattle(options?: ActionBattleOptions): any;
|
|
7
|
+
declare const _default: {
|
|
8
|
+
server: any;
|
|
9
|
+
client: any;
|
|
10
|
+
};
|
|
11
|
+
export default _default;
|
package/dist/server/index.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
import server from "./index2.js";
|
|
2
|
-
import { DEFAULT_PLAYER_ATTACK_HITBOXES, applyPlayerHitToEvent, getPlayerWeaponKnockbackForce } from "./index2.js";
|
|
1
|
+
import server, { createActionBattleServer } from "./index2.js";
|
|
2
|
+
import { ACTION_BATTLE_ACTION_BAR_GUI_ID, DEFAULT_PLAYER_ATTACK_HITBOXES, applyPlayerHitToEvent, getPlayerWeaponKnockbackForce, openActionBattleActionBar, updateActionBattleActionBar } from "./index2.js";
|
|
3
3
|
import { createModule } from "@rpgjs/common";
|
|
4
4
|
import { AiDebug, AiState, AttackPattern, BattleAi, DEFAULT_KNOCKBACK, EnemyType } from "./index3.js";
|
|
5
5
|
const client = null;
|
|
6
|
-
|
|
6
|
+
const createActionBattleClient = null;
|
|
7
|
+
function provideActionBattle(options = {}) {
|
|
7
8
|
return createModule("ActionBattle", [
|
|
8
9
|
{
|
|
9
|
-
server,
|
|
10
|
-
client
|
|
10
|
+
server: createActionBattleServer?.(options),
|
|
11
|
+
client: createActionBattleClient?.(options)
|
|
11
12
|
}
|
|
12
13
|
]);
|
|
13
14
|
}
|
|
15
|
+
const index = {
|
|
16
|
+
server,
|
|
17
|
+
client
|
|
18
|
+
};
|
|
14
19
|
export {
|
|
20
|
+
ACTION_BATTLE_ACTION_BAR_GUI_ID,
|
|
15
21
|
AiDebug,
|
|
16
22
|
AiState,
|
|
17
23
|
AttackPattern,
|
|
@@ -20,6 +26,10 @@ export {
|
|
|
20
26
|
DEFAULT_PLAYER_ATTACK_HITBOXES,
|
|
21
27
|
EnemyType,
|
|
22
28
|
applyPlayerHitToEvent,
|
|
29
|
+
createActionBattleServer,
|
|
30
|
+
index as default,
|
|
23
31
|
getPlayerWeaponKnockbackForce,
|
|
24
|
-
|
|
32
|
+
openActionBattleActionBar,
|
|
33
|
+
provideActionBattle,
|
|
34
|
+
updateActionBattleActionBar
|
|
25
35
|
};
|