@rpgjs/server 4.0.0-beta.9 → 4.0.0-rc.10

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.
Files changed (77) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/lib/Game/EventManager.d.ts +53 -0
  3. package/lib/Game/EventManager.js +93 -0
  4. package/lib/Game/EventManager.js.map +1 -0
  5. package/lib/Game/Map.d.ts +6 -30
  6. package/lib/Game/Map.js +26 -61
  7. package/lib/Game/Map.js.map +1 -1
  8. package/lib/Gui/MenuGui.js +2 -2
  9. package/lib/Gui/MenuGui.js.map +1 -1
  10. package/lib/Player/BattleManager.d.ts +5 -5
  11. package/lib/Player/BattleManager.js +8 -7
  12. package/lib/Player/BattleManager.js.map +1 -1
  13. package/lib/Player/ClassManager.d.ts +11 -4
  14. package/lib/Player/ClassManager.js +7 -3
  15. package/lib/Player/ClassManager.js.map +1 -1
  16. package/lib/Player/EffectManager.d.ts +2 -2
  17. package/lib/Player/EffectManager.js +6 -6
  18. package/lib/Player/EffectManager.js.map +1 -1
  19. package/lib/Player/ElementManager.d.ts +4 -1
  20. package/lib/Player/ElementManager.js.map +1 -1
  21. package/lib/Player/ItemManager.d.ts +21 -0
  22. package/lib/Player/ItemManager.js +22 -1
  23. package/lib/Player/ItemManager.js.map +1 -1
  24. package/lib/Player/MoveManager.js +27 -14
  25. package/lib/Player/MoveManager.js.map +1 -1
  26. package/lib/Player/ParameterManager.d.ts +2 -1
  27. package/lib/Player/ParameterManager.js +15 -4
  28. package/lib/Player/ParameterManager.js.map +1 -1
  29. package/lib/Player/Player.d.ts +150 -54
  30. package/lib/Player/Player.js +142 -58
  31. package/lib/Player/Player.js.map +1 -1
  32. package/lib/Player/SkillManager.d.ts +13 -8
  33. package/lib/Player/SkillManager.js +14 -12
  34. package/lib/Player/SkillManager.js.map +1 -1
  35. package/lib/Player/StateManager.d.ts +11 -6
  36. package/lib/Player/StateManager.js +21 -6
  37. package/lib/Player/StateManager.js.map +1 -1
  38. package/lib/RpgServer.d.ts +42 -2
  39. package/lib/Scenes/Map.d.ts +3 -0
  40. package/lib/Scenes/Map.js +4 -0
  41. package/lib/Scenes/Map.js.map +1 -1
  42. package/lib/decorators/event.d.ts +1 -1
  43. package/lib/decorators/event.js +2 -1
  44. package/lib/decorators/event.js.map +1 -1
  45. package/lib/decorators/map.d.ts +5 -2
  46. package/lib/decorators/map.js.map +1 -1
  47. package/lib/express/server.js +5 -1
  48. package/lib/express/server.js.map +1 -1
  49. package/lib/index.d.ts +3 -1
  50. package/lib/index.js +3 -1
  51. package/lib/index.js.map +1 -1
  52. package/lib/models/Item.d.ts +1 -1
  53. package/lib/server.d.ts +3 -6
  54. package/lib/server.js +9 -8
  55. package/lib/server.js.map +1 -1
  56. package/package.json +8 -7
  57. package/src/Game/EventManager.ts +110 -0
  58. package/src/Game/Map.ts +37 -69
  59. package/src/Gui/MenuGui.ts +3 -3
  60. package/src/Player/BattleManager.ts +10 -9
  61. package/src/Player/ClassManager.ts +13 -7
  62. package/src/Player/EffectManager.ts +6 -5
  63. package/src/Player/ElementManager.ts +4 -1
  64. package/src/Player/ItemManager.ts +47 -26
  65. package/src/Player/MoveManager.ts +35 -15
  66. package/src/Player/ParameterManager.ts +19 -8
  67. package/src/Player/Player.ts +170 -57
  68. package/src/Player/SkillManager.ts +23 -21
  69. package/src/Player/StateManager.ts +30 -11
  70. package/src/RpgServer.ts +42 -2
  71. package/src/Scenes/Map.ts +4 -0
  72. package/src/decorators/event.ts +2 -1
  73. package/src/decorators/map.ts +5 -2
  74. package/src/express/server.ts +9 -3
  75. package/src/index.ts +10 -8
  76. package/src/models/Item.ts +1 -1
  77. package/src/server.ts +11 -8
