@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.
- package/CHANGELOG.md +22 -0
- package/dist/client/ai.server.d.ts +57 -8
- package/dist/client/attack-input.d.ts +3 -0
- package/dist/client/core/action-use.d.ts +18 -0
- package/dist/client/core/ai-behavior-tree.d.ts +99 -0
- package/dist/client/core/attack-runtime.d.ts +2 -0
- package/dist/client/core/defaults.d.ts +3 -2
- package/dist/client/core/equipment.d.ts +1 -0
- package/dist/client/core/targets.d.ts +15 -0
- package/dist/client/enemies/factory.d.ts +2 -0
- package/dist/client/index.d.ts +12 -7
- package/dist/client/index.js +16 -11
- package/dist/client/index10.js +32 -56
- package/dist/client/index11.js +99 -52
- package/dist/client/index12.js +76 -103
- package/dist/client/index13.js +72 -135
- package/dist/client/index14.js +67 -23
- package/dist/client/index15.js +197 -63
- package/dist/client/index16.js +112 -1337
- package/dist/client/index17.js +203 -7
- package/dist/client/index18.js +32 -58
- package/dist/client/index19.js +70 -8
- package/dist/client/index20.js +57 -501
- package/dist/client/index21.js +70 -0
- package/dist/client/index22.js +226 -0
- package/dist/client/index23.js +16 -0
- package/dist/client/index24.js +25 -0
- package/dist/client/index25.js +107 -0
- package/dist/client/index26.js +1949 -0
- package/dist/client/index27.js +12 -0
- package/dist/client/index28.js +589 -0
- package/dist/client/index4.js +79 -38
- package/dist/client/index6.js +65 -306
- package/dist/client/index7.js +33 -33
- package/dist/client/index8.js +24 -100
- package/dist/client/index9.js +293 -61
- package/dist/client/locomotion.d.ts +16 -0
- package/dist/client/movement.d.ts +14 -0
- package/dist/client/server.d.ts +7 -3
- package/dist/client/ui.d.ts +22 -0
- package/dist/client/visual.d.ts +15 -0
- package/dist/server/ai.server.d.ts +57 -8
- package/dist/server/attack-input.d.ts +3 -0
- package/dist/server/core/action-use.d.ts +18 -0
- package/dist/server/core/ai-behavior-tree.d.ts +99 -0
- package/dist/server/core/attack-runtime.d.ts +2 -0
- package/dist/server/core/defaults.d.ts +3 -2
- package/dist/server/core/equipment.d.ts +1 -0
- package/dist/server/core/targets.d.ts +15 -0
- package/dist/server/enemies/factory.d.ts +2 -0
- package/dist/server/index.d.ts +12 -7
- package/dist/server/index.js +14 -9
- package/dist/server/index10.js +64 -1336
- package/dist/server/index11.js +33 -33
- package/dist/server/index13.js +67 -11
- package/dist/server/index14.js +207 -484
- package/dist/server/index15.js +15 -9
- package/dist/server/index16.js +26 -0
- package/dist/server/index17.js +25 -0
- package/dist/server/index18.js +107 -0
- package/dist/server/index19.js +1949 -0
- package/dist/server/index2.js +10 -2
- package/dist/server/index20.js +37 -0
- package/dist/server/index21.js +588 -0
- package/dist/server/index22.js +78 -0
- package/dist/server/index23.js +12 -0
- package/dist/server/index5.js +79 -38
- package/dist/server/index6.js +192 -129
- package/dist/server/index7.js +208 -24
- package/dist/server/index8.js +28 -66
- package/dist/server/index9.js +68 -51
- package/dist/server/locomotion.d.ts +16 -0
- package/dist/server/movement.d.ts +14 -0
- package/dist/server/server.d.ts +7 -3
- package/dist/server/ui.d.ts +22 -0
- package/dist/server/visual.d.ts +15 -0
- package/package.json +5 -5
- package/src/ai.server.spec.ts +380 -1
- package/src/ai.server.ts +963 -137
- package/src/animations.spec.ts +40 -0
- package/src/animations.ts +31 -9
- package/src/attack-input.spec.ts +51 -0
- package/src/attack-input.ts +59 -0
- package/src/client.ts +75 -62
- package/src/config.ts +84 -37
- package/src/core/action-use.spec.ts +317 -0
- package/src/core/action-use.ts +387 -0
- package/src/core/ai-behavior-tree.spec.ts +116 -0
- package/src/core/ai-behavior-tree.ts +272 -0
- package/src/core/attack-profile.spec.ts +46 -0
- package/src/core/attack-runtime.spec.ts +35 -0
- package/src/core/attack-runtime.ts +32 -0
- package/src/core/context.ts +9 -0
- package/src/core/contracts.ts +146 -1
- package/src/core/defaults.ts +72 -1
- package/src/core/equipment.ts +9 -5
- package/src/core/hit.spec.ts +21 -0
- package/src/core/targets.spec.ts +124 -0
- package/src/core/targets.ts +150 -0
- package/src/enemies/factory.ts +8 -0
- package/src/index.ts +111 -2
- package/src/locomotion.spec.ts +51 -0
- package/src/locomotion.ts +48 -0
- package/src/movement.spec.ts +78 -0
- package/src/movement.ts +46 -0
- package/src/server.ts +242 -66
- package/src/types.ts +105 -35
- package/src/ui.ts +113 -0
- package/src/visual.spec.ts +166 -0
- package/src/visual.ts +285 -0
- package/README.md +0 -1242
package/dist/client/index8.js
CHANGED
|
@@ -1,102 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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 {
|
|
26
|
+
export { forceActionBattleLocomotionAnimation, withActionBattleAnimationUnlocked };
|
package/dist/client/index9.js
CHANGED
|
@@ -1,78 +1,310 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { RpgClientEngine, inject } from "@rpgjs/client";
|
|
3
|
-
import {
|
|
4
|
-
//#region src/components/
|
|
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
|
|
16
|
+
const defineProps = useDefineProps($$props);
|
|
8
17
|
const engine = inject(RpgClientEngine);
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
14
|
-
|
|
15
|
-
return
|
|
51
|
+
const showSkills = computed(() => {
|
|
52
|
+
const mode = uiOptions().actionBar?.mode || "both";
|
|
53
|
+
return mode === "skills" || mode === "both";
|
|
16
54
|
});
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
|
|
60
|
+
const resolveProp = (value) => typeof value === "function" ? value() : value;
|
|
61
|
+
const actionBarData = computed(() => resolveProp(data) || {
|
|
62
|
+
items: [],
|
|
63
|
+
skills: []
|
|
27
64
|
});
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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 (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
package/dist/client/server.d.ts
CHANGED
|
@@ -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,
|
|
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 {};
|