@rpgjs/client 5.0.0-beta.10 → 5.0.0-beta.12
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 +21 -0
- package/dist/Game/AnimationManager.d.ts +1 -0
- package/dist/Game/AnimationManager.js +3 -0
- package/dist/Game/AnimationManager.js.map +1 -1
- package/dist/Game/ClientVisuals.d.ts +61 -0
- package/dist/Game/ClientVisuals.js +96 -0
- package/dist/Game/ClientVisuals.js.map +1 -0
- package/dist/Game/ClientVisuals.spec.d.ts +1 -0
- package/dist/Game/EventComponentResolver.d.ts +16 -0
- package/dist/Game/EventComponentResolver.js +52 -0
- package/dist/Game/EventComponentResolver.js.map +1 -0
- package/dist/Game/EventComponentResolver.spec.d.ts +1 -0
- package/dist/Game/Map.js +9 -0
- package/dist/Game/Map.js.map +1 -1
- package/dist/Game/Object.js +2 -2
- package/dist/Game/Object.js.map +1 -1
- package/dist/Game/Object.spec.d.ts +1 -0
- package/dist/Game/ProjectileManager.d.ts +98 -0
- package/dist/Game/ProjectileManager.js +196 -0
- package/dist/Game/ProjectileManager.js.map +1 -0
- package/dist/Game/ProjectileManager.spec.d.ts +1 -0
- package/dist/RpgClient.d.ts +117 -13
- package/dist/RpgClientEngine.d.ts +82 -4
- package/dist/RpgClientEngine.js +296 -51
- package/dist/RpgClientEngine.js.map +1 -1
- package/dist/components/animations/fx.ce.js +58 -0
- package/dist/components/animations/fx.ce.js.map +1 -0
- package/dist/components/animations/hit.ce.js.map +1 -1
- package/dist/components/animations/index.d.ts +1 -0
- package/dist/components/animations/index.js +3 -1
- package/dist/components/animations/index.js.map +1 -1
- package/dist/components/character.ce.js +140 -40
- package/dist/components/character.ce.js.map +1 -1
- package/dist/components/dynamics/bar.ce.js +4 -3
- package/dist/components/dynamics/bar.ce.js.map +1 -1
- package/dist/components/dynamics/image.ce.js +2 -1
- package/dist/components/dynamics/image.ce.js.map +1 -1
- package/dist/components/dynamics/shape.ce.js +3 -2
- package/dist/components/dynamics/shape.ce.js.map +1 -1
- package/dist/components/dynamics/text.ce.js +9 -8
- package/dist/components/dynamics/text.ce.js.map +1 -1
- package/dist/components/gui/dialogbox/index.ce.js +3 -2
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/gameover.ce.js +3 -2
- package/dist/components/gui/gameover.ce.js.map +1 -1
- package/dist/components/gui/hud/hud.ce.js.map +1 -1
- package/dist/components/gui/menu/equip-menu.ce.js +2 -1
- package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/exit-menu.ce.js +2 -1
- package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/items-menu.ce.js +3 -2
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/main-menu.ce.js +3 -2
- package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
- package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
- package/dist/components/gui/notification/notification.ce.js.map +1 -1
- package/dist/components/gui/save-load.ce.js +2 -1
- package/dist/components/gui/save-load.ce.js.map +1 -1
- package/dist/components/gui/shop/shop.ce.js +3 -2
- package/dist/components/gui/shop/shop.ce.js.map +1 -1
- package/dist/components/gui/title-screen.ce.js +3 -2
- package/dist/components/gui/title-screen.ce.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +1 -0
- package/dist/components/player-components.ce.js +11 -10
- package/dist/components/player-components.ce.js.map +1 -1
- package/dist/components/prebuilt/hp-bar.ce.js +4 -3
- package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
- package/dist/components/prebuilt/light-halo.ce.js +2 -1
- package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
- package/dist/components/scenes/canvas.ce.js +12 -4
- package/dist/components/scenes/canvas.ce.js.map +1 -1
- package/dist/components/scenes/draw-map.ce.js +6 -3
- package/dist/components/scenes/draw-map.ce.js.map +1 -1
- package/dist/components/scenes/event-layer.ce.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10 -5
- package/dist/module.js +18 -0
- package/dist/module.js.map +1 -1
- package/dist/services/actionInput.d.ts +14 -0
- package/dist/services/actionInput.js +59 -0
- package/dist/services/actionInput.js.map +1 -0
- package/dist/services/actionInput.spec.d.ts +1 -0
- package/dist/services/mmorpg-connection.d.ts +5 -0
- package/dist/services/mmorpg-connection.js +50 -0
- package/dist/services/mmorpg-connection.js.map +1 -0
- package/dist/services/mmorpg-connection.spec.d.ts +1 -0
- package/dist/services/mmorpg.d.ts +10 -4
- package/dist/services/mmorpg.js +48 -30
- package/dist/services/mmorpg.js.map +1 -1
- package/dist/services/pointerContext.d.ts +11 -0
- package/dist/services/pointerContext.js +48 -0
- package/dist/services/pointerContext.js.map +1 -0
- package/dist/services/pointerContext.spec.d.ts +1 -0
- package/dist/services/standalone-message.d.ts +1 -0
- package/dist/services/standalone-message.js +9 -0
- package/dist/services/standalone-message.js.map +1 -0
- package/dist/services/standalone.d.ts +3 -1
- package/dist/services/standalone.js +34 -15
- package/dist/services/standalone.js.map +1 -1
- package/dist/services/standalone.spec.d.ts +1 -0
- package/dist/utils/mapId.d.ts +1 -0
- package/dist/utils/mapId.js +6 -0
- package/dist/utils/mapId.js.map +1 -0
- package/package.json +7 -7
- package/src/Game/AnimationManager.ts +4 -0
- package/src/Game/ClientVisuals.spec.ts +56 -0
- package/src/Game/ClientVisuals.ts +184 -0
- package/src/Game/EventComponentResolver.spec.ts +84 -0
- package/src/Game/EventComponentResolver.ts +74 -0
- package/src/Game/Map.ts +10 -0
- package/src/Game/Object.spec.ts +46 -0
- package/src/Game/Object.ts +2 -2
- package/src/Game/ProjectileManager.spec.ts +449 -0
- package/src/Game/ProjectileManager.ts +346 -0
- package/src/RpgClient.ts +130 -15
- package/src/RpgClientEngine.ts +405 -69
- package/src/components/animations/fx.ce +101 -0
- package/src/components/animations/index.ts +4 -2
- package/src/components/character.ce +185 -40
- package/src/components/dynamics/bar.ce +4 -3
- package/src/components/dynamics/image.ce +2 -1
- package/src/components/dynamics/shape.ce +3 -2
- package/src/components/dynamics/text.ce +9 -8
- package/src/components/gui/dialogbox/index.ce +3 -2
- package/src/components/gui/gameover.ce +2 -1
- package/src/components/gui/menu/equip-menu.ce +2 -1
- package/src/components/gui/menu/exit-menu.ce +2 -1
- package/src/components/gui/menu/items-menu.ce +3 -2
- package/src/components/gui/menu/main-menu.ce +2 -1
- package/src/components/gui/save-load.ce +2 -1
- package/src/components/gui/shop/shop.ce +3 -2
- package/src/components/gui/title-screen.ce +2 -1
- package/src/components/index.ts +2 -1
- package/src/components/player-components.ce +11 -10
- package/src/components/prebuilt/hp-bar.ce +4 -3
- package/src/components/prebuilt/light-halo.ce +2 -2
- package/src/components/scenes/canvas.ce +10 -2
- package/src/components/scenes/draw-map.ce +17 -3
- package/src/index.ts +4 -0
- package/src/module.ts +24 -0
- package/src/services/actionInput.spec.ts +155 -0
- package/src/services/actionInput.ts +120 -0
- package/src/services/mmorpg-connection.spec.ts +99 -0
- package/src/services/mmorpg-connection.ts +69 -0
- package/src/services/mmorpg.ts +60 -34
- package/src/services/pointerContext.spec.ts +36 -0
- package/src/services/pointerContext.ts +84 -0
- package/src/services/standalone-message.ts +7 -0
- package/src/services/standalone.spec.ts +34 -0
- package/src/services/standalone.ts +42 -12
- package/src/utils/mapId.ts +2 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<Fx
|
|
2
|
+
name={name}
|
|
3
|
+
preset={preset}
|
|
4
|
+
trigger={trigger}
|
|
5
|
+
autostart={autostart}
|
|
6
|
+
loop={loop}
|
|
7
|
+
enabled={enabled}
|
|
8
|
+
x={x}
|
|
9
|
+
y={y}
|
|
10
|
+
rotation={rotation}
|
|
11
|
+
scale={scale}
|
|
12
|
+
alpha={alpha}
|
|
13
|
+
timeScale={timeScale}
|
|
14
|
+
maxParticles={maxParticles}
|
|
15
|
+
preload={preload}
|
|
16
|
+
missingTexture={missingTexture}
|
|
17
|
+
zIndex={zIndex}
|
|
18
|
+
onStart={onStart}
|
|
19
|
+
onComplete={finish}
|
|
20
|
+
onParticleSpawn={onParticleSpawn}
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
<script>
|
|
24
|
+
import { tick } from "canvasengine";
|
|
25
|
+
import { Fx } from "@canvasengine/presets";
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
name,
|
|
29
|
+
preset,
|
|
30
|
+
trigger,
|
|
31
|
+
onFinish,
|
|
32
|
+
onStart,
|
|
33
|
+
onComplete,
|
|
34
|
+
onParticleSpawn,
|
|
35
|
+
displayDuration,
|
|
36
|
+
duration,
|
|
37
|
+
autostart,
|
|
38
|
+
loop,
|
|
39
|
+
enabled,
|
|
40
|
+
x,
|
|
41
|
+
y,
|
|
42
|
+
rotation,
|
|
43
|
+
scale,
|
|
44
|
+
alpha,
|
|
45
|
+
timeScale,
|
|
46
|
+
maxParticles,
|
|
47
|
+
preload,
|
|
48
|
+
missingTexture,
|
|
49
|
+
zIndex,
|
|
50
|
+
} = defineProps({
|
|
51
|
+
autostart: {
|
|
52
|
+
default: true,
|
|
53
|
+
},
|
|
54
|
+
loop: {
|
|
55
|
+
default: false,
|
|
56
|
+
},
|
|
57
|
+
enabled: {
|
|
58
|
+
default: true,
|
|
59
|
+
},
|
|
60
|
+
rotation: {
|
|
61
|
+
default: 0,
|
|
62
|
+
},
|
|
63
|
+
scale: {
|
|
64
|
+
default: 1,
|
|
65
|
+
},
|
|
66
|
+
alpha: {
|
|
67
|
+
default: 1,
|
|
68
|
+
},
|
|
69
|
+
timeScale: {
|
|
70
|
+
default: 1,
|
|
71
|
+
},
|
|
72
|
+
maxParticles: {
|
|
73
|
+
default: 600,
|
|
74
|
+
},
|
|
75
|
+
preload: {
|
|
76
|
+
default: true,
|
|
77
|
+
},
|
|
78
|
+
missingTexture: {
|
|
79
|
+
default: "shape",
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
let elapsedTime = 0;
|
|
84
|
+
let finished = false;
|
|
85
|
+
|
|
86
|
+
function finish(instance) {
|
|
87
|
+
if (finished) return;
|
|
88
|
+
finished = true;
|
|
89
|
+
onComplete?.(instance);
|
|
90
|
+
onFinish?.(instance);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
tick(({ deltaTime }) => {
|
|
94
|
+
const maxDuration = displayDuration?.() ?? (loop() ? duration?.() : undefined);
|
|
95
|
+
if (!maxDuration || finished) return;
|
|
96
|
+
elapsedTime += deltaTime;
|
|
97
|
+
if (elapsedTime >= maxDuration) {
|
|
98
|
+
finish();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
</script>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<Container x={smoothX} y={smoothY} zIndex={z} viewportFollow={shouldFollowCamera} controls onBeforeDestroy visible>
|
|
2
2
|
@for (compConfig of normalizedComponentsBehind) {
|
|
3
3
|
<Container>
|
|
4
|
-
<compConfig.component object ...compConfig.props />
|
|
4
|
+
<compConfig.component object={sprite} ...compConfig.props />
|
|
5
5
|
</Container>
|
|
6
6
|
}
|
|
7
|
-
<PlayerComponents object position="bottom" graphicBounds />
|
|
8
|
-
<PlayerComponents object position="left" graphicBounds />
|
|
7
|
+
<PlayerComponents object={sprite} position="bottom" graphicBounds />
|
|
8
|
+
<PlayerComponents object={sprite} position="left" graphicBounds />
|
|
9
9
|
<Particle emit={emitParticleTrigger} settings={particleSettings} zIndex={1000} name={particleName} />
|
|
10
10
|
<Container>
|
|
11
|
-
@for (graphicObj of
|
|
11
|
+
@for (graphicObj of renderedGraphics) {
|
|
12
12
|
<Container scale={graphicScale(graphicObj)}>
|
|
13
13
|
<Sprite
|
|
14
14
|
sheet={sheet(graphicObj)}
|
|
@@ -20,19 +20,24 @@
|
|
|
20
20
|
/>
|
|
21
21
|
</Container>
|
|
22
22
|
}
|
|
23
|
+
@for (eventComponent of resolvedEventComponents) {
|
|
24
|
+
<Container dependencies={eventComponent.dependencies}>
|
|
25
|
+
<eventComponent.component ...eventComponent.props />
|
|
26
|
+
</Container>
|
|
27
|
+
}
|
|
23
28
|
</Container>
|
|
24
|
-
<PlayerComponents object position="center" graphicBounds />
|
|
25
|
-
<PlayerComponents object position="right" graphicBounds />
|
|
26
|
-
<PlayerComponents object position="top" graphicBounds />
|
|
29
|
+
<PlayerComponents object={sprite} position="center" graphicBounds />
|
|
30
|
+
<PlayerComponents object={sprite} position="right" graphicBounds />
|
|
31
|
+
<PlayerComponents object={sprite} position="top" graphicBounds />
|
|
27
32
|
@for (compConfig of normalizedComponentsInFront) {
|
|
28
33
|
<Container dependencies={compConfig.dependencies}>
|
|
29
|
-
<compConfig.component object ...compConfig.props />
|
|
34
|
+
<compConfig.component object={sprite} ...compConfig.props />
|
|
30
35
|
</Container>
|
|
31
36
|
}
|
|
32
37
|
@for (attachedGui of attachedGuis) {
|
|
33
38
|
@if (shouldDisplayAttachedGui) {
|
|
34
39
|
<Container>
|
|
35
|
-
<attachedGui.component ...attachedGui.data() dependencies={attachedGui.dependencies} object={
|
|
40
|
+
<attachedGui.component ...attachedGui.data() dependencies={attachedGui.dependencies} object={sprite} onFinish={(data) => {
|
|
36
41
|
onAttachedGuiFinish(attachedGui, data)
|
|
37
42
|
}} onInteraction={(name, data) => {
|
|
38
43
|
onAttachedGuiInteraction(attachedGui, name, data)
|
|
@@ -52,12 +57,20 @@
|
|
|
52
57
|
import { RpgClientEngine } from "../RpgClientEngine";
|
|
53
58
|
import { inject } from "../core/inject";
|
|
54
59
|
import { Direction, Animation } from "@rpgjs/common";
|
|
60
|
+
import { normalizeEventComponent } from "../Game/EventComponentResolver";
|
|
55
61
|
import Hit from "./effects/hit.ce";
|
|
56
62
|
import PlayerComponents from "./player-components.ce";
|
|
57
63
|
import { RpgGui } from "../Gui/Gui";
|
|
58
64
|
import { getCanMoveValue } from "../utils/readPropValue";
|
|
65
|
+
import {
|
|
66
|
+
getKeyboardControlBind,
|
|
67
|
+
keyboardEventMatchesBind,
|
|
68
|
+
resolveKeyboardActionInput,
|
|
69
|
+
resolveKeyboardDirectionInput,
|
|
70
|
+
} from "../services/actionInput";
|
|
59
71
|
|
|
60
72
|
const { object, id } = defineProps();
|
|
73
|
+
const sprite = object();
|
|
61
74
|
|
|
62
75
|
const client = inject(RpgClientEngine);
|
|
63
76
|
const hooks = inject(ModulesToken);
|
|
@@ -71,9 +84,9 @@
|
|
|
71
84
|
const playerId = client.playerIdSignal();
|
|
72
85
|
const currentPlayer = playerId ? client.sceneMap?.players?.()?.[playerId] : undefined;
|
|
73
86
|
return readProp(id) === playerId
|
|
74
|
-
|| readProp(
|
|
75
|
-
||
|
|
76
|
-
||
|
|
87
|
+
|| readProp(sprite?.id) === playerId
|
|
88
|
+
|| sprite === currentPlayer
|
|
89
|
+
|| sprite === client.sceneMap?.getCurrentPlayer?.();
|
|
77
90
|
};
|
|
78
91
|
const isMe = computed(isCurrentPlayer);
|
|
79
92
|
const shadowsEnabled = computed(() => {
|
|
@@ -150,8 +163,8 @@
|
|
|
150
163
|
// The computed will be created in the template when needed
|
|
151
164
|
return {
|
|
152
165
|
component: componentRef,
|
|
153
|
-
props: typeof propsValue === 'function' ? propsValue(
|
|
154
|
-
dependencies: dependenciesFn ? dependenciesFn(
|
|
166
|
+
props: typeof propsValue === 'function' ? propsValue(sprite) : propsValue || {},
|
|
167
|
+
dependencies: dependenciesFn ? dependenciesFn(sprite) : []
|
|
155
168
|
};
|
|
156
169
|
};
|
|
157
170
|
|
|
@@ -211,6 +224,18 @@
|
|
|
211
224
|
const normalizedComponentsInFront = computed(() => {
|
|
212
225
|
return normalizeComponents(componentsInFront());
|
|
213
226
|
});
|
|
227
|
+
|
|
228
|
+
const isEventSprite = () => {
|
|
229
|
+
return typeof sprite?.isEvent === 'function'
|
|
230
|
+
? sprite.isEvent()
|
|
231
|
+
: sprite?._type === 'event';
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const resolvedEventComponents = computed(() => {
|
|
235
|
+
if (!isEventSprite()) return [];
|
|
236
|
+
const eventComponent = normalizeEventComponent(client.resolveEventComponent(sprite), sprite);
|
|
237
|
+
return eventComponent ? [eventComponent] : [];
|
|
238
|
+
});
|
|
214
239
|
|
|
215
240
|
/**
|
|
216
241
|
* Determine if the camera should follow this sprite
|
|
@@ -259,7 +284,13 @@
|
|
|
259
284
|
isConnected,
|
|
260
285
|
graphicsSignals,
|
|
261
286
|
flashTrigger
|
|
262
|
-
} =
|
|
287
|
+
} = sprite;
|
|
288
|
+
|
|
289
|
+
const renderedGraphics = computed(() => {
|
|
290
|
+
const eventComponent = resolvedEventComponents()[0];
|
|
291
|
+
if (eventComponent && !eventComponent.renderGraphic) return [];
|
|
292
|
+
return graphicsSignals();
|
|
293
|
+
});
|
|
263
294
|
|
|
264
295
|
/**
|
|
265
296
|
* Flash configuration signals for dynamic options
|
|
@@ -304,11 +335,92 @@
|
|
|
304
335
|
|
|
305
336
|
const particleSettings = client.particleSettings;
|
|
306
337
|
|
|
307
|
-
const canControls = () => isMe() && getCanMoveValue(
|
|
338
|
+
const canControls = () => isMe() && getCanMoveValue(sprite)
|
|
308
339
|
const keyboardControls = client.globalConfig.keyboardControls;
|
|
340
|
+
const activeDirectionKeys = new Map();
|
|
341
|
+
|
|
342
|
+
const resolveHeldDirection = () => {
|
|
343
|
+
const directions = Array.from(activeDirectionKeys.values());
|
|
344
|
+
return directions[directions.length - 1];
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
const resolveSpriteDirection = () => {
|
|
348
|
+
const heldDirection = resolveHeldDirection();
|
|
349
|
+
if (heldDirection) return heldDirection;
|
|
350
|
+
if (typeof sprite.getDirection === 'function') return sprite.getDirection();
|
|
351
|
+
if (typeof sprite.direction === 'function') return sprite.direction();
|
|
352
|
+
return direction();
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const withCurrentDirection = (payload) => {
|
|
356
|
+
if (payload.action !== 'action') return payload;
|
|
357
|
+
const data = payload.data && typeof payload.data === 'object'
|
|
358
|
+
? { ...payload.data }
|
|
359
|
+
: {};
|
|
360
|
+
return {
|
|
361
|
+
...payload,
|
|
362
|
+
data: {
|
|
363
|
+
...data,
|
|
364
|
+
direction: data.direction ?? resolveSpriteDirection(),
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const resolveCurrentActionInput = () =>
|
|
370
|
+
withCurrentDirection(
|
|
371
|
+
resolveKeyboardActionInput(keyboardControls.action, client, sprite)
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
const playPredictedWalkAnimation = () => {
|
|
375
|
+
if (sprite.animationFixed) return;
|
|
376
|
+
if (sprite.animationIsPlaying && sprite.animationIsPlaying()) return;
|
|
377
|
+
realAnimationName.set('walk');
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
const resumeHeldDirectionWalkAnimation = () => {
|
|
381
|
+
if (!isCurrentPlayer()) return false;
|
|
382
|
+
if (activeDirectionKeys.size === 0) return false;
|
|
383
|
+
if (!canControls()) return false;
|
|
384
|
+
if (sprite.animationFixed) return false;
|
|
385
|
+
if (sprite.animationIsPlaying && sprite.animationIsPlaying()) return false;
|
|
386
|
+
realAnimationName.set('walk');
|
|
387
|
+
return true;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
const processMovementInput = (input) => {
|
|
391
|
+
if (!canControls()) return;
|
|
392
|
+
client.processInput({ input });
|
|
393
|
+
playPredictedWalkAnimation();
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const actionBind = () => getKeyboardControlBind(keyboardControls.action);
|
|
397
|
+
const keyboardEventId = (event) => `${event.keyCode}:${event.code}:${event.key}`;
|
|
398
|
+
|
|
399
|
+
const handleNativeActionWhileMoving = (event) => {
|
|
400
|
+
const inputDirection = resolveKeyboardDirectionInput(event, keyboardControls);
|
|
401
|
+
if (inputDirection) {
|
|
402
|
+
const keyId = keyboardEventId(event);
|
|
403
|
+
if (event.type === 'keydown') {
|
|
404
|
+
activeDirectionKeys.delete(keyId);
|
|
405
|
+
activeDirectionKeys.set(keyId, inputDirection);
|
|
406
|
+
resumeHeldDirectionWalkAnimation();
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
activeDirectionKeys.delete(keyId);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (!isCurrentPlayer()) return;
|
|
414
|
+
if (event.type !== 'keydown' || event.repeat) return;
|
|
415
|
+
if (activeDirectionKeys.size === 0) return;
|
|
416
|
+
if (!keyboardEventMatchesBind(event, actionBind())) return;
|
|
417
|
+
if (!canControls()) return;
|
|
418
|
+
|
|
419
|
+
client.processAction(resolveCurrentActionInput());
|
|
420
|
+
};
|
|
309
421
|
|
|
310
422
|
const visible = computed(() => {
|
|
311
|
-
if (
|
|
423
|
+
if (sprite.isEvent()) {
|
|
312
424
|
return true
|
|
313
425
|
}
|
|
314
426
|
return isConnected()
|
|
@@ -319,35 +431,35 @@
|
|
|
319
431
|
repeat: true,
|
|
320
432
|
bind: keyboardControls.down,
|
|
321
433
|
keyDown() {
|
|
322
|
-
|
|
434
|
+
processMovementInput(Direction.Down)
|
|
323
435
|
},
|
|
324
436
|
},
|
|
325
437
|
up: {
|
|
326
438
|
repeat: true,
|
|
327
439
|
bind: keyboardControls.up,
|
|
328
440
|
keyDown() {
|
|
329
|
-
|
|
441
|
+
processMovementInput(Direction.Up)
|
|
330
442
|
},
|
|
331
443
|
},
|
|
332
444
|
left: {
|
|
333
445
|
repeat: true,
|
|
334
446
|
bind: keyboardControls.left,
|
|
335
447
|
keyDown() {
|
|
336
|
-
|
|
448
|
+
processMovementInput(Direction.Left)
|
|
337
449
|
},
|
|
338
450
|
},
|
|
339
451
|
right: {
|
|
340
452
|
repeat: true,
|
|
341
453
|
bind: keyboardControls.right,
|
|
342
454
|
keyDown() {
|
|
343
|
-
|
|
455
|
+
processMovementInput(Direction.Right)
|
|
344
456
|
},
|
|
345
457
|
},
|
|
346
458
|
action: {
|
|
347
|
-
bind: keyboardControls.action,
|
|
459
|
+
bind: getKeyboardControlBind(keyboardControls.action),
|
|
348
460
|
keyDown() {
|
|
349
461
|
if (canControls()) {
|
|
350
|
-
client.processAction(
|
|
462
|
+
client.processAction(resolveCurrentActionInput())
|
|
351
463
|
}
|
|
352
464
|
},
|
|
353
465
|
},
|
|
@@ -373,7 +485,7 @@
|
|
|
373
485
|
});
|
|
374
486
|
|
|
375
487
|
const z = computed(() => {
|
|
376
|
-
return
|
|
488
|
+
return sprite.y() + sprite.z()
|
|
377
489
|
});
|
|
378
490
|
|
|
379
491
|
const realAnimationName = signal(animationName());
|
|
@@ -646,6 +758,10 @@
|
|
|
646
758
|
const graphicBounds = computed(() => {
|
|
647
759
|
const box = hitbox();
|
|
648
760
|
const fallback = hitboxBounds();
|
|
761
|
+
const customEventComponent = resolvedEventComponents()[0];
|
|
762
|
+
if (customEventComponent && !customEventComponent.renderGraphic) {
|
|
763
|
+
return fallback;
|
|
764
|
+
}
|
|
649
765
|
const dimensions = imageDimensions();
|
|
650
766
|
const graphics = graphicsSignals();
|
|
651
767
|
let bounds = null;
|
|
@@ -734,8 +850,8 @@
|
|
|
734
850
|
let beforeRemovePromise = null;
|
|
735
851
|
let beforeRemoveTransitionValue = null;
|
|
736
852
|
const resolveRemoveContext = () => {
|
|
737
|
-
if (!
|
|
738
|
-
const value =
|
|
853
|
+
if (!sprite._removeTransition) return null;
|
|
854
|
+
const value = sprite._removeTransition();
|
|
739
855
|
if (!value || typeof value !== 'string') return null;
|
|
740
856
|
try {
|
|
741
857
|
const context = JSON.parse(value);
|
|
@@ -764,37 +880,57 @@
|
|
|
764
880
|
}
|
|
765
881
|
beforeRemoveTransitionValue = context.__transitionValue;
|
|
766
882
|
beforeRemovePromise = withTimeout(
|
|
767
|
-
lastValueFrom(hooks.callHooks("client-sprite-onBeforeRemove",
|
|
883
|
+
lastValueFrom(hooks.callHooks("client-sprite-onBeforeRemove", sprite, context)),
|
|
768
884
|
context.timeoutMs
|
|
769
885
|
);
|
|
770
886
|
return beforeRemovePromise;
|
|
771
887
|
};
|
|
772
888
|
|
|
773
|
-
const removeTransitionSubscription =
|
|
889
|
+
const removeTransitionSubscription = sprite._removeTransition?.observable?.subscribe(() => {
|
|
774
890
|
if (resolveRemoveContext()) {
|
|
775
891
|
runBeforeRemove();
|
|
776
892
|
}
|
|
777
893
|
});
|
|
778
894
|
|
|
779
895
|
const animationMovementSubscription = combineLatest([animationChange$, moving$]).subscribe(([[prev, curr], isMoving]) => {
|
|
896
|
+
const isMovementAnimation = movementAnimations.includes(curr);
|
|
897
|
+
const isTemporaryAnimationPlaying =
|
|
898
|
+
sprite.animationIsPlaying && sprite.animationIsPlaying();
|
|
899
|
+
|
|
900
|
+
if (sprite.animationFixed && isMovementAnimation && isTemporaryAnimationPlaying) {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
|
|
780
904
|
if (curr == 'stand' && !isMoving) {
|
|
781
|
-
|
|
905
|
+
if (!resumeHeldDirectionWalkAnimation()) {
|
|
906
|
+
realAnimationName.set(curr);
|
|
907
|
+
}
|
|
782
908
|
}
|
|
783
909
|
else if (curr == 'walk' && isMoving) {
|
|
784
910
|
realAnimationName.set(curr);
|
|
785
911
|
}
|
|
786
|
-
else if (!
|
|
912
|
+
else if (!isMovementAnimation) {
|
|
787
913
|
realAnimationName.set(curr);
|
|
788
914
|
}
|
|
789
|
-
if (!isMoving &&
|
|
790
|
-
if (
|
|
791
|
-
if (typeof
|
|
792
|
-
|
|
915
|
+
if (!isMoving && isTemporaryAnimationPlaying) {
|
|
916
|
+
if (isMovementAnimation) {
|
|
917
|
+
if (typeof sprite.resetAnimationState === 'function') {
|
|
918
|
+
sprite.resetAnimationState();
|
|
793
919
|
}
|
|
794
920
|
}
|
|
795
921
|
}
|
|
796
922
|
});
|
|
797
923
|
|
|
924
|
+
const resumeWalkSubscriptions = [
|
|
925
|
+
sprite._canMove,
|
|
926
|
+
sprite._animationFixed,
|
|
927
|
+
sprite.animationIsPlaying,
|
|
928
|
+
]
|
|
929
|
+
.filter(signal => signal?.observable)
|
|
930
|
+
.map(signal => signal.observable.subscribe(() => {
|
|
931
|
+
resumeHeldDirectionWalkAnimation();
|
|
932
|
+
}));
|
|
933
|
+
|
|
798
934
|
/**
|
|
799
935
|
* Cleanup subscriptions and call hooks before sprite destruction.
|
|
800
936
|
*
|
|
@@ -806,7 +942,7 @@
|
|
|
806
942
|
* await onBeforeDestroy();
|
|
807
943
|
*/
|
|
808
944
|
const waitForTemporaryAnimationEnd = (maxDuration = 1200) => {
|
|
809
|
-
if (!
|
|
945
|
+
if (!sprite.animationIsPlaying || !sprite.animationIsPlaying()) {
|
|
810
946
|
return Promise.resolve();
|
|
811
947
|
}
|
|
812
948
|
|
|
@@ -822,7 +958,7 @@
|
|
|
822
958
|
resolve();
|
|
823
959
|
};
|
|
824
960
|
timeout = setTimeout(finish, maxDuration);
|
|
825
|
-
subscription =
|
|
961
|
+
subscription = sprite.animationIsPlaying.observable.subscribe((isPlaying) => {
|
|
826
962
|
if (!isPlaying) finish();
|
|
827
963
|
});
|
|
828
964
|
if (finished) subscription.unsubscribe();
|
|
@@ -832,17 +968,26 @@
|
|
|
832
968
|
const onBeforeDestroy = async () => {
|
|
833
969
|
await runBeforeRemove();
|
|
834
970
|
await waitForTemporaryAnimationEnd();
|
|
971
|
+
if (typeof document !== 'undefined') {
|
|
972
|
+
document.removeEventListener('keydown', handleNativeActionWhileMoving);
|
|
973
|
+
document.removeEventListener('keyup', handleNativeActionWhileMoving);
|
|
974
|
+
}
|
|
835
975
|
removeTransitionSubscription?.unsubscribe();
|
|
836
976
|
animationMovementSubscription.unsubscribe();
|
|
977
|
+
resumeWalkSubscriptions.forEach(subscription => subscription.unsubscribe());
|
|
837
978
|
xSubscription.unsubscribe();
|
|
838
979
|
ySubscription.unsubscribe();
|
|
839
|
-
await lastValueFrom(hooks.callHooks("client-sprite-onDestroy",
|
|
840
|
-
await lastValueFrom(hooks.callHooks("client-sceneMap-onRemoveSprite", client.sceneMap,
|
|
980
|
+
await lastValueFrom(hooks.callHooks("client-sprite-onDestroy", sprite))
|
|
981
|
+
await lastValueFrom(hooks.callHooks("client-sceneMap-onRemoveSprite", client.sceneMap, sprite))
|
|
841
982
|
}
|
|
842
983
|
|
|
843
984
|
mount((element) => {
|
|
844
|
-
|
|
845
|
-
|
|
985
|
+
if (typeof document !== 'undefined') {
|
|
986
|
+
document.addEventListener('keydown', handleNativeActionWhileMoving);
|
|
987
|
+
document.addEventListener('keyup', handleNativeActionWhileMoving);
|
|
988
|
+
}
|
|
989
|
+
hooks.callHooks("client-sprite-onAdd", sprite).subscribe()
|
|
990
|
+
hooks.callHooks("client-sceneMap-onAddSprite", client.sceneMap, sprite).subscribe()
|
|
846
991
|
effect(() => {
|
|
847
992
|
if (isCurrentPlayer()) {
|
|
848
993
|
client.setKeyboardControls(element.directives.controls)
|
|
@@ -10,17 +10,18 @@ import { computed } from "canvasengine";
|
|
|
10
10
|
import { resolveDynamicValue } from "./parse-value";
|
|
11
11
|
|
|
12
12
|
const { object, current, max, style, text } = defineProps();
|
|
13
|
+
const sprite = object();
|
|
13
14
|
|
|
14
15
|
const read = (prop, fallback) => prop ? prop() : fallback;
|
|
15
16
|
|
|
16
17
|
const toNumber = (value, fallback = 0) => {
|
|
17
|
-
const resolved = resolveDynamicValue(value,
|
|
18
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
18
19
|
const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);
|
|
19
20
|
return Number.isFinite(num) ? num : fallback;
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
const toColor = (value, fallback) => {
|
|
23
|
-
const resolved = resolveDynamicValue(value,
|
|
24
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
24
25
|
if (typeof resolved === 'number') return resolved;
|
|
25
26
|
if (typeof resolved === 'string' && resolved.startsWith('#')) {
|
|
26
27
|
return parseInt(resolved.slice(1), 16);
|
|
@@ -57,7 +58,7 @@ const labelText = computed(() => {
|
|
|
57
58
|
.replace(/\{\$max\}/g, String(maxValue()))
|
|
58
59
|
.replace(/\{\$percent\}/g, String(Math.round(percent() * 100)));
|
|
59
60
|
|
|
60
|
-
return String(resolveDynamicValue(value,
|
|
61
|
+
return String(resolveDynamicValue(value, sprite) ?? '');
|
|
61
62
|
});
|
|
62
63
|
const labelSize = computed(() => toNumber(config().fontSize, 10));
|
|
63
64
|
const hasLabel = computed(() => labelText().length > 0);
|
|
@@ -7,10 +7,11 @@ import { inject } from "../../core/inject";
|
|
|
7
7
|
import { resolveDynamicValue } from "./parse-value";
|
|
8
8
|
|
|
9
9
|
const { object, value } = defineProps();
|
|
10
|
+
const sprite = object();
|
|
10
11
|
const client = inject(RpgClientEngine);
|
|
11
12
|
|
|
12
13
|
const sheet = computed(() => {
|
|
13
|
-
const id = resolveDynamicValue(value?.(),
|
|
14
|
+
const id = resolveDynamicValue(value?.(), sprite);
|
|
14
15
|
if (!id) return null;
|
|
15
16
|
return {
|
|
16
17
|
definition: client.getSpriteSheet(id),
|
|
@@ -9,17 +9,18 @@ import { getShapeBox, translatePolygonPoints } from "./shape-utils";
|
|
|
9
9
|
|
|
10
10
|
const props = defineProps();
|
|
11
11
|
const { object } = props;
|
|
12
|
+
const sprite = object();
|
|
12
13
|
|
|
13
14
|
const read = (prop, fallback) => prop ? prop() : fallback;
|
|
14
15
|
|
|
15
16
|
const toNumber = (value, fallback = 0) => {
|
|
16
|
-
const resolved = resolveDynamicValue(value,
|
|
17
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
17
18
|
const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);
|
|
18
19
|
return Number.isFinite(num) ? num : fallback;
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
const toColor = (value, fallback) => {
|
|
22
|
-
const resolved = resolveDynamicValue(value,
|
|
23
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
23
24
|
if (typeof resolved === 'number') return resolved;
|
|
24
25
|
if (typeof resolved === 'string' && resolved.startsWith('#')) {
|
|
25
26
|
return parseInt(resolved.slice(1), 16);
|
|
@@ -5,11 +5,12 @@ import { computed } from "canvasengine";
|
|
|
5
5
|
import { resolveDynamicValue } from "./parse-value";
|
|
6
6
|
|
|
7
7
|
const { object, value, style } = defineProps();
|
|
8
|
+
const sprite = object();
|
|
8
9
|
|
|
9
10
|
const read = (prop, fallback) => prop ? prop() : fallback;
|
|
10
11
|
|
|
11
12
|
const parseNumericStyleValue = (value, object) => {
|
|
12
|
-
value = resolveDynamicValue(value,
|
|
13
|
+
value = resolveDynamicValue(value, sprite);
|
|
13
14
|
if (value === undefined || value === null) return undefined;
|
|
14
15
|
if (typeof value === 'number') return value;
|
|
15
16
|
|
|
@@ -22,15 +23,15 @@ const getTextStyle = (style) => {
|
|
|
22
23
|
const textStyle = {};
|
|
23
24
|
|
|
24
25
|
if (style.fontStyle !== undefined) {
|
|
25
|
-
textStyle.fontStyle = resolveDynamicValue(style.fontStyle,
|
|
26
|
+
textStyle.fontStyle = resolveDynamicValue(style.fontStyle, sprite);
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
if (style.fontWeight !== undefined) {
|
|
29
|
-
textStyle.fontWeight = resolveDynamicValue(style.fontWeight,
|
|
30
|
+
textStyle.fontWeight = resolveDynamicValue(style.fontWeight, sprite);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
if (style.stroke !== undefined) {
|
|
33
|
-
textStyle.stroke = resolveDynamicValue(style.stroke,
|
|
34
|
+
textStyle.stroke = resolveDynamicValue(style.stroke, sprite);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
if (style.opacity !== undefined) {
|
|
@@ -45,16 +46,16 @@ const getTextStyle = (style) => {
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
if (style.align !== undefined) {
|
|
48
|
-
textStyle.align = resolveDynamicValue(style.align,
|
|
49
|
+
textStyle.align = resolveDynamicValue(style.align, sprite);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
return textStyle;
|
|
52
53
|
};
|
|
53
54
|
|
|
54
|
-
const textValue = computed(() => String(resolveDynamicValue(read(value, ''),
|
|
55
|
+
const textValue = computed(() => String(resolveDynamicValue(read(value, ''), sprite) ?? ''));
|
|
55
56
|
const textColor = computed(() => {
|
|
56
57
|
const currentStyle = read(style, {});
|
|
57
|
-
return currentStyle.fill !== undefined ? resolveDynamicValue(currentStyle.fill,
|
|
58
|
+
return currentStyle.fill !== undefined ? resolveDynamicValue(currentStyle.fill, sprite) : undefined;
|
|
58
59
|
});
|
|
59
60
|
const textSize = computed(() => {
|
|
60
61
|
const currentStyle = read(style, {});
|
|
@@ -62,7 +63,7 @@ const textSize = computed(() => {
|
|
|
62
63
|
});
|
|
63
64
|
const textFontFamily = computed(() => {
|
|
64
65
|
const currentStyle = read(style, {});
|
|
65
|
-
return currentStyle.fontFamily !== undefined ? resolveDynamicValue(currentStyle.fontFamily,
|
|
66
|
+
return currentStyle.fontFamily !== undefined ? resolveDynamicValue(currentStyle.fontFamily, sprite) : undefined;
|
|
66
67
|
});
|
|
67
68
|
const textStyle = computed(() => getTextStyle(read(style, {})));
|
|
68
69
|
</script>
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
import { inject } from "../../../core/inject";
|
|
54
54
|
import { RpgClientEngine } from "../../../RpgClientEngine";
|
|
55
55
|
import { delay } from "@rpgjs/common";
|
|
56
|
+
import { getKeyboardControlBind } from "../../../services/actionInput";
|
|
56
57
|
|
|
57
58
|
const engine = inject(RpgClientEngine);
|
|
58
59
|
const currentPlayer = engine.scene.currentPlayer
|
|
@@ -172,7 +173,7 @@
|
|
|
172
173
|
}
|
|
173
174
|
},
|
|
174
175
|
action: {
|
|
175
|
-
bind: keyboardControls.action,
|
|
176
|
+
bind: getKeyboardControlBind(keyboardControls.action),
|
|
176
177
|
keyDown() {
|
|
177
178
|
if (isTyping()) {
|
|
178
179
|
finishTyping();
|
|
@@ -189,7 +190,7 @@
|
|
|
189
190
|
|
|
190
191
|
const dialogControls = signal({
|
|
191
192
|
action: {
|
|
192
|
-
bind: keyboardControls.action,
|
|
193
|
+
bind: getKeyboardControlBind(keyboardControls.action),
|
|
193
194
|
keyDown() {
|
|
194
195
|
if (isTyping()) {
|
|
195
196
|
finishTyping();
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
import { inject } from "../../core/inject";
|
|
32
32
|
import { RpgClientEngine } from "../../RpgClientEngine";
|
|
33
33
|
import { RpgGui } from "../../Gui/Gui";
|
|
34
|
+
import { getKeyboardControlBind } from "../../services/actionInput";
|
|
34
35
|
|
|
35
36
|
const engine = inject(RpgClientEngine);
|
|
36
37
|
const guiService = inject(RpgGui);
|
|
@@ -146,7 +147,7 @@
|
|
|
146
147
|
}
|
|
147
148
|
},
|
|
148
149
|
action: {
|
|
149
|
-
bind: keyboardControls.action,
|
|
150
|
+
bind: getKeyboardControlBind(keyboardControls.action),
|
|
150
151
|
keyDown() {
|
|
151
152
|
triggerSelect(selectedEntry());
|
|
152
153
|
}
|