@@ -0,0 +1,110 @@
1
+ import { PlayerType } from "@rpgjs/types"
2
+ import { RpgEvent, RpgPlayer } from "../Player/Player"
3
+ import { RpgMap } from "./Map"
4
+
5
+ export type EventsList = {
6
+ [playerId: string]: RpgEvent
7
+ }
8
+
9
+ export enum EventMode {
10
+ Shared = 'shared',
11
+ Scenario = 'scenario'
12
+ }
13
+
14
+ /**
15
+ * ⚠️ Please note that the event system can be on the player or on the card.
16
+ * On player, it's Scenario mode
17
+ * On-map: Shared mode
18
+ * So this here is either RpgMap or RpgPlayer
19
+ * You can check the mode with the mode cleanup on the retrieved event
20
+ */
21
+ export class EventManager {
22
+ /**
23
+ * @title event list
24
+ * @prop { { [eventId: string]: RpgEvent } } [events]
25
+ * @memberof Map
26
+ * */
27
+ public events: EventsList
28
+
29
+ /**
30
+ * Get Event in current map
31
+ * @title Get Event
32
+ * @since 3.0.0-beta.7
33
+ * @method map.getEvent(eventId)
34
+ * @param {string} eventId Event Id
35
+ * @returns {RpgEvent | undefined}
36
+ * @memberof Map
37
+ */
38
+ getEvent<T extends RpgEvent>(eventId: string): T | undefined {
39
+ return this.events[eventId] as T
40
+ }
41
+
42
+ getEventByName<T extends RpgEvent>(eventName: string): T | undefined {
43
+ const events = Object.keys(this.events)
44
+ const key = events.find(key => this.events[key].name == eventName)
45
+ if (!key) return
46
+ return this.events[key] as T
47
+ }
48
+
49
+ /**
50
+ * Removes an event from the map. Returns false if the event is not found
51
+ *
52
+ * Deletion of an event forced to be performed at the end of several aynschronous notions
53
+ *
54
+ * @title Remove Event
55
+ * @since 3.0.0-beta.4
56
+ * @method map.removeEvent(eventId)
57
+ * @param {string} eventId Event Name
58
+ * @returns {boolean}
59
+ * @memberof Map
60
+ */
61
+ removeEvent(eventId: string): boolean {
62
+ if (!this.events[eventId]) return false
63
+ const mode = this.events[eventId].mode
64
+ this.removeObject(this.events[eventId], mode)
65
+ delete this.events[eventId]
66
+ // Change the state of the packet that will be sent to the client, adding the deleted flag to indicate to the client that the event has been deleted.
67
+ if (mode == EventMode.Scenario) {
68
+ this.getCurrentMap()?.$setCurrentState(`users.${this.id}.events.${eventId}.deleted`, true)
69
+ }
70
+ else {
71
+ this.$setCurrentState(`events.${eventId}.deleted`, true)
72
+ }
73
+ return true
74
+ }
75
+
76
+ // @internal
77
+ removeObject(object: RpgPlayer | RpgEvent, mode: EventMode = EventMode.Shared) {
78
+ const map = this.getCurrentMap()
79
+ if (!map) return
80
+ map.getShapes().forEach(shape => shape.out(object))
81
+ const events: RpgPlayer[] = Object.values(map.game.world.getObjectsOfGroup(map.id, object))
82
+ for (let event of events) {
83
+ object.getShapes().forEach(shape => shape.out(event))
84
+ event.getShapes().forEach(shape => shape.out(object))
85
+ }
86
+ object._destroy$.next()
87
+ object._destroy$.complete()
88
+ // force RXJS, close subject. TODO: avoid this
89
+ if (object.type != PlayerType.Player) object._destroy$['_closed'] = true
90
+ map.grid.clearObjectInCells(object.id)
91
+ for (let playerId in map.players) {
92
+ if (object.id == playerId) continue
93
+ const otherPlayer = map.players[playerId]
94
+ if (otherPlayer.following?.id == object.id) {
95
+ otherPlayer.cameraFollow(otherPlayer)
96
+ }
97
+ }
98
+ // last player before removed of this map
99
+ if (map.nbPlayers === 1 && object.type === PlayerType.Player) {
100
+ // clear cache for this map
101
+ map.remove(true)
102
+ }
103
+ }
104
+ }
105
+
106
+ export interface EventManager {
107
+ getCurrentMap(): RpgMap | null
108
+ id: string
109
+ $setCurrentState: (path: string, value: any) => void;
110
+ }
package/src/Game/Map.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import { RpgCommonMap, Utils, RpgShape, RpgCommonGame, AbstractObject } from '@rpgjs/common'
2
2
  import { TiledParserFile, TiledParser, TiledTileset } from '@rpgjs/tiled'
