@rpgjs/action-battle 5.0.0-beta.2 → 5.0.0-beta.4
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 +137 -0
- package/dist/ai.server.d.ts +8 -1
- package/dist/client/index.js +19 -31
- package/dist/client/index10.js +142 -29
- package/dist/client/index11.js +25 -0
- package/dist/client/index12.js +1222 -0
- package/dist/client/index13.js +46 -0
- package/dist/client/index14.js +10 -0
- package/dist/client/index15.js +448 -0
- package/dist/client/index2.js +93 -46
- package/dist/client/index3.js +82 -1329
- package/dist/client/index4.js +305 -344
- package/dist/client/index5.js +36 -291
- package/dist/client/index6.js +99 -95
- package/dist/client/index7.js +78 -61
- package/dist/client/index8.js +57 -65
- package/dist/client/index9.js +97 -62
- package/dist/client.d.ts +3 -2
- package/dist/core/context.d.ts +5 -0
- package/dist/core/defaults.d.ts +81 -0
- package/dist/core/hit.d.ts +2 -0
- package/dist/enemies/factory.d.ts +7 -0
- package/dist/index.d.ts +9 -4
- package/dist/server/index.js +18 -31
- package/dist/server/index10.js +10 -0
- package/dist/server/index2.js +59 -345
- package/dist/server/index3.js +92 -1329
- package/dist/server/index4.js +141 -67
- package/dist/server/index5.js +24 -29
- package/dist/server/index6.js +1219 -62
- package/dist/server/index7.js +37 -0
- package/dist/server/index8.js +46 -0
- package/dist/server/index9.js +447 -0
- package/dist/server.d.ts +5 -3
- package/dist/ui/state.d.ts +20 -3
- package/package.json +5 -5
- package/src/ai.server.ts +91 -24
- package/src/animations.ts +43 -4
- package/src/canvas-engine-shim.ts +4 -0
- package/src/client.ts +122 -2
- package/src/components/action-bar.ce +5 -3
- package/src/components/attack-preview.ce +90 -0
- package/src/config.ts +30 -0
- package/src/core/context.ts +35 -0
- package/src/core/contracts.ts +123 -0
- package/src/core/defaults.ts +162 -0
- package/src/core/hit.spec.ts +58 -0
- package/src/core/hit.ts +66 -0
- package/src/enemies/factory.ts +25 -0
- package/src/index.ts +40 -0
- package/src/server.ts +235 -71
- package/src/targeting.spec.ts +24 -0
- package/src/types/canvas-engine.d.ts +4 -0
- package/src/types.ts +46 -1
- package/src/ui/state.ts +57 -0
package/dist/client/index5.js
CHANGED
|
@@ -1,292 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (
|
|
5
|
-
|
|
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
|
+
//#region src/targeting.ts
|
|
2
|
+
var normalizeMaskRows = (mask) => {
|
|
3
|
+
if (!mask) return ["#"];
|
|
4
|
+
if (Array.isArray(mask)) return mask;
|
|
5
|
+
return mask.trim().split("\n").map((row) => row.replace(/\r/g, ""));
|
|
292
6
|
};
|
|
7
|
+
var parseAoeMask = (mask) => {
|
|
8
|
+
const rows = normalizeMaskRows(mask);
|
|
9
|
+
const height = rows.length;
|
|
10
|
+
const width = rows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
11
|
+
const centerX = Math.floor(width / 2);
|
|
12
|
+
const centerY = Math.floor(height / 2);
|
|
13
|
+
const cells = [];
|
|
14
|
+
rows.forEach((row, y) => {
|
|
15
|
+
for (let x = 0; x < row.length; x++) {
|
|
16
|
+
const char = row[x];
|
|
17
|
+
if (char && char !== "." && char !== " ") cells.push({
|
|
18
|
+
dx: x - centerX,
|
|
19
|
+
dy: y - centerY
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
if (cells.length === 0) cells.push({
|
|
24
|
+
dx: 0,
|
|
25
|
+
dy: 0
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
width,
|
|
29
|
+
height,
|
|
30
|
+
centerX,
|
|
31
|
+
centerY,
|
|
32
|
+
cells
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
var manhattanDistance = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
36
|
+
//#endregion
|
|
37
|
+
export { manhattanDistance, parseAoeMask };
|
package/dist/client/index6.js
CHANGED
|
@@ -1,97 +1,101 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { actionBattleTargetingState, actionBattleUiOptions } from "./index3.js";
|
|
2
|
+
import { parseAoeMask } from "./index5.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
|
|
5
6
|
function component($$props) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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;
|
|
13
|
+
});
|
|
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 })));
|
|
94
99
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
};
|
|
100
|
+
//#endregion
|
|
101
|
+
export { component as default };
|
package/dist/client/index7.js
CHANGED
|
@@ -1,61 +1,78 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
);
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
import { actionBattleAttackPreviewState } from "./index3.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
|
|
5
|
+
function component($$props) {
|
|
6
|
+
useProps($$props);
|
|
7
|
+
const { object } = useDefineProps($$props)();
|
|
8
|
+
const engine = inject(RpgClientEngine);
|
|
9
|
+
const now = signal(Date.now());
|
|
10
|
+
tick(() => {
|
|
11
|
+
if (actionBattleAttackPreviewState().active) now.set(Date.now());
|
|
12
|
+
});
|
|
13
|
+
const isCurrentPlayer = computed(() => {
|
|
14
|
+
if (!object?.id) return false;
|
|
15
|
+
return (typeof object.id === "function" ? object.id() : object.id) === engine.playerId;
|
|
16
|
+
});
|
|
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));
|
|
23
|
+
});
|
|
24
|
+
const shouldRender = computed(() => {
|
|
25
|
+
const state = preview();
|
|
26
|
+
return isCurrentPlayer() && state.active && progress() < 1;
|
|
27
|
+
});
|
|
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
|
|
37
|
+
});
|
|
38
|
+
};
|
|
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);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
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);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
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);
|
|
74
|
+
};
|
|
75
|
+
return h(Container, null, cond(shouldRender, () => h(Graphics, { draw: drawSlash })));
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { component as default };
|