@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,8 +1,9 @@
|
|
|
1
|
-
import { isInstanceOf, isString, Item, type Constructor } from "@rpgjs/common";
|
|
1
|
+
import { isInstanceOf, isString, Item, PlayerCtor, type Constructor } from "@rpgjs/common";
|
|
2
2
|
import { RpgCommonPlayer, Matter } from "@rpgjs/common";
|
|
3
3
|
import { ATK, PDEF, SDEF } from "../presets";
|
|
4
4
|
import { ItemLog } from "../logs";
|
|
5
5
|
import { ArmorInstance, ItemClass, ItemInstance, WeaponInstance } from "@rpgjs/database";
|
|
6
|
+
import { RpgPlayer } from "./Player";
|
|
6
7
|
|
|
7
8
|
// Ajout des enums manquants
|
|
8
9
|
enum Effect {
|
|
@@ -13,27 +14,180 @@ enum ClassHooks {
|
|
|
13
14
|
canEquip = 'canEquip'
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
type Inventory = { nb: number; item: ItemInstance };
|
|
18
|
+
|
|
16
19
|
/**
|
|
17
|
-
* Interface defining
|
|
20
|
+
* Interface defining the hooks that can be implemented on item classes or objects
|
|
21
|
+
*
|
|
22
|
+
* These hooks are called at specific moments during the item lifecycle:
|
|
23
|
+
* - `onAdd`: When the item is added to the player's inventory
|
|
24
|
+
* - `onUse`: When the item is successfully used
|
|
25
|
+
* - `onUseFailed`: When the item usage fails (e.g., chance roll failed)
|
|
26
|
+
* - `onRemove`: When the item is removed from the inventory
|
|
27
|
+
* - `onEquip`: When the item is equipped or unequipped
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const itemHooks: ItemHooks = {
|
|
32
|
+
* onAdd(player) {
|
|
33
|
+
* console.log('Item added to inventory');
|
|
34
|
+
* },
|
|
35
|
+
* onUse(player) {
|
|
36
|
+
* player.hp += 100;
|
|
37
|
+
* }
|
|
38
|
+
* };
|
|
39
|
+
* ```
|
|
18
40
|
*/
|
|
19
|
-
export interface
|
|
20
|
-
|
|
41
|
+
export interface ItemHooks {
|
|
42
|
+
/**
|
|
43
|
+
* Called when the item is added to the player's inventory
|
|
44
|
+
*
|
|
45
|
+
* @param player - The player receiving the item
|
|
46
|
+
*/
|
|
47
|
+
onAdd?: (player: RpgPlayer) => void | Promise<void>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Called when the item is successfully used
|
|
51
|
+
*
|
|
52
|
+
* @param player - The player using the item
|
|
53
|
+
*/
|
|
54
|
+
onUse?: (player: RpgPlayer) => void | Promise<void>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Called when the item usage fails (e.g., chance roll failed)
|
|
58
|
+
*
|
|
59
|
+
* @param player - The player attempting to use the item
|
|
60
|
+
*/
|
|
61
|
+
onUseFailed?: (player: RpgPlayer) => void | Promise<void>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Called when the item is removed from the inventory
|
|
65
|
+
*
|
|
66
|
+
* @param player - The player losing the item
|
|
67
|
+
*/
|
|
68
|
+
onRemove?: (player: RpgPlayer) => void | Promise<void>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Called when the item is equipped or unequipped
|
|
72
|
+
*
|
|
73
|
+
* @param player - The player equipping/unequipping the item
|
|
74
|
+
* @param equip - true if equipping, false if unequipping
|
|
75
|
+
*/
|
|
76
|
+
onEquip?: (player: RpgPlayer, equip: boolean) => void | Promise<void>;
|
|
21
77
|
}
|
|
22
78
|
|
|
23
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Base properties that can be included in an item object
|
|
81
|
+
*
|
|
82
|
+
* This interface defines the common properties that items can have.
|
|
83
|
+
* Use this as a base and extend it with specific item types.
|
|
84
|
+
*
|
|
85
|
+
* @template T - Additional properties specific to the item type
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* interface PotionData extends ItemData {
|
|
90
|
+
* hpValue: number;
|
|
91
|
+
* mpValue: number;
|
|
92
|
+
* }
|
|
93
|
+
*
|
|
94
|
+
* const potion: ItemObject<PotionData> = {
|
|
95
|
+
* name: 'Health Potion',
|
|
96
|
+
* description: 'Restores 100 HP',
|
|
97
|
+
* price: 200,
|
|
98
|
+
* hpValue: 100,
|
|
99
|
+
* mpValue: 0,
|
|
100
|
+
* onUse(player) {
|
|
101
|
+
* player.hp += this.hpValue;
|
|
102
|
+
* }
|
|
103
|
+
* };
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export interface ItemData {
|
|
107
|
+
/** Item name */
|
|
108
|
+
name?: string;
|
|
109
|
+
/** Item description */
|
|
110
|
+
description?: string;
|
|
111
|
+
/** Item price */
|
|
112
|
+
price?: number;
|
|
113
|
+
/** HP value restored when used */
|
|
114
|
+
hpValue?: number;
|
|
115
|
+
/** MP/SP value restored when used */
|
|
116
|
+
mpValue?: number;
|
|
117
|
+
/** Chance to successfully use the item (0-1) */
|
|
118
|
+
hitRate?: number;
|
|
119
|
+
/** Whether the item is consumable */
|
|
120
|
+
consumable?: boolean;
|
|
121
|
+
/** States to add when used */
|
|
122
|
+
addStates?: any[];
|
|
123
|
+
/** States to remove when used */
|
|
124
|
+
removeStates?: any[];
|
|
125
|
+
/** Elemental properties */
|
|
126
|
+
elements?: any[];
|
|
127
|
+
/** Parameter modifiers */
|
|
128
|
+
paramsModifier?: Record<string, any>;
|
|
129
|
+
/** Item type (for equipment validation) */
|
|
130
|
+
_type?: 'item' | 'weapon' | 'armor';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Item object type that combines data properties with hooks
|
|
135
|
+
*
|
|
136
|
+
* This type allows you to create item objects directly without needing a class.
|
|
137
|
+
* The object can contain both item data properties and lifecycle hooks.
|
|
138
|
+
*
|
|
139
|
+
* @template T - Additional properties specific to the item type (extends ItemData)
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const potion: ItemObject = {
|
|
144
|
+
* name: 'Health Potion',
|
|
145
|
+
* description: 'Restores 100 HP',
|
|
146
|
+
* price: 200,
|
|
147
|
+
* hpValue: 100,
|
|
148
|
+
* consumable: true,
|
|
149
|
+
* onAdd(player) {
|
|
150
|
+
* console.log('Potion added!');
|
|
151
|
+
* },
|
|
152
|
+
* onUse(player) {
|
|
153
|
+
* player.hp += 100;
|
|
154
|
+
* }
|
|
155
|
+
* };
|
|
156
|
+
*
|
|
157
|
+
* player.addItem(potion);
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export type ItemObject<T extends ItemData = ItemData> = T & ItemHooks & {
|
|
161
|
+
/** Item identifier (required if not using class or string) */
|
|
162
|
+
id?: string;
|
|
163
|
+
};
|
|
24
164
|
|
|
25
165
|
/**
|
|
26
|
-
*
|
|
166
|
+
* Item Manager Mixin
|
|
27
167
|
*
|
|
28
|
-
*
|
|
168
|
+
* Provides comprehensive item management capabilities to any class. This mixin handles
|
|
169
|
+
* inventory management, item usage, equipment, buying/selling, and item effects.
|
|
170
|
+
* It manages the complete item system including restrictions, transactions, and equipment.
|
|
29
171
|
*
|
|
30
|
-
* @param Base - The base class to extend
|
|
31
|
-
* @returns
|
|
172
|
+
* @param Base - The base class to extend with item management
|
|
173
|
+
* @returns Extended class with item management methods
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* class MyPlayer extends WithItemManager(BasePlayer) {
|
|
178
|
+
* constructor() {
|
|
179
|
+
* super();
|
|
180
|
+
* // Item system is automatically initialized
|
|
181
|
+
* }
|
|
182
|
+
* }
|
|
183
|
+
*
|
|
184
|
+
* const player = new MyPlayer();
|
|
185
|
+
* player.addItem('potion', 5);
|
|
186
|
+
* player.useItem('potion');
|
|
187
|
+
* ```
|
|
32
188
|
*/
|
|
33
|
-
export function WithItemManager<TBase extends
|
|
34
|
-
Base
|
|
35
|
-
): Constructor<IItemManager> & TBase {
|
|
36
|
-
return class extends Base implements IItemManager {
|
|
189
|
+
export function WithItemManager<TBase extends PlayerCtor>(Base: TBase) {
|
|
190
|
+
return class extends Base {
|
|
37
191
|
|
|
38
192
|
/**
|
|
39
193
|
* Retrieves the information of an object: the number and the instance
|
|
@@ -54,7 +208,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
54
208
|
*/
|
|
55
209
|
getItem(itemClass: ItemClass | string): Item {
|
|
56
210
|
const index: number = this._getItemIndex(itemClass);
|
|
57
|
-
return this.items()[index];
|
|
211
|
+
return (this as any).items()[index];
|
|
58
212
|
}
|
|
59
213
|
|
|
60
214
|
/**
|
|
@@ -77,7 +231,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
77
231
|
}
|
|
78
232
|
|
|
79
233
|
_getItemIndex(itemClass: ItemClass | string): number {
|
|
80
|
-
return this.items().findIndex((it: Item): boolean => {
|
|
234
|
+
return (this as any).items().findIndex((it: Item): boolean => {
|
|
81
235
|
if (isString(itemClass)) {
|
|
82
236
|
return it.id() == itemClass;
|
|
83
237
|
}
|
|
@@ -87,34 +241,149 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
87
241
|
/**
|
|
88
242
|
* Add an item in the player's inventory. You can give more than one by specifying `nb`
|
|
89
243
|
*
|
|
90
|
-
*
|
|
244
|
+
* Supports three ways to add items:
|
|
245
|
+
* 1. **String**: Pass a string ID to retrieve the item from the database (requires item to be registered in `@RpgModule` database).
|
|
246
|
+
* 2. **Class**: Pass an item class (e.g., `Potion`). The class will be instantiated and automatically added to the map's database if not already present.
|
|
247
|
+
* 3. **Object**: Pass an item object with properties and hooks directly. The object will be automatically added to the map's database if not already present.
|
|
248
|
+
*
|
|
249
|
+
* For classes and objects, if they don't exist in the database, they are automatically added using `map.addInDatabase()`.
|
|
250
|
+
* This allows dynamic item creation without requiring pre-registration in the module database.
|
|
251
|
+
*
|
|
252
|
+
* `onAdd()` method is called on the ItemClass or ItemObject
|
|
91
253
|
*
|
|
92
254
|
* @title Add Item
|
|
93
255
|
* @method player.addItem(item,nb=1)
|
|
94
|
-
* @param {ItemClass}
|
|
256
|
+
* @param {ItemClass | ItemObject | string} item - Item class, object, or string identifier
|
|
95
257
|
* @param {number} [nb] Default 1
|
|
96
|
-
* @returns {
|
|
258
|
+
* @returns {Item} The item instance added to inventory
|
|
97
259
|
* @memberof ItemManager
|
|
98
260
|
* @example
|
|
99
261
|
*
|
|
100
262
|
* ```ts
|
|
101
263
|
* import Potion from 'your-database/potion'
|
|
264
|
+
*
|
|
265
|
+
* // Using string ID (retrieves from database - item must be in @RpgModule database)
|
|
266
|
+
* player.addItem('Potion', 5)
|
|
267
|
+
*
|
|
268
|
+
* // Using class (creates instance, auto-adds to map database if not present)
|
|
102
269
|
* player.addItem(Potion, 5)
|
|
270
|
+
*
|
|
271
|
+
* // Using object directly (auto-adds to map database if not present)
|
|
272
|
+
* player.addItem({
|
|
273
|
+
* id: 'custom-potion',
|
|
274
|
+
* name: 'Custom Potion',
|
|
275
|
+
* description: 'A custom potion',
|
|
276
|
+
* price: 150,
|
|
277
|
+
* hpValue: 50,
|
|
278
|
+
* consumable: true,
|
|
279
|
+
* onAdd(player) {
|
|
280
|
+
* console.log('Custom potion added!');
|
|
281
|
+
* },
|
|
282
|
+
* onUse(player) {
|
|
283
|
+
* player.hp += 50;
|
|
284
|
+
* }
|
|
285
|
+
* }, 3)
|
|
286
|
+
*
|
|
287
|
+
* // Object without ID (auto-generates ID and adds to database)
|
|
288
|
+
* player.addItem({
|
|
289
|
+
* name: 'Dynamic Item',
|
|
290
|
+
* price: 100,
|
|
291
|
+
* onUse(player) {
|
|
292
|
+
* console.log('Dynamic item used!');
|
|
293
|
+
* }
|
|
294
|
+
* })
|
|
103
295
|
* ```
|
|
104
296
|
*/
|
|
105
|
-
addItem(
|
|
106
|
-
const
|
|
107
|
-
|
|
297
|
+
addItem(item: ItemClass | ItemObject | string, nb: number = 1): Item {
|
|
298
|
+
const map = (this as any).getCurrentMap();
|
|
299
|
+
if (!map) {
|
|
300
|
+
throw new Error('Player must be on a map to add items');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
let itemId: string;
|
|
304
|
+
let data: any;
|
|
305
|
+
let itemInstance: any = null;
|
|
306
|
+
|
|
307
|
+
// Handle string: retrieve from database
|
|
308
|
+
if (isString(item)) {
|
|
309
|
+
itemId = item as string;
|
|
310
|
+
data = (this as any).databaseById(itemId);
|
|
311
|
+
if (!data) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
`The ID=${itemId} data is not found in the database. Add the data in the property "database"`
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// Handle class: create instance and add to database if needed
|
|
318
|
+
else if (typeof item === 'function' || (item as any).prototype) {
|
|
319
|
+
itemId = (item as any).name;
|
|
320
|
+
|
|
321
|
+
// Check if already in database
|
|
322
|
+
const existingData = map.database()[itemId];
|
|
323
|
+
if (existingData) {
|
|
324
|
+
// Use existing data from database
|
|
325
|
+
data = existingData;
|
|
326
|
+
} else {
|
|
327
|
+
// Add the class to the database (it will be retrieved later via databaseById)
|
|
328
|
+
map.addInDatabase(itemId, item as ItemClass);
|
|
329
|
+
// Use the class as data (it will be used to create Item instance)
|
|
330
|
+
data = item as ItemClass;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Create instance of the class for hooks
|
|
334
|
+
itemInstance = new (item as ItemClass)();
|
|
335
|
+
}
|
|
336
|
+
// Handle object: use directly and add to database if needed
|
|
337
|
+
else {
|
|
338
|
+
const itemObj = item as ItemObject;
|
|
339
|
+
itemId = itemObj.id || `item-${Date.now()}`;
|
|
340
|
+
|
|
341
|
+
// Check if already in database
|
|
342
|
+
const existingData = map.database()[itemId];
|
|
343
|
+
if (existingData) {
|
|
344
|
+
// Merge with existing data and force update
|
|
345
|
+
data = { ...existingData, ...itemObj };
|
|
346
|
+
// Update database with merged data (force overwrite)
|
|
347
|
+
map.addInDatabase(itemId, data, { force: true });
|
|
348
|
+
} else {
|
|
349
|
+
// Add the object to the database
|
|
350
|
+
map.addInDatabase(itemId, itemObj);
|
|
351
|
+
// Use object directly as data
|
|
352
|
+
data = itemObj;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
itemInstance = itemObj;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Find existing item in inventory
|
|
359
|
+
const existingItem = (this as any).items().find((it: Item) => it.id() == itemId);
|
|
108
360
|
let instance: Item;
|
|
109
|
-
|
|
110
|
-
|
|
361
|
+
|
|
362
|
+
if (existingItem) {
|
|
363
|
+
// Item already exists, just update quantity
|
|
364
|
+
instance = existingItem;
|
|
111
365
|
instance.quantity.update((it) => it + nb);
|
|
112
366
|
} else {
|
|
367
|
+
// Create new item instance
|
|
113
368
|
instance = new Item(data);
|
|
114
369
|
instance.id.set(itemId);
|
|
115
|
-
|
|
370
|
+
|
|
371
|
+
// Attach hooks from class instance or object
|
|
372
|
+
if (itemInstance) {
|
|
373
|
+
// Store the original instance for hook execution
|
|
374
|
+
(instance as any)._itemInstance = itemInstance;
|
|
375
|
+
|
|
376
|
+
// Attach onAdd hook directly for immediate use
|
|
377
|
+
if (itemInstance.onAdd) {
|
|
378
|
+
instance.onAdd = itemInstance.onAdd.bind(itemInstance);
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
(this as any).items().push(instance);
|
|
116
382
|
}
|
|
117
|
-
|
|
383
|
+
|
|
384
|
+
// Call onAdd hook - use stored instance if available
|
|
385
|
+
const hookTarget = (instance as any)._itemInstance || instance;
|
|
386
|
+
(this as any)["execMethod"]("onAdd", [this], hookTarget);
|
|
118
387
|
return instance;
|
|
119
388
|
}
|
|
120
389
|
|
|
@@ -165,7 +434,9 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
165
434
|
} else {
|
|
166
435
|
this.items()[itemIndex].quantity.update((it) => it - nb);
|
|
167
436
|
}
|
|
168
|
-
|
|
437
|
+
// Call onRemove hook - use stored instance if available
|
|
438
|
+
const hookTarget = (item as any)._itemInstance || item;
|
|
439
|
+
this["execMethod"]("onRemove", [this], hookTarget);
|
|
169
440
|
return this.items()[itemIndex];
|
|
170
441
|
}
|
|
171
442
|
|
|
@@ -176,7 +447,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
176
447
|
*
|
|
177
448
|
* @title Buy Item
|
|
178
449
|
* @method player.buyItem(item,nb=1)
|
|
179
|
-
* @param {ItemClass | string} itemClass
|
|
450
|
+
* @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
|
|
180
451
|
* @param {number} [nb] Default 1
|
|
181
452
|
* @returns {{ nb: number, item: instance of ItemClass }}
|
|
182
453
|
* @throws {ItemLog} haveNotPrice
|
|
@@ -202,15 +473,38 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
202
473
|
* import Potion from 'your-database/potion'
|
|
203
474
|
*
|
|
204
475
|
* try {
|
|
476
|
+
* // Using class
|
|
205
477
|
* player.buyItem(Potion)
|
|
478
|
+
*
|
|
479
|
+
* // Using string ID
|
|
480
|
+
* player.buyItem('Potion')
|
|
206
481
|
* }
|
|
207
482
|
* catch (err) {
|
|
208
483
|
* console.log(err)
|
|
209
484
|
* }
|
|
210
485
|
* ```
|
|
211
486
|
*/
|
|
212
|
-
buyItem(
|
|
213
|
-
|
|
487
|
+
buyItem(item: ItemClass | ItemObject | string, nb = 1): Item {
|
|
488
|
+
let itemId: string;
|
|
489
|
+
let data: any;
|
|
490
|
+
|
|
491
|
+
if (isString(item)) {
|
|
492
|
+
itemId = item as string;
|
|
493
|
+
data = (this as any).databaseById(itemId);
|
|
494
|
+
} else if (typeof item === 'function' || (item as any).prototype) {
|
|
495
|
+
itemId = (item as any).name;
|
|
496
|
+
data = (this as any).databaseById(itemId);
|
|
497
|
+
} else {
|
|
498
|
+
const itemObj = item as ItemObject;
|
|
499
|
+
itemId = itemObj.id || `item-${Date.now()}`;
|
|
500
|
+
try {
|
|
501
|
+
const dbData = (this as any).databaseById(itemId);
|
|
502
|
+
data = { ...dbData, ...itemObj };
|
|
503
|
+
} catch {
|
|
504
|
+
data = itemObj;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
214
508
|
if (!data.price) {
|
|
215
509
|
throw ItemLog.haveNotPrice(itemId);
|
|
216
510
|
}
|
|
@@ -219,7 +513,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
219
513
|
throw ItemLog.notEnoughGold(itemId, nb);
|
|
220
514
|
}
|
|
221
515
|
this._gold.update((gold) => gold - totalPrice);
|
|
222
|
-
return this.addItem(
|
|
516
|
+
return this.addItem(item, nb);
|
|
223
517
|
}
|
|
224
518
|
|
|
225
519
|
/**
|
|
@@ -229,7 +523,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
229
523
|
*
|
|
230
524
|
* @title Sell Item
|
|
231
525
|
* @method player.sellItem(item,nb=1)
|
|
232
|
-
* @param {ItemClass | string} itemClass
|
|
526
|
+
* @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
|
|
233
527
|
* @param {number} [nbToSell] Default 1
|
|
234
528
|
* @returns {{ nb: number, item: instance of ItemClass }}
|
|
235
529
|
* @throws {ItemLog} haveNotPrice
|
|
@@ -264,16 +558,20 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
264
558
|
*
|
|
265
559
|
* try {
|
|
266
560
|
* player.addItem(Potion)
|
|
561
|
+
* // Using class
|
|
267
562
|
* player.sellItem(Potion)
|
|
563
|
+
* // Using string ID
|
|
564
|
+
* player.sellItem('Potion')
|
|
268
565
|
* }
|
|
269
566
|
* catch (err) {
|
|
270
567
|
* console.log(err)
|
|
271
568
|
* }
|
|
272
569
|
* ```
|
|
273
570
|
*/
|
|
274
|
-
sellItem(
|
|
275
|
-
const
|
|
276
|
-
const
|
|
571
|
+
sellItem(itemClass: ItemClass | string, nbToSell = 1): Item {
|
|
572
|
+
const itemId = isString(itemClass) ? itemClass : (itemClass as any).name;
|
|
573
|
+
const data = (this as any).databaseById(itemId);
|
|
574
|
+
const inventory = this.getItem(itemClass);
|
|
277
575
|
if (!inventory) {
|
|
278
576
|
throw ItemLog.notInInventory(itemId);
|
|
279
577
|
}
|
|
@@ -285,7 +583,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
285
583
|
throw ItemLog.haveNotPrice(itemId);
|
|
286
584
|
}
|
|
287
585
|
this._gold.update((gold) => gold + (data.price / 2) * nbToSell);
|
|
288
|
-
this.removeItem(
|
|
586
|
+
this.removeItem(itemClass, nbToSell);
|
|
289
587
|
return inventory;
|
|
290
588
|
}
|
|
291
589
|
|
|
@@ -343,7 +641,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
343
641
|
*
|
|
344
642
|
* @title Use an Item
|
|
345
643
|
* @method player.useItem(item,nb=1)
|
|
346
|
-
* @param {ItemClass | string} itemClass
|
|
644
|
+
* @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
|
|
347
645
|
* @returns {{ nb: number, item: instance of ItemClass }}
|
|
348
646
|
* @throws {ItemLog} restriction
|
|
349
647
|
* If the player has the `Effect.CAN_NOT_ITEM` effect
|
|
@@ -389,15 +687,19 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
389
687
|
*
|
|
390
688
|
* try {
|
|
391
689
|
* player.addItem(Potion)
|
|
690
|
+
* // Using class
|
|
392
691
|
* player.useItem(Potion)
|
|
692
|
+
* // Using string ID
|
|
693
|
+
* player.useItem('Potion')
|
|
393
694
|
* }
|
|
394
695
|
* catch (err) {
|
|
395
696
|
* console.log(err)
|
|
396
697
|
* }
|
|
397
698
|
* ```
|
|
398
699
|
*/
|
|
399
|
-
useItem(
|
|
400
|
-
const
|
|
700
|
+
useItem(itemClass: ItemClass | string): Item {
|
|
701
|
+
const itemId = isString(itemClass) ? itemClass : (itemClass as any).name;
|
|
702
|
+
const inventory = this.getItem(itemClass);
|
|
401
703
|
if ((this as any).hasEffect?.(Effect.CAN_NOT_ITEM)) {
|
|
402
704
|
throw ItemLog.restriction(itemId);
|
|
403
705
|
}
|
|
@@ -409,15 +711,16 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
409
711
|
throw ItemLog.notUseItem(itemId);
|
|
410
712
|
}
|
|
411
713
|
const hitRate = (item as any).hitRate ?? 1;
|
|
714
|
+
const hookTarget = (item as any)._itemInstance || item;
|
|
412
715
|
if (Math.random() > hitRate) {
|
|
413
|
-
this.removeItem(
|
|
414
|
-
this["execMethod"]("onUseFailed", [this],
|
|
716
|
+
this.removeItem(itemClass);
|
|
717
|
+
this["execMethod"]("onUseFailed", [this], hookTarget);
|
|
415
718
|
throw ItemLog.chanceToUseFailed(itemId);
|
|
416
719
|
}
|
|
417
720
|
(this as any).applyEffect?.(item);
|
|
418
721
|
(this as any).applyStates?.(this, item);
|
|
419
|
-
this["execMethod"]("onUse", [this],
|
|
420
|
-
this.removeItem(
|
|
722
|
+
this["execMethod"]("onUse", [this], hookTarget);
|
|
723
|
+
this.removeItem(itemClass);
|
|
421
724
|
return inventory;
|
|
422
725
|
}
|
|
423
726
|
|
|
@@ -428,7 +731,7 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
428
731
|
*
|
|
429
732
|
* @title Equip Weapon or Armor
|
|
430
733
|
* @method player.equip(itemClass,equip=true)
|
|
431
|
-
* @param {ItemClass | string} itemClass
|
|
734
|
+
* @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
|
|
432
735
|
* @param {number} [equip] Equip the object if true or un-equipped if false
|
|
433
736
|
* @returns {void}
|
|
434
737
|
* @throws {ItemLog} notInInventory
|
|
@@ -463,7 +766,10 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
463
766
|
*
|
|
464
767
|
* try {
|
|
465
768
|
* player.addItem(Sword)
|
|
769
|
+
* // Using class
|
|
466
770
|
* player.equip(Sword)
|
|
771
|
+
* // Using string ID
|
|
772
|
+
* player.equip('Sword')
|
|
467
773
|
* }
|
|
468
774
|
* catch (err) {
|
|
469
775
|
* console.log(err)
|
|
@@ -471,14 +777,15 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
471
777
|
* ```
|
|
472
778
|
*/
|
|
473
779
|
equip(
|
|
474
|
-
|
|
780
|
+
itemClass: ItemClass | string,
|
|
475
781
|
equip: boolean = true
|
|
476
782
|
): void {
|
|
477
|
-
const
|
|
783
|
+
const itemId = isString(itemClass) ? itemClass : (itemClass as any).name;
|
|
784
|
+
const inventory: Item = this.getItem(itemClass);
|
|
478
785
|
if (!inventory) {
|
|
479
786
|
throw ItemLog.notInInventory(itemId);
|
|
480
787
|
}
|
|
481
|
-
const data = this.databaseById(itemId);
|
|
788
|
+
const data = (this as any).databaseById(itemId);
|
|
482
789
|
if (data._type == "item") {
|
|
483
790
|
throw ItemLog.invalidToEquiped(itemId);
|
|
484
791
|
}
|
|
@@ -506,7 +813,15 @@ export function WithItemManager<TBase extends Constructor<RpgCommonPlayer>>(
|
|
|
506
813
|
} else {
|
|
507
814
|
this.equipments().push(item);
|
|
508
815
|
}
|
|
509
|
-
|
|
816
|
+
// Call onEquip hook - use stored instance if available
|
|
817
|
+
const hookTarget = (item as any)._itemInstance || item;
|
|
818
|
+
this["execMethod"]("onEquip", [this, equip], hookTarget);
|
|
510
819
|
}
|
|
511
|
-
};
|
|
820
|
+
} as unknown as TBase;
|
|
512
821
|
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Type helper to extract the interface from the WithItemManager mixin
|
|
825
|
+
* This provides the type without duplicating method signatures
|
|
826
|
+
*/
|
|
827
|
+
export type IItemManager = InstanceType<ReturnType<typeof WithItemManager>>;
|