3
3
  import { EventOptions } from '../decorators/event'
4
- import { RpgPlayer, EventMode, RpgEvent, RpgClassEvent } from '../Player/Player'
4
+ import { RpgPlayer, RpgEvent, RpgClassEvent } from '../Player/Player'
5
5
  import { Move } from '../Player/MoveManager'
6
6
  import { RpgServerEngine } from '../server'
7
7
  import { Observable } from 'rxjs'
8
8
  import path from 'path'
9
- import { HitBox, MovingHitbox, Position } from '@rpgjs/types'
9
+ import { HitBox, MovingHitbox, PlayerType, Position } from '@rpgjs/types'
10
10
  import { World } from 'simple-room'
11
+ import { EventManager, EventMode } from './EventManager'
11
12
 
12
13
  export type EventPosOption = {
13
14
  x: number,
@@ -63,15 +64,9 @@ export class RpgMap extends RpgCommonMap {
63
64
  public _events: EventOption[]
64
65
  public file: any
65
66
 
66
- /**
67
- * @title event list
68
- * @prop { { [eventId: string]: RpgEvent } } [events]
69
- * @memberof Map
70
- * */
71
- public events: EventsList = {}
72
-
73
67
  constructor(private _server: RpgServerEngine) {
74
68
  super()
69
+ this.events = {}
75
70
  }
76
71
 
77
72
  // alias of users property in simple-room package
@@ -237,7 +232,16 @@ export class RpgMap extends RpgCommonMap {
237
232
  this.removeObject(player)
238
233
  }
239
234
 
240
- private loadCommonEvents(commonEvents: RpgClassEvent<RpgEvent>[]) {
235
+ /**
236
+ * Loads common events onto the game map.
237
+ *
238
+ * @private
239
+ * @param {RpgClassEvent<RpgEvent>[]} commonEvents - An array of common events to load.
240
+ * @param {RpgPlayer} [player] - The player instance on which to create the dynamic events. If not provided, the function will use the current instance.
241
+ * @returns {void}
242
+ */
243
+ // @internal
244
+ loadCommonEvents(commonEvents: RpgClassEvent<RpgEvent>[], player?: RpgPlayer) {
241
245
  let events: EventPosOption[] = []
242
246
  this.getShapes().forEach(shape => {
243
247
  const findEvent = commonEvents.find(event => event._name == shape.name)
@@ -248,8 +252,14 @@ export class RpgMap extends RpgCommonMap {
248
252
  y,
249
253
  event: findEvent
250
254
  })
251
- })
252
- this.createDynamicEvent(events)
255
+ });
256
+ if (player) {
257
+ player.createDynamicEvent(events, false)
258
+ }
259
+ else {
260
+ this.createDynamicEvent(events)
261
+ }
262
+
253
263
  }
254
264
 
255
265
  // TODO
