@rpgjs/server 5.0.0-alpha.2 → 5.0.0-alpha.21
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/dist/Gui/DialogGui.d.ts +4 -0
- package/dist/Gui/index.d.ts +1 -0
- package/dist/Player/BattleManager.d.ts +32 -22
- package/dist/Player/ClassManager.d.ts +31 -18
- package/dist/Player/ComponentManager.d.ts +123 -0
- package/dist/Player/Components.d.ts +345 -0
- package/dist/Player/EffectManager.d.ts +40 -0
- package/dist/Player/ElementManager.d.ts +31 -0
- package/dist/Player/GoldManager.d.ts +22 -0
- package/dist/Player/GuiManager.d.ts +176 -0
- package/dist/Player/ItemFixture.d.ts +6 -0
- package/dist/Player/ItemManager.d.ts +164 -10
- package/dist/Player/MoveManager.d.ts +32 -44
- package/dist/Player/ParameterManager.d.ts +343 -14
- package/dist/Player/Player.d.ts +266 -8
- package/dist/Player/SkillManager.d.ts +27 -19
- package/dist/Player/StateManager.d.ts +28 -35
- package/dist/Player/VariableManager.d.ts +30 -0
- package/dist/RpgServer.d.ts +227 -1
- package/dist/decorators/event.d.ts +46 -0
- package/dist/decorators/map.d.ts +177 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +17472 -18167
- package/dist/index.js.map +1 -1
- package/dist/rooms/map.d.ts +486 -8
- package/package.json +17 -15
- package/src/Gui/DialogGui.ts +7 -2
- package/src/Gui/index.ts +3 -1
- package/src/Player/BattleManager.ts +97 -38
- package/src/Player/ClassManager.ts +95 -35
- package/src/Player/ComponentManager.ts +425 -19
- package/src/Player/Components.ts +380 -0
- package/src/Player/EffectManager.ts +110 -27
- package/src/Player/ElementManager.ts +126 -25
- package/src/Player/GoldManager.ts +32 -35
- package/src/Player/GuiManager.ts +187 -140
- package/src/Player/ItemFixture.ts +4 -5
- package/src/Player/ItemManager.ts +363 -48
- package/src/Player/MoveManager.ts +323 -308
- package/src/Player/ParameterManager.ts +499 -99
- package/src/Player/Player.ts +719 -80
- package/src/Player/SkillManager.ts +44 -23
- package/src/Player/StateManager.ts +210 -95
- package/src/Player/VariableManager.ts +180 -48
- package/src/RpgServer.ts +236 -1
- package/src/core/context.ts +1 -0
- package/src/decorators/event.ts +61 -0
- package/src/decorators/map.ts +198 -0
- package/src/index.ts +7 -1
- package/src/module.ts +24 -0
- package/src/rooms/map.ts +1054 -54
- package/dist/Player/Event.d.ts +0 -0
- package/src/Player/Event.ts +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { RpgCommonPlayer,
|
|
3
|
-
import {
|
|
4
|
-
MovementManager,
|
|
1
|
+
import { PlayerCtor, ProjectileType } from "@rpgjs/common";
|
|
2
|
+
import { RpgCommonPlayer, Direction, Entity } from "@rpgjs/common";
|
|
3
|
+
import {
|
|
5
4
|
MovementStrategy,
|
|
6
5
|
LinearMove,
|
|
7
6
|
Dash,
|
|
@@ -13,7 +12,6 @@ import {
|
|
|
13
12
|
LinearRepulsion,
|
|
14
13
|
IceMovement,
|
|
15
14
|
ProjectileMovement,
|
|
16
|
-
ProjectileType,
|
|
17
15
|
random,
|
|
18
16
|
isFunction,
|
|
19
17
|
capitalize
|
|
@@ -34,31 +32,10 @@ interface PlayerWithMixins extends RpgCommonPlayer {
|
|
|
34
32
|
changeDirection: (direction: Direction) => boolean;
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
export interface IMoveManager {
|
|
38
|
-
addMovement(strategy: MovementStrategy): void;
|
|
39
|
-
removeMovement(strategy: MovementStrategy): boolean;
|
|
40
|
-
clearMovements(): void;
|
|
41
|
-
hasActiveMovements(): boolean;
|
|
42
|
-
getActiveMovements(): MovementStrategy[];
|
|
43
|
-
|
|
44
|
-
moveTo(target: RpgCommonPlayer | { x: number, y: number }): void;
|
|
45
|
-
stopMoveTo(): void;
|
|
46
|
-
dash(direction: { x: number, y: number }, speed?: number, duration?: number): void;
|
|
47
|
-
knockback(direction: { x: number, y: number }, force?: number, duration?: number): void;
|
|
48
|
-
followPath(waypoints: Array<{ x: number, y: number }>, speed?: number, loop?: boolean): void;
|
|
49
|
-
oscillate(direction: { x: number, y: number }, amplitude?: number, period?: number): void;
|
|
50
|
-
applyIceMovement(direction: { x: number, y: number }, maxSpeed?: number): void;
|
|
51
|
-
shootProjectile(type: ProjectileType, direction: { x: number, y: number }, speed?: number): void;
|
|
52
|
-
moveRoutes(routes: Routes): Promise<boolean>;
|
|
53
|
-
infiniteMoveRoute(routes: Routes): void;
|
|
54
|
-
breakRoutes(force?: boolean): void;
|
|
55
|
-
replayRoutes(): void;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
35
|
|
|
59
36
|
function wait(sec: number) {
|
|
60
37
|
return new Promise((resolve) => {
|
|
61
|
-
|
|
38
|
+
setTimeout(resolve, sec * 1000)
|
|
62
39
|
})
|
|
63
40
|
}
|
|
64
41
|
|
|
@@ -116,297 +93,297 @@ export enum Speed {
|
|
|
116
93
|
class MoveList {
|
|
117
94
|
|
|
118
95
|
repeatMove(direction: Direction, repeat: number): Direction[] {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
96
|
+
// Safety check for valid repeat value
|
|
97
|
+
if (!Number.isFinite(repeat) || repeat < 0 || repeat > 10000) {
|
|
98
|
+
console.warn('Invalid repeat value:', repeat, 'using default value 1');
|
|
99
|
+
repeat = 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Ensure repeat is an integer
|
|
103
|
+
repeat = Math.floor(repeat);
|
|
104
|
+
|
|
105
|
+
// Additional safety check - ensure repeat is a safe integer
|
|
106
|
+
if (repeat < 0 || repeat > Number.MAX_SAFE_INTEGER || !Number.isSafeInteger(repeat)) {
|
|
107
|
+
console.warn('Unsafe repeat value:', repeat, 'using default value 1');
|
|
108
|
+
repeat = 1;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
return new Array(repeat).fill(direction);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error('Error creating array with repeat:', repeat, error);
|
|
115
|
+
return [direction]; // Return single direction as fallback
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private repeatTileMove(direction: string, repeat: number, propMap: string): CallbackTileMove {
|
|
120
|
+
return (player: RpgPlayer, map): Direction[] => {
|
|
121
|
+
const playerSpeed = typeof player.speed === 'function' ? player.speed() : player.speed;
|
|
122
|
+
|
|
123
|
+
// Safety checks
|
|
124
|
+
if (!playerSpeed || playerSpeed <= 0) {
|
|
125
|
+
console.warn('Invalid player speed:', playerSpeed, 'using default speed 3');
|
|
126
|
+
return this[direction](repeat);
|
|
123
127
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
repeat = 1;
|
|
128
|
+
|
|
129
|
+
const repeatTile = Math.floor((map[propMap] || 32) / playerSpeed) * repeat;
|
|
130
|
+
|
|
131
|
+
// Additional safety check for the calculated repeat value
|
|
132
|
+
if (!Number.isFinite(repeatTile) || repeatTile < 0 || repeatTile > 10000) {
|
|
133
|
+
console.warn('Calculated repeatTile is invalid:', repeatTile, 'using original repeat:', repeat);
|
|
134
|
+
return this[direction](repeat);
|
|
132
135
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return [direction]; // Return single direction as fallback
|
|
136
|
+
|
|
137
|
+
// Final safety check before calling the method
|
|
138
|
+
if (!Number.isSafeInteger(repeatTile)) {
|
|
139
|
+
console.warn('repeatTile is not a safe integer:', repeatTile, 'using original repeat:', repeat);
|
|
140
|
+
return this[direction](repeat);
|
|
139
141
|
}
|
|
140
|
-
}
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (!playerSpeed || playerSpeed <= 0) {
|
|
148
|
-
console.warn('Invalid player speed:', playerSpeed, 'using default speed 3');
|
|
149
|
-
return this[direction](repeat);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const repeatTile = Math.floor((map[propMap] || 32) / playerSpeed) * repeat;
|
|
153
|
-
|
|
154
|
-
// Additional safety check for the calculated repeat value
|
|
155
|
-
if (!Number.isFinite(repeatTile) || repeatTile < 0 || repeatTile > 10000) {
|
|
156
|
-
console.warn('Calculated repeatTile is invalid:', repeatTile, 'using original repeat:', repeat);
|
|
157
|
-
return this[direction](repeat);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Final safety check before calling the method
|
|
161
|
-
if (!Number.isSafeInteger(repeatTile)) {
|
|
162
|
-
console.warn('repeatTile is not a safe integer:', repeatTile, 'using original repeat:', repeat);
|
|
163
|
-
return this[direction](repeat);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
return this[direction](repeatTile);
|
|
168
|
-
} catch (error) {
|
|
169
|
-
console.error('Error calling direction method with repeatTile:', repeatTile, error);
|
|
170
|
-
return this[direction](repeat); // Fallback to original repeat
|
|
171
|
-
}
|
|
143
|
+
try {
|
|
144
|
+
return this[direction](repeatTile);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('Error calling direction method with repeatTile:', repeatTile, error);
|
|
147
|
+
return this[direction](repeat); // Fallback to original repeat
|
|
172
148
|
}
|
|
149
|
+
}
|
|
173
150
|
}
|
|
174
151
|
|
|
175
152
|
right(repeat: number = 1): Direction[] {
|
|
176
|
-
|
|
153
|
+
return this.repeatMove(Direction.Right, repeat)
|
|
177
154
|
}
|
|
178
155
|
|
|
179
156
|
left(repeat: number = 1): Direction[] {
|
|
180
|
-
|
|
157
|
+
return this.repeatMove(Direction.Left, repeat)
|
|
181
158
|
}
|
|
182
159
|
|
|
183
160
|
up(repeat: number = 1): Direction[] {
|
|
184
|
-
|
|
161
|
+
return this.repeatMove(Direction.Up, repeat)
|
|
185
162
|
}
|
|
186
163
|
|
|
187
164
|
down(repeat: number = 1): Direction[] {
|
|
188
|
-
|
|
165
|
+
return this.repeatMove(Direction.Down, repeat)
|
|
189
166
|
}
|
|
190
167
|
|
|
191
168
|
wait(sec: number): Promise<unknown> {
|
|
192
|
-
|
|
169
|
+
return wait(sec)
|
|
193
170
|
}
|
|
194
171
|
|
|
195
172
|
random(repeat: number = 1): Direction[] {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
173
|
+
// Safety check for valid repeat value
|
|
174
|
+
if (!Number.isFinite(repeat) || repeat < 0 || repeat > 10000) {
|
|
175
|
+
console.warn('Invalid repeat value in random:', repeat, 'using default value 1');
|
|
176
|
+
repeat = 1;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Ensure repeat is an integer
|
|
180
|
+
repeat = Math.floor(repeat);
|
|
181
|
+
|
|
182
|
+
// Additional safety check - ensure repeat is a safe integer
|
|
183
|
+
if (repeat < 0 || repeat > Number.MAX_SAFE_INTEGER || !Number.isSafeInteger(repeat)) {
|
|
184
|
+
console.warn('Unsafe repeat value in random:', repeat, 'using default value 1');
|
|
185
|
+
repeat = 1;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
return new Array(repeat).fill(null).map(() => [
|
|
190
|
+
Direction.Right,
|
|
191
|
+
Direction.Left,
|
|
192
|
+
Direction.Up,
|
|
193
|
+
Direction.Down
|
|
194
|
+
][random(0, 3)]);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error('Error creating random array with repeat:', repeat, error);
|
|
197
|
+
return [Direction.Down]; // Return single direction as fallback
|
|
198
|
+
}
|
|
222
199
|
}
|
|
223
200
|
|
|
224
201
|
tileRight(repeat: number = 1): CallbackTileMove {
|
|
225
|
-
|
|
202
|
+
return this.repeatTileMove('right', repeat, 'tileWidth')
|
|
226
203
|
}
|
|
227
204
|
|
|
228
205
|
tileLeft(repeat: number = 1): CallbackTileMove {
|
|
229
|
-
|
|
206
|
+
return this.repeatTileMove('left', repeat, 'tileWidth')
|
|
230
207
|
}
|
|
231
208
|
|
|
232
209
|
tileUp(repeat: number = 1): CallbackTileMove {
|
|
233
|
-
|
|
210
|
+
return this.repeatTileMove('up', repeat, 'tileHeight')
|
|
234
211
|
}
|
|
235
212
|
|
|
236
213
|
tileDown(repeat: number = 1): CallbackTileMove {
|
|
237
|
-
|
|
214
|
+
return this.repeatTileMove('down', repeat, 'tileHeight')
|
|
238
215
|
}
|
|
239
216
|
|
|
240
217
|
tileRandom(repeat: number = 1): CallbackTileMove {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
} catch (error) {
|
|
266
|
-
console.warn('Error in tileRandom iteration:', error);
|
|
267
|
-
// Continue with next iteration instead of breaking
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Safety check to prevent excessive array growth
|
|
271
|
-
if (directions.length > 10000) {
|
|
272
|
-
console.warn('tileRandom generated too many directions, truncating');
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
218
|
+
return (player: RpgPlayer, map): Direction[] => {
|
|
219
|
+
// Safety check for valid repeat value
|
|
220
|
+
if (!Number.isFinite(repeat) || repeat < 0 || repeat > 1000) {
|
|
221
|
+
console.warn('Invalid repeat value in tileRandom:', repeat, 'using default value 1');
|
|
222
|
+
repeat = 1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Ensure repeat is an integer
|
|
226
|
+
repeat = Math.floor(repeat);
|
|
227
|
+
|
|
228
|
+
let directions: Direction[] = []
|
|
229
|
+
for (let i = 0; i < repeat; i++) {
|
|
230
|
+
const randFn: CallbackTileMove = [
|
|
231
|
+
this.tileRight(),
|
|
232
|
+
this.tileLeft(),
|
|
233
|
+
this.tileUp(),
|
|
234
|
+
this.tileDown()
|
|
235
|
+
][random(0, 3)]
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
const newDirections = randFn(player, map);
|
|
239
|
+
if (Array.isArray(newDirections)) {
|
|
240
|
+
directions = [...directions, ...newDirections];
|
|
275
241
|
}
|
|
276
|
-
|
|
242
|
+
} catch (error) {
|
|
243
|
+
console.warn('Error in tileRandom iteration:', error);
|
|
244
|
+
// Continue with next iteration instead of breaking
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Safety check to prevent excessive array growth
|
|
248
|
+
if (directions.length > 10000) {
|
|
249
|
+
console.warn('tileRandom generated too many directions, truncating');
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
277
252
|
}
|
|
253
|
+
return directions
|
|
254
|
+
}
|
|
278
255
|
}
|
|
279
256
|
|
|
280
257
|
private _awayFromPlayerDirection(player: RpgPlayer, otherPlayer: RpgPlayer): Direction {
|
|
281
|
-
|
|
282
|
-
|
|
258
|
+
const directionOtherPlayer = otherPlayer.getDirection()
|
|
259
|
+
let newDirection: Direction = Direction.Down
|
|
283
260
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
261
|
+
switch (directionOtherPlayer) {
|
|
262
|
+
case Direction.Left:
|
|
263
|
+
case Direction.Right:
|
|
264
|
+
if (otherPlayer.x() > player.x()) {
|
|
265
|
+
newDirection = Direction.Left
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
newDirection = Direction.Right
|
|
269
|
+
}
|
|
270
|
+
break
|
|
271
|
+
case Direction.Up:
|
|
272
|
+
case Direction.Down:
|
|
273
|
+
if (otherPlayer.y() > player.y()) {
|
|
274
|
+
newDirection = Direction.Up
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
newDirection = Direction.Down
|
|
278
|
+
}
|
|
279
|
+
break
|
|
280
|
+
}
|
|
281
|
+
return newDirection
|
|
305
282
|
}
|
|
306
283
|
|
|
307
284
|
private _towardPlayerDirection(player: RpgPlayer, otherPlayer: RpgPlayer): Direction {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
285
|
+
const directionOtherPlayer = otherPlayer.getDirection()
|
|
286
|
+
let newDirection: Direction = Direction.Down
|
|
287
|
+
|
|
288
|
+
switch (directionOtherPlayer) {
|
|
289
|
+
case Direction.Left:
|
|
290
|
+
case Direction.Right:
|
|
291
|
+
if (otherPlayer.x() > player.x()) {
|
|
292
|
+
newDirection = Direction.Right
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
newDirection = Direction.Left
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
case Direction.Up:
|
|
299
|
+
case Direction.Down:
|
|
300
|
+
if (otherPlayer.y() > player.y()) {
|
|
301
|
+
newDirection = Direction.Down
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
newDirection = Direction.Up
|
|
305
|
+
}
|
|
306
|
+
break
|
|
307
|
+
}
|
|
308
|
+
return newDirection
|
|
332
309
|
}
|
|
333
310
|
|
|
334
311
|
private _awayFromPlayer({ isTile, typeMov }: { isTile: boolean, typeMov: string }, otherPlayer: RpgPlayer, repeat: number = 1) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
312
|
+
const method = (dir: Direction) => {
|
|
313
|
+
const direction: string = DirectionNames[dir as any] || 'down'
|
|
314
|
+
return this[isTile ? 'tile' + capitalize(direction) : direction](repeat)
|
|
315
|
+
}
|
|
316
|
+
return (player: RpgPlayer, map) => {
|
|
317
|
+
let newDirection: Direction = Direction.Down
|
|
318
|
+
switch (typeMov) {
|
|
319
|
+
case 'away':
|
|
320
|
+
newDirection = this._awayFromPlayerDirection(player, otherPlayer)
|
|
321
|
+
break;
|
|
322
|
+
case 'toward':
|
|
323
|
+
newDirection = this._towardPlayerDirection(player, otherPlayer)
|
|
324
|
+
break
|
|
338
325
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
case 'away':
|
|
343
|
-
newDirection = this._awayFromPlayerDirection(player, otherPlayer)
|
|
344
|
-
break;
|
|
345
|
-
case 'toward':
|
|
346
|
-
newDirection = this._towardPlayerDirection(player, otherPlayer)
|
|
347
|
-
break
|
|
348
|
-
}
|
|
349
|
-
let direction: any = method(newDirection)
|
|
350
|
-
if (isFunction(direction)) {
|
|
351
|
-
direction = direction(player, map)
|
|
352
|
-
}
|
|
353
|
-
return direction
|
|
326
|
+
let direction: any = method(newDirection)
|
|
327
|
+
if (isFunction(direction)) {
|
|
328
|
+
direction = direction(player, map)
|
|
354
329
|
}
|
|
330
|
+
return direction
|
|
331
|
+
}
|
|
355
332
|
}
|
|
356
333
|
|
|
357
334
|
towardPlayer(player: RpgPlayer, repeat: number = 1) {
|
|
358
|
-
|
|
335
|
+
return this._awayFromPlayer({ isTile: false, typeMov: 'toward' }, player, repeat)
|
|
359
336
|
}
|
|
360
337
|
|
|
361
338
|
tileTowardPlayer(player: RpgPlayer, repeat: number = 1) {
|
|
362
|
-
|
|
339
|
+
return this._awayFromPlayer({ isTile: true, typeMov: 'toward' }, player, repeat)
|
|
363
340
|
}
|
|
364
341
|
|
|
365
342
|
awayFromPlayer(player: RpgPlayer, repeat: number = 1): CallbackTileMove {
|
|
366
|
-
|
|
343
|
+
return this._awayFromPlayer({ isTile: false, typeMov: 'away' }, player, repeat)
|
|
367
344
|
}
|
|
368
345
|
|
|
369
346
|
tileAwayFromPlayer(player: RpgPlayer, repeat: number = 1): CallbackTileMove {
|
|
370
|
-
|
|
347
|
+
return this._awayFromPlayer({ isTile: true, typeMov: 'away' }, player, repeat)
|
|
371
348
|
}
|
|
372
349
|
|
|
373
350
|
turnLeft(): string {
|
|
374
|
-
|
|
351
|
+
return 'turn-' + Direction.Left
|
|
375
352
|
}
|
|
376
353
|
|
|
377
354
|
turnRight(): string {
|
|
378
|
-
|
|
355
|
+
return 'turn-' + Direction.Right
|
|
379
356
|
}
|
|
380
357
|
|
|
381
358
|
turnUp(): string {
|
|
382
|
-
|
|
359
|
+
return 'turn-' + Direction.Up
|
|
383
360
|
}
|
|
384
361
|
|
|
385
362
|
turnDown(): string {
|
|
386
|
-
|
|
363
|
+
return 'turn-' + Direction.Down
|
|
387
364
|
}
|
|
388
365
|
|
|
389
366
|
turnRandom(): string {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
367
|
+
return [
|
|
368
|
+
this.turnRight(),
|
|
369
|
+
this.turnLeft(),
|
|
370
|
+
this.turnUp(),
|
|
371
|
+
this.turnDown()
|
|
372
|
+
][random(0, 3)]
|
|
396
373
|
}
|
|
397
374
|
|
|
398
375
|
turnAwayFromPlayer(otherPlayer: RpgPlayer): CallbackTurnMove {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
376
|
+
return (player: RpgPlayer) => {
|
|
377
|
+
const direction = this._awayFromPlayerDirection(player, otherPlayer)
|
|
378
|
+
return 'turn-' + direction
|
|
379
|
+
}
|
|
403
380
|
}
|
|
404
381
|
|
|
405
382
|
turnTowardPlayer(otherPlayer: RpgPlayer): CallbackTurnMove {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
383
|
+
return (player: RpgPlayer) => {
|
|
384
|
+
const direction = this._towardPlayerDirection(player, otherPlayer)
|
|
385
|
+
return 'turn-' + direction
|
|
386
|
+
}
|
|
410
387
|
}
|
|
411
388
|
}
|
|
412
389
|
|
|
@@ -431,7 +408,7 @@ export const Move = new MoveList();
|
|
|
431
408
|
* - **Strategy Management**: Add, remove, and query movement strategies
|
|
432
409
|
* - **Predefined Movements**: Quick access to common movement patterns
|
|
433
410
|
* - **Composite Movements**: Combine multiple strategies
|
|
434
|
-
* - **Physics Integration**: Seamless integration with
|
|
411
|
+
* - **Physics Integration**: Seamless integration with the deterministic @rpgjs/physic engine
|
|
435
412
|
*
|
|
436
413
|
* ## Available Movement Strategies
|
|
437
414
|
* - `LinearMove`: Constant velocity movement
|
|
@@ -475,15 +452,49 @@ export const Move = new MoveList();
|
|
|
475
452
|
* }
|
|
476
453
|
* ```
|
|
477
454
|
*/
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
455
|
+
/**
|
|
456
|
+
* Move Manager Mixin
|
|
457
|
+
*
|
|
458
|
+
* Provides comprehensive movement management capabilities to any class. This mixin handles
|
|
459
|
+
* various types of movement including pathfinding, physics-based movement, route following,
|
|
460
|
+
* and advanced movement strategies like dashing, knockback, and projectile movement.
|
|
461
|
+
*
|
|
462
|
+
* @param Base - The base class to extend with movement management
|
|
463
|
+
* @returns Extended class with movement management methods
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* class MyPlayer extends WithMoveManager(BasePlayer) {
|
|
468
|
+
* constructor() {
|
|
469
|
+
* super();
|
|
470
|
+
* this.frequency = Frequency.High;
|
|
471
|
+
* }
|
|
472
|
+
* }
|
|
473
|
+
*
|
|
474
|
+
* const player = new MyPlayer();
|
|
475
|
+
* player.moveTo({ x: 100, y: 100 });
|
|
476
|
+
* player.dash({ x: 1, y: 0 }, 8, 200);
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
export function WithMoveManager<TBase extends PlayerCtor>(Base: TBase) {
|
|
480
|
+
const baseProto = Base.prototype as any;
|
|
481
|
+
class WithMoveManagerClass extends Base {
|
|
482
|
+
setAnimation(animationName: string, nbTimes: number): void {
|
|
483
|
+
if (typeof baseProto.setAnimation === 'function') {
|
|
484
|
+
baseProto.setAnimation.call(this, animationName, nbTimes);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
showComponentAnimation(id: string, params: any): void {
|
|
489
|
+
if (typeof baseProto.showComponentAnimation === 'function') {
|
|
490
|
+
baseProto.showComponentAnimation.call(this, id, params);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Properties for infinite route management
|
|
495
|
+
_infiniteRoutes: Routes | null = null;
|
|
496
|
+
_finishRoute: ((value: boolean) => void) | null = null;
|
|
497
|
+
_isInfiniteRouteActive: boolean = false;
|
|
487
498
|
|
|
488
499
|
/**
|
|
489
500
|
* The player passes through the other players (or vice versa). But the player does not go through the events.
|
|
@@ -520,7 +531,7 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
520
531
|
set through(value: boolean) {
|
|
521
532
|
this._through.set(value);
|
|
522
533
|
}
|
|
523
|
-
|
|
534
|
+
|
|
524
535
|
get through(): boolean {
|
|
525
536
|
return this._through();
|
|
526
537
|
}
|
|
@@ -561,7 +572,7 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
561
572
|
get frequency(): number {
|
|
562
573
|
return this._frequency();
|
|
563
574
|
}
|
|
564
|
-
|
|
575
|
+
|
|
565
576
|
/**
|
|
566
577
|
* Add a custom movement strategy to this entity
|
|
567
578
|
*
|
|
@@ -582,9 +593,9 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
582
593
|
* ```
|
|
583
594
|
*/
|
|
584
595
|
addMovement(strategy: MovementStrategy): void {
|
|
585
|
-
const map = (this as unknown as PlayerWithMixins).getCurrentMap();
|
|
596
|
+
const map = (this as unknown as PlayerWithMixins).getCurrentMap() as any;
|
|
586
597
|
if (!map) return;
|
|
587
|
-
|
|
598
|
+
|
|
588
599
|
map.moveManager.add((this as unknown as PlayerWithMixins).id, strategy);
|
|
589
600
|
}
|
|
590
601
|
|
|
@@ -605,9 +616,9 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
605
616
|
* ```
|
|
606
617
|
*/
|
|
607
618
|
removeMovement(strategy: MovementStrategy): boolean {
|
|
608
|
-
const map = (this as unknown as PlayerWithMixins).getCurrentMap();
|
|
619
|
+
const map = (this as unknown as PlayerWithMixins).getCurrentMap() as any;
|
|
609
620
|
if (!map) return false;
|
|
610
|
-
|
|
621
|
+
|
|
611
622
|
return map.moveManager.remove((this as unknown as PlayerWithMixins).id, strategy);
|
|
612
623
|
}
|
|
613
624
|
|
|
@@ -627,9 +638,9 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
627
638
|
* ```
|
|
628
639
|
*/
|
|
629
640
|
clearMovements(): void {
|
|
630
|
-
const map = (this as unknown as PlayerWithMixins).getCurrentMap();
|
|
641
|
+
const map = (this as unknown as PlayerWithMixins).getCurrentMap() as any;
|
|
631
642
|
if (!map) return;
|
|
632
|
-
|
|
643
|
+
|
|
633
644
|
map.moveManager.clear((this as unknown as PlayerWithMixins).id);
|
|
634
645
|
}
|
|
635
646
|
|
|
@@ -652,9 +663,9 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
652
663
|
* ```
|
|
653
664
|
*/
|
|
654
665
|
hasActiveMovements(): boolean {
|
|
655
|
-
const map = (this as unknown as PlayerWithMixins).getCurrentMap();
|
|
666
|
+
const map = (this as unknown as PlayerWithMixins).getCurrentMap() as any;
|
|
656
667
|
if (!map) return false;
|
|
657
|
-
|
|
668
|
+
|
|
658
669
|
return map.moveManager.hasActiveStrategies((this as unknown as PlayerWithMixins).id);
|
|
659
670
|
}
|
|
660
671
|
|
|
@@ -674,9 +685,9 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
674
685
|
* ```
|
|
675
686
|
*/
|
|
676
687
|
getActiveMovements(): MovementStrategy[] {
|
|
677
|
-
const map = (this as unknown as PlayerWithMixins).getCurrentMap();
|
|
688
|
+
const map = (this as unknown as PlayerWithMixins).getCurrentMap() as any;
|
|
678
689
|
if (!map) return [];
|
|
679
|
-
|
|
690
|
+
|
|
680
691
|
return map.moveManager.getStrategies((this as unknown as PlayerWithMixins).id);
|
|
681
692
|
}
|
|
682
693
|
|
|
@@ -702,30 +713,30 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
702
713
|
* ```
|
|
703
714
|
*/
|
|
704
715
|
moveTo(target: RpgCommonPlayer | { x: number, y: number }): void {
|
|
705
|
-
const map = (this as unknown as PlayerWithMixins).getCurrentMap();
|
|
716
|
+
const map = (this as unknown as PlayerWithMixins).getCurrentMap() as any;
|
|
706
717
|
if (!map) return;
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
718
|
+
|
|
719
|
+
const engine = map.physic;
|
|
720
|
+
|
|
710
721
|
if ('id' in target) {
|
|
711
|
-
|
|
712
|
-
targetBody = map.physic.getBody(target.id);
|
|
713
|
-
} else {
|
|
714
|
-
// Target is a position - create a temporary target function
|
|
715
|
-
const getTargetPos = () => Matter.Vector.create(target.x, target.y);
|
|
722
|
+
const targetProvider = () => (map as any).getBody(target.id) ?? null;
|
|
716
723
|
map.moveManager.add(
|
|
717
|
-
(this as unknown as PlayerWithMixins).id,
|
|
718
|
-
new SeekAvoid(
|
|
724
|
+
(this as unknown as PlayerWithMixins).id,
|
|
725
|
+
new SeekAvoid(engine, targetProvider, 180, 140, 80, 48)
|
|
719
726
|
);
|
|
720
727
|
return;
|
|
721
728
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
+
|
|
730
|
+
const staticTarget = new Entity({
|
|
731
|
+
position: { x: target.x, y: target.y },
|
|
732
|
+
mass: Infinity,
|
|
733
|
+
});
|
|
734
|
+
staticTarget.freeze();
|
|
735
|
+
|
|
736
|
+
map.moveManager.add(
|
|
737
|
+
(this as unknown as PlayerWithMixins).id,
|
|
738
|
+
new SeekAvoid(engine, () => staticTarget, 80, 140, 80, 48)
|
|
739
|
+
);
|
|
729
740
|
}
|
|
730
741
|
|
|
731
742
|
/**
|
|
@@ -745,9 +756,9 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
745
756
|
* ```
|
|
746
757
|
*/
|
|
747
758
|
stopMoveTo(): void {
|
|
748
|
-
const map = (this as unknown as PlayerWithMixins).getCurrentMap();
|
|
759
|
+
const map = (this as unknown as PlayerWithMixins).getCurrentMap() as any;
|
|
749
760
|
if (!map) return;
|
|
750
|
-
|
|
761
|
+
|
|
751
762
|
const strategies = this.getActiveMovements();
|
|
752
763
|
strategies.forEach(strategy => {
|
|
753
764
|
if (strategy instanceof SeekAvoid || strategy instanceof LinearRepulsion) {
|
|
@@ -912,7 +923,7 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
912
923
|
maxBounces: type === ProjectileType.Bounce ? 3 : undefined,
|
|
913
924
|
bounciness: type === ProjectileType.Bounce ? 0.6 : undefined
|
|
914
925
|
};
|
|
915
|
-
|
|
926
|
+
|
|
916
927
|
this.addMovement(new ProjectileMovement(type, config));
|
|
917
928
|
}
|
|
918
929
|
|
|
@@ -963,18 +974,18 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
963
974
|
let count = 0;
|
|
964
975
|
let frequence = 0;
|
|
965
976
|
const player = this as unknown as PlayerWithMixins;
|
|
966
|
-
|
|
977
|
+
|
|
967
978
|
// Break any existing route movement
|
|
968
979
|
this.clearMovements();
|
|
969
|
-
|
|
980
|
+
|
|
970
981
|
return new Promise(async (resolve) => {
|
|
971
982
|
// Store the resolve function for potential breaking
|
|
972
983
|
this._finishRoute = resolve;
|
|
973
|
-
|
|
984
|
+
|
|
974
985
|
// Process function routes first
|
|
975
986
|
const processedRoutes = routes.map((route: any) => {
|
|
976
987
|
if (typeof route === 'function') {
|
|
977
|
-
const map = player.getCurrentMap();
|
|
988
|
+
const map = player.getCurrentMap() as any;
|
|
978
989
|
if (!map) {
|
|
979
990
|
return undefined;
|
|
980
991
|
}
|
|
@@ -982,11 +993,11 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
982
993
|
}
|
|
983
994
|
return route;
|
|
984
995
|
});
|
|
985
|
-
|
|
996
|
+
|
|
986
997
|
// Flatten nested arrays
|
|
987
998
|
const flatRoutes = this.flattenRoutes(processedRoutes);
|
|
988
999
|
let routeIndex = 0;
|
|
989
|
-
|
|
1000
|
+
|
|
990
1001
|
const executeNextRoute = async (): Promise<void> => {
|
|
991
1002
|
// Check if player still exists and is on a map
|
|
992
1003
|
if (!player || !player.getCurrentMap()) {
|
|
@@ -994,7 +1005,7 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
994
1005
|
resolve(false);
|
|
995
1006
|
return;
|
|
996
1007
|
}
|
|
997
|
-
|
|
1008
|
+
|
|
998
1009
|
// Handle frequency timing
|
|
999
1010
|
if (count >= (player.nbPixelInTile || 32)) {
|
|
1000
1011
|
if (frequence < (player.frequency || 0)) {
|
|
@@ -1003,25 +1014,25 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1003
1014
|
return;
|
|
1004
1015
|
}
|
|
1005
1016
|
}
|
|
1006
|
-
|
|
1017
|
+
|
|
1007
1018
|
frequence = 0;
|
|
1008
1019
|
count++;
|
|
1009
|
-
|
|
1020
|
+
|
|
1010
1021
|
// Check if we've completed all routes
|
|
1011
1022
|
if (routeIndex >= flatRoutes.length) {
|
|
1012
1023
|
this._finishRoute = null;
|
|
1013
1024
|
resolve(true);
|
|
1014
1025
|
return;
|
|
1015
1026
|
}
|
|
1016
|
-
|
|
1027
|
+
|
|
1017
1028
|
const currentRoute = flatRoutes[routeIndex];
|
|
1018
1029
|
routeIndex++;
|
|
1019
|
-
|
|
1030
|
+
|
|
1020
1031
|
if (currentRoute === undefined) {
|
|
1021
1032
|
executeNextRoute();
|
|
1022
1033
|
return;
|
|
1023
1034
|
}
|
|
1024
|
-
|
|
1035
|
+
|
|
1025
1036
|
try {
|
|
1026
1037
|
// Handle different route types
|
|
1027
1038
|
if (typeof currentRoute === 'object' && 'then' in currentRoute) {
|
|
@@ -1032,7 +1043,7 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1032
1043
|
// Handle turn commands
|
|
1033
1044
|
const directionStr = currentRoute.replace('turn-', '');
|
|
1034
1045
|
let direction: Direction = Direction.Down;
|
|
1035
|
-
|
|
1046
|
+
|
|
1036
1047
|
// Convert string direction to Direction enum
|
|
1037
1048
|
switch (directionStr) {
|
|
1038
1049
|
case 'up':
|
|
@@ -1052,7 +1063,7 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1052
1063
|
direction = Direction.Right;
|
|
1053
1064
|
break;
|
|
1054
1065
|
}
|
|
1055
|
-
|
|
1066
|
+
|
|
1056
1067
|
if (player.changeDirection) {
|
|
1057
1068
|
player.changeDirection(direction);
|
|
1058
1069
|
}
|
|
@@ -1071,7 +1082,8 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1071
1082
|
case Direction.Down: vy = 1; break;
|
|
1072
1083
|
case Direction.Up: vy = -1; break;
|
|
1073
1084
|
}
|
|
1074
|
-
|
|
1085
|
+
const speed = player.speed?.() ?? 3;
|
|
1086
|
+
this.addMovement(new LinearMove({ x: vx * speed, y: vy * speed }, 0.1));
|
|
1075
1087
|
setTimeout(executeNextRoute, 100);
|
|
1076
1088
|
return;
|
|
1077
1089
|
}
|
|
@@ -1085,11 +1097,11 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1085
1097
|
executeNextRoute();
|
|
1086
1098
|
}
|
|
1087
1099
|
};
|
|
1088
|
-
|
|
1100
|
+
|
|
1089
1101
|
executeNextRoute();
|
|
1090
1102
|
});
|
|
1091
1103
|
}
|
|
1092
|
-
|
|
1104
|
+
|
|
1093
1105
|
/**
|
|
1094
1106
|
* Utility method to flatten nested route arrays
|
|
1095
1107
|
*
|
|
@@ -1097,18 +1109,13 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1097
1109
|
* @param routes - Routes array that may contain nested arrays
|
|
1098
1110
|
* @returns Flattened array of routes
|
|
1099
1111
|
*/
|
|
1100
|
-
private flattenRoutes(routes:
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
if (Array.isArray(route)) {
|
|
1105
|
-
result.push(...this.flattenRoutes(route));
|
|
1106
|
-
} else {
|
|
1107
|
-
result.push(route);
|
|
1112
|
+
private flattenRoutes(routes: Routes): Routes {
|
|
1113
|
+
return routes.reduce((acc: Routes, item) => {
|
|
1114
|
+
if (Array.isArray(item)) {
|
|
1115
|
+
return acc.concat(this.flattenRoutes(item));
|
|
1108
1116
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
return result;
|
|
1117
|
+
return acc.concat(item);
|
|
1118
|
+
}, []);
|
|
1112
1119
|
}
|
|
1113
1120
|
|
|
1114
1121
|
/**
|
|
@@ -1154,7 +1161,7 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1154
1161
|
|
|
1155
1162
|
const executeInfiniteRoute = (isBreaking: boolean = false) => {
|
|
1156
1163
|
if (isBreaking || !this._isInfiniteRouteActive) return;
|
|
1157
|
-
|
|
1164
|
+
|
|
1158
1165
|
this.moveRoutes(routes).then((completed) => {
|
|
1159
1166
|
// Only continue if the route completed successfully and we're still active
|
|
1160
1167
|
if (completed && this._isInfiniteRouteActive) {
|
|
@@ -1197,12 +1204,12 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1197
1204
|
*/
|
|
1198
1205
|
breakRoutes(force: boolean = false): void {
|
|
1199
1206
|
this._isInfiniteRouteActive = false;
|
|
1200
|
-
|
|
1207
|
+
|
|
1201
1208
|
if (force) {
|
|
1202
1209
|
// Force stop by clearing all movements immediately
|
|
1203
1210
|
this.clearMovements();
|
|
1204
1211
|
}
|
|
1205
|
-
|
|
1212
|
+
|
|
1206
1213
|
// If there's an active route promise, resolve it
|
|
1207
1214
|
if (this._finishRoute) {
|
|
1208
1215
|
this._finishRoute(force);
|
|
@@ -1241,5 +1248,13 @@ export function WithMoveManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
1241
1248
|
this.infiniteMoveRoute(this._infiniteRoutes);
|
|
1242
1249
|
}
|
|
1243
1250
|
}
|
|
1244
|
-
}
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
return WithMoveManagerClass as unknown as PlayerCtor;
|
|
1245
1254
|
}
|
|
1255
|
+
|
|
1256
|
+
/**
|
|
1257
|
+
* Type helper to extract the interface from the WithMoveManager mixin
|
|
1258
|
+
* This provides the type without duplicating method signatures
|
|
1259
|
+
*/
|
|
1260
|
+
export type IMoveManager = InstanceType<ReturnType<typeof WithMoveManager>>;
|