@@ -350,7 +360,7 @@ export class RpgMap extends RpgCommonMap {
350
360
  const events = this.createEvents(eventsList as EventPosOption[], EventMode.Shared)
351
361
  let ret = {}
352
362
  for (let key in events) {
353
- this.events[key] = events[key]
363
+ this.events[key] = events[key] as any
354
364
  this.events[key].updateInVirtualGrid()
355
365
  this.events[key].execMethod('onInit')
356
366
  // force to get Proxy object to sync with client
@@ -359,35 +369,6 @@ export class RpgMap extends RpgCommonMap {
359
369
  return ret
360
370
  }
361
371
 
362
- /**
363
- * Get Event in current map
364
- * @title Get Event
365
- * @since 3.0.0-beta.7
366
- * @method map.getEvent(eventId)
367
- * @param {string} eventId Event Id
368
- * @returns {RpgEvent | undefined}
369
- * @memberof Map
370
- */
371
- getEvent<T extends RpgEvent>(eventId: string): T | undefined {
372
- return this.events[eventId] as T
373
- }
374
-
375
- /**
376
- * Removes an event from the map. Returns false if the event is not found
377
- * @title Remove Event
378
- * @since 3.0.0-beta.4
379
- * @method map.removeEvent(eventId)
380
- * @param {string} eventId Event Name
381
- * @returns {boolean}
382
- * @memberof Map
383
- */
384
- removeEvent(eventId: string): boolean {
385
- if (!this.events[eventId]) return false
386
- this.removeObject(this.events[eventId])
387
- delete this.events[eventId]
388
- return true
389
- }
390
-
391
372
  createEvent(obj: EventPosOption, mode: EventMode, shape?: RpgShape): RpgEvent | null {
392
373
  let event: any, position: Position | undefined
393
374
 
@@ -397,7 +378,7 @@ export class RpgMap extends RpgCommonMap {
397
378
  }
398
379
  else {
399
380
  event = obj.event
400
- position = { x: obj.x, y: obj.y, z: 0 }
381
+ position = { x: obj.x, y: obj.y, z: obj.z ?? 0 }
401
382
  }
402
383
 
403
384
  // The event is ignored if the mode is different.
@@ -433,30 +414,6 @@ export class RpgMap extends RpgCommonMap {
433
414
  return events
434
415
  }
435
416
 
436
- private removeObject(object: RpgPlayer | RpgEvent) {
437
- this.getShapes().forEach(shape => shape.out(object))
438
- const events: RpgPlayer[] = Object.values(this.game.world.getObjectsOfGroup(this.id, object))
439
- for (let event of events) {
440
- object.getShapes().forEach(shape => shape.out(event))
441
- event.getShapes().forEach(shape => shape.out(object))
442
- }
443
- object._destroy$.next()
444
- object._destroy$.complete()
445
- this.grid.clearObjectInCells(object.id)
446
- for (let playerId in this.players) {
447
- if (object.id == playerId) continue
448
- const otherPlayer = this.players[playerId]
449
- if (otherPlayer.following?.id == object.id) {
450
- otherPlayer.cameraFollow(otherPlayer)
451
- }
452
- }
453
- // last player before removed of this map
454
- if (this.nbPlayers === 1 && object.type === 'player') {
455
- // clear cache for this map
456
- this.remove(true)
457
- }
458
- }
459
-
460
417
  /**
461
418
  * Allows to create a temporary hitbox on the map that can have a movement
462
419
  For example, you can use it to explode a bomb and find all the affected players, or during a sword strike, you can create a moving hitbox and find the affected players again
@@ -501,13 +458,24 @@ For example, you can use it to explode a bomb and find all the affected players,
501
458
  setSync(schema: any) {
502
459
  return this.$setSchema(schema)
503
460
  }
461
+
462
+ // Reflects itself. Just for compatibility with the EventManager class
463
+ getCurrentMap() {
464
+ return this
465
+ }
504
466
  }
505
467
 
506
- export interface RpgMap {
468
+ export interface RpgMap extends EventManager {
507
469
  sounds: string[]
508
470
  $schema: any
509
471
  $setSchema: (schema: any) => void
510
472
  $patchSchema: (schema: any) => void
511
473
  $snapshotUser: (userId: string) => any
512
474
  onLoad()
513
- }
475
+ $setCurrentState: (path: string, value: any) => void;
476
+ id: string
477
+ }
478
+
479
+ Utils.applyMixins(RpgMap, [
480
+ EventManager
481
+ ])
@@ -11,11 +11,11 @@ export class MenuGui extends Gui implements IGui {
11
11
  open() {
12
12
  this.on('useItem', (id) => {
13
13
  try {
14
- // this.player.useItem(id)
14
+ this.player.useItem(id)
15
15
  this.player.syncChanges()
16
16
  }
17
- catch (err) {
18
- console.log(err)
17
+ catch (err: any) {
18
+ this.player.showNotification(err.msg)
19
19
  }
20
20
  })
21
21
  return super.open('', {
@@ -18,30 +18,30 @@ const {
18
18
  export class BattleManager {
19
19
 
20
20
  /**
21
- * Apply damage. Player will lose HP. the `otherPlayer` parameter is the other player, the one who attacks.
21
+ * Apply damage. Player will lose HP. the `attackerPlayer` parameter is the other player, the one who attacks.
22
22
  *
23
23
  * If you don't set the skill parameter, it will be a physical attack.
24
24
  * The attack formula is already defined but you can customize it in the server options
25
25
  *
26
26
  * ```ts
27
- * player.applyDamage(otherPlayer) // returns { damage: number }
27
+ * player.applyDamage(attackerPlayer) // returns { damage: number }
28
28
  * ```
29
29
  *
30
30
  * @title Apply Damage
31
- * @method player.applyDamage(otherPlayer,skill)
32
- * @param {RpgPlayer} otherPlayer The attacking player
31
+ * @method player.applyDamage(attackerPlayer,skill)
32
+ * @param {RpgPlayer} attackerPlayer The attacking player
33
33
  * @param {any} [skill]
34
34
  * @returns {object}
35
35
  * @memberof BattleManager
36
36
  * */
37
- applyDamage(otherPlayer: RpgPlayer, skill?: any): {
37
+ applyDamage(attackerPlayer: RpgPlayer, skill?: any): {
38
38
  damage: number,
39
39
  critical: boolean,
40
40
  elementVulnerable: boolean,
41
41
  guard: boolean,
42
42
  superGuard: boolean
43
43
  } {
44
- const getParam = (player) => {
44
+ const getParam = (player: RpgPlayer) => {
45
45
  const params = {}
46
46
  this.parameters.forEach((val, key) => {
47
47
  params[key] = player.param[key]
@@ -58,8 +58,8 @@ export class BattleManager {
58
58
  let guard = false
59
59
  let superGuard = false
60
60
  let elementVulnerable = false
61
- const paramA = getParam(otherPlayer)
62
- const paramB = getParam(this)
61
+ const paramA = getParam(attackerPlayer)
62
+ const paramB = getParam(<any>this)
63
63
  if (skill) {
64
64
  fn = this.getFormulas('damageSkill')
65
65
  if (!fn) {
@@ -73,7 +73,7 @@ export class BattleManager {
73
73
  throw new Error('Physic Formulas not exists')
74
74
  }
75
75
  damage = fn(paramA, paramB)
76
- const coef = this.coefficientElements(otherPlayer)
76
+ const coef = this.coefficientElements(attackerPlayer)
77
77
  if (coef >= 2) {
78
78
  elementVulnerable = true
79
79
  }
@@ -99,6 +99,7 @@ export class BattleManager {
99
99
  }
100
100
  if (this.hasEffect(Effect.SUPER_GUARD)) {
101
101
  damage /= 4
102
+ superGuard = true
102
103
  }
103
104
  this.hp -= damage
104
105
  return {
@@ -3,9 +3,13 @@ import { ParameterManager } from './ParameterManager'
3
3
  import { ItemManager } from './ItemManager'
4
4
 
5
5
  const {
6
- applyMixins
6
+ applyMixins,
7
+ isString
7
8
  } = Utils
8
9
 
10
+ type ClassClass = { new(...args: any[]) }
11
+ type ActorClass = { new(...args: any[]) }
12
+
9
13
  export class ClassManager {
10
14
 
11
15
  _class: any
@@ -21,12 +25,13 @@ export class ClassManager {
21
25
  *
22
26
  * @title Set Class
23
27
  * @method player.setClass(ClassClass)
24
- * @param {ClassClass} class
28
+ * @param {ClassClass} class class or id
25
29
  * @returns {instance of ClassClass}
26
30
  * @memberof ClassManager
27
31
  * */
28
- setClass(_class) {
29
- this._class = new _class()
32
+ setClass(_class: ClassClass | string) {
33
+ if (isString(_class)) _class = this.databaseById(_class)
34
+ this._class = new (_class as ClassClass)()
30
35
  this['execMethod']('onSet', [this], this._class)
31
36
  return this._class
32
37
  }
@@ -42,12 +47,13 @@ export class ClassManager {
42
47
  *
43
48
  * @title Set Actor
44
49
  * @method player.setActor(ActorClass)
45
- * @param {ActorClass} actorClass
50
+ * @param {ActorClass} actorClass actor class or id
46
51
  * @returns {instance of ActorClass}
47
52
  * @memberof ClassManager
48
53
  * */
49
- setActor(actorClass) {
50
- const actor = new actorClass()
54
+ setActor(actorClass: ActorClass | string) {
55
+ if (isString(actorClass)) actorClass = this.databaseById(actorClass)
56
+ const actor = new (actorClass as ActorClass)()
51
57
  this.name = actor.name
52
58
  this.initialLevel = actor.initialLevel
53
59
  this.finalLevel = actor.finalLevel
@@ -4,6 +4,7 @@ import { ParameterManager } from './ParameterManager'
4
4
 
5
5
  import {
6
6
  MAXHP,
7
+ MAXSP
7
8
  } from '../presets'
8
9
 
9
10
  const {
@@ -22,19 +23,19 @@ export class EffectManager {
22
23
  this.hp += item.hpValue
23
24
  }
24
25
  if (item.hpRate) {
25
- this.hp += this.param[MAXHP] / item.hpRate
26
+ this.hp += this.param[MAXHP] * item.hpRate
26
27
  }
27
28
  if (item.spValue) {
28
- this.sp += item.hpValue
29
+ this.sp += item.spValue
29
30
  }
30
31
  if (item.spRate) {
31
- this.sp += this.param[MAXHP] / item.hpRate
32
+ this.sp += this.param[MAXSP] * item.spRate
32
33
  }
33
34
  }
34
35
 
35
36
  /**
36
37
  * ```ts
37
- * import { Effect } from '@rpgjs/server'
38
+ * import { Effect } from '@rpgjs/database'
38
39
  *
39
40
  * const bool = player.hasEffect(Effect.CAN_NOT_SKILL)
40
41
  * ```
@@ -75,7 +76,7 @@ export class EffectManager {
75
76
  * Assigns effects to the player. If you give a array, it does not change the effects of the player's states and armor/weapons equipped.
76
77
  *
77
78
  * ```ts
78
- * import { Effect } from '@rpgjs/server'
79
+ * import { Effect } from '@rpgjs/database'
79
80
  *
80
81
  * player.effects = [Effect.CAN_NOT_SKILL]
81
82
  * ```
@@ -101,7 +101,10 @@ export class ElementManager extends ItemFixture {
101
101
  * @readonly
102
102
  * @memberof ElementManager
103
103
  * */
104
- get elements() {
104
+ get elements(): {
105
+ rate: number,
106
+ element: string
107
+ }[] {
105
108
  let elements: any = []
106
109
  for (let item of this.equipments) {
107
110
  if (item.elements) {
@@ -1,4 +1,4 @@
1
- import { Utils } from '@rpgjs/common'
1
+ import { Utils } from '@rpgjs/common'
2
2
  import { Effect, ItemOptions } from '@rpgjs/database'
3
3
  import { ItemLog } from '../logs'
4
4
  import { ItemModel } from '../models/Item'
@@ -6,43 +6,43 @@ import { EffectManager } from './EffectManager'
6
6
  import { GoldManager } from './GoldManager'
7
7
  import { StateManager } from './StateManager'
8
8
 
9
- import {
9
+ import {
10
10
  ATK,
11
11
  PDEF,
12
12
  SDEF
13
13
  } from '../presets'
14
14
 
15
- const {
16
- isString,
15
+ const {
16
+ isString,
17
17
  isInstanceOf,
18
18
  applyMixins
19
19
  } = Utils
20
20
 
21
21
  type ItemClass = { new(...args: any[]), price?: number, _type?: string }
22
- type Inventory = { nb: number, item: ItemModel }
22
+ type Inventory = { nb: number, item: ItemModel }
23
23
 
24
24
  export class ItemManager {
25
25
 
26
26
  items: Inventory[]
27
27
  equipments: ItemModel[] = []
28
-
29
- /**
30
- * Retrieves the information of an object: the number and the instance
31
- * @title Get Item
32
- * @method player.getItem(itemClass)
33
- * @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
34
- * @returns {{ nb: number, item: instance of ItemClass }}
35
- * @memberof ItemManager
36
- * @example
37
- *
38
- * ```ts
39
- * import Potion from 'your-database/potion'
40
- *
41
- * player.addItem(Potion, 5)
42
- * const inventory = player.getItem(Potion)
43
- * console.log(inventory) // { nb: 5, item: <instance of Potion> }
44
- * ```
45
- */
28
+
29
+ /**
30
+ * Retrieves the information of an object: the number and the instance
31
+ * @title Get Item
32
+ * @method player.getItem(itemClass)
33
+ * @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
34
+ * @returns {{ nb: number, item: instance of ItemClass }}
35
+ * @memberof ItemManager
36
+ * @example
37
+ *
38
+ * ```ts
39
+ * import Potion from 'your-database/potion'
40
+ *
41
+ * player.addItem(Potion, 5)
42
+ * const inventory = player.getItem(Potion)
43
+ * console.log(inventory) // { nb: 5, item: <instance of Potion> }
44
+ * ```
45
+ */
46
46
  getItem(itemClass: ItemClass | string): Inventory {
47
47
  const index: number = this._getItemIndex(itemClass)
48
48
  return this.items[index]
@@ -281,9 +281,9 @@ export class ItemManager {
281
281
  this.gold += (ItemClass.price / 2) * nbToSell
282
282
  this.removeItem(ItemClass, nbToSell)
283
283
  return inventory
284
- }
284
+ }
285
285
 
286
- private getParamItem(name) {
286
+ private getParamItem(name: string): number {
287
287
  let nb = 0
288
288
  for (let item of this.equipments) {
289
289
  nb += item[name] || 0
@@ -296,14 +296,35 @@ export class ItemManager {
296
296
  return nb
297
297
  }
298
298
 
299
+ /**
300
+ * recover the attack sum of items equipped on the player.
301
+ *
302
+ * @title Get the player's attack
303
+ * @prop {number} player.atk
304
+ * @memberof ItemManager
305
+ */
299
306
  get atk(): number {
300
307
  return this.getParamItem(ATK)
301
308
  }
302
309
 
310
+ /**
311
+ * recover the physic defense sum of items equipped on the player.
312
+ *
313
+ * @title Get the player's pdef
314
+ * @prop {number} player.pdef
315
+ * @memberof ItemManager
316
+ */
303
317
  get pdef(): number {
304
318
  return this.getParamItem(PDEF)
305
319
  }
306
320
 
321
+ /**
322
+ * recover the skill defense sum of items equipped on the player.
323
+ *
324
+ * @title Get the player's sdef
325
+ * @prop {number} player.sdef
326
+ * @memberof ItemManager
327
+ */
307
328
  get sdef(): number {
308
329
  return this.getParamItem(SDEF)
309
330
  }
@@ -381,7 +402,7 @@ export class ItemManager {
381
402
  if (item.consumable === false) {
382
403
  throw ItemLog.notUseItem(itemClass)
383
404
  }
384
- const hitRate = item.hitRate || 1
405
+ const hitRate = item.hitRate ?? 1
385
406
  if (Math.random() > hitRate) {
386
407
  this.removeItem(itemClass)
387
408
  this['execMethod']('onUseFailed', [this], item)