@rpgjs/server 5.0.0-alpha.10 → 5.0.0-alpha.3

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 (41) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/Player/BattleManager.d.ts +22 -32
  3. package/dist/Player/ClassManager.d.ts +18 -31
  4. package/dist/Player/Event.d.ts +0 -0
  5. package/dist/Player/ItemManager.d.ts +13 -27
  6. package/dist/Player/MoveManager.d.ts +43 -31
  7. package/dist/Player/ParameterManager.d.ts +19 -27
  8. package/dist/Player/Player.d.ts +8 -123
  9. package/dist/Player/SkillManager.d.ts +19 -27
  10. package/dist/Player/StateManager.d.ts +35 -28
  11. package/dist/RpgServer.d.ts +1 -224
  12. package/dist/index.js +647 -1108
  13. package/dist/index.js.map +1 -1
  14. package/dist/rooms/map.d.ts +1 -70
  15. package/package.json +8 -8
  16. package/src/Player/BattleManager.ts +38 -97
  17. package/src/Player/ClassManager.ts +35 -95
  18. package/src/Player/ComponentManager.ts +20 -64
  19. package/src/Player/EffectManager.ts +27 -110
  20. package/src/Player/ElementManager.ts +25 -126
  21. package/src/Player/Event.ts +0 -0
  22. package/src/Player/GoldManager.ts +35 -32
  23. package/src/Player/GuiManager.ts +140 -187
  24. package/src/Player/ItemFixture.ts +5 -4
  25. package/src/Player/ItemManager.ts +26 -39
  26. package/src/Player/MoveManager.ts +31 -40
  27. package/src/Player/ParameterManager.ts +25 -35
  28. package/src/Player/Player.ts +39 -184
  29. package/src/Player/SkillManager.ts +23 -44
  30. package/src/Player/StateManager.ts +95 -210
  31. package/src/Player/VariableManager.ts +48 -180
  32. package/src/RpgServer.ts +1 -232
  33. package/src/core/context.ts +0 -1
  34. package/src/rooms/map.ts +8 -76
  35. package/dist/Player/ComponentManager.d.ts +0 -60
  36. package/dist/Player/EffectManager.d.ts +0 -40
  37. package/dist/Player/ElementManager.d.ts +0 -31
  38. package/dist/Player/GoldManager.d.ts +0 -22
  39. package/dist/Player/GuiManager.d.ts +0 -176
  40. package/dist/Player/ItemFixture.d.ts +0 -6
  41. package/dist/Player/VariableManager.d.ts +0 -30
package/dist/index.js CHANGED
@@ -26158,7 +26158,7 @@ function WithMoveManager(Base) {
26158
26158
  return class extends Base {
26159
26159
  constructor() {
26160
26160
  super(...arguments);
26161
- // Properties for infinite route management
26161
+ // Private properties for infinite route management
26162
26162
  this._infiniteRoutes = null;
26163
26163
  this._finishRoute = null;
26164
26164
  this._isInfiniteRouteActive = false;
@@ -26962,16 +26962,123 @@ class NotificationGui extends Gui {
26962
26962
  }
26963
26963
 
26964
26964
  function WithGuiManager(Base) {
26965
- class GuiManagerMixin extends Base {
26965
+ return class extends Base {
26966
26966
  constructor() {
26967
26967
  super(...arguments);
26968
26968
  this._gui = {};
26969
26969
  }
26970
+ /**
26971
+ * Show a text. This is a graphical interface already built. Opens the GUI named `rpg-dialog`
26972
+ *
26973
+ * ```ts
26974
+ * player.showText('Hello World')
26975
+ * ```
26976
+ *
26977
+ * The method returns a promise. It is resolved when the dialog box is closed.
26978
+ *
26979
+ * ```ts
26980
+ * await player.showText('Hello World')
26981
+ * // dialog box is closed, then ...
26982
+ * ```
26983
+ *
26984
+ * **Option: position**
26985
+ *
26986
+ * You can define how the dialog box is displayed:
26987
+ * - top
26988
+ * - middle
26989
+ * - bottom
26990
+ *
26991
+ * (bottom by default)
26992
+ *
26993
+ * ```ts
26994
+ * player.showText('Hello World', {
26995
+ * position: 'top'
26996
+ * })
26997
+ * ```
26998
+ *
26999
+ * **Option: fullWidth**
27000
+ *
27001
+ * `boolean` (true by default)
27002
+ *
27003
+ * Indicate that the dialog box will take the full width of the screen.
27004
+ *
27005
+ * ```ts
27006
+ * player.showText('Hello World', {
27007
+ * fullWidth: true
27008
+ * })
27009
+ * ```
27010
+ *
27011
+ * **Option: autoClose**
27012
+ *
27013
+ * `boolean` (false by default)
27014
+ *
27015
+ * If false, the user will have to press Enter to close the dialog box.
27016
+ *
27017
+ * ```ts
27018
+ * player.showText('Hello World', {
27019
+ * autoClose: true
27020
+ * })
27021
+ * ```
27022
+ *
27023
+ * **Option: typewriterEffect**
27024
+ *
27025
+ * `boolean` (true by default)
27026
+ *
27027
+ * Performs a typewriter effect
27028
+ *
27029
+ * ```ts
27030
+ * player.showText('Hello World', {
27031
+ * typewriterEffect: false
27032
+ * })
27033
+ * ```
27034
+ *
27035
+ * **Option: talkWith**
27036
+ *
27037
+ * `RpgPlayer` (nothing by default)
27038
+ *
27039
+ * If you specify the event or another player, the other player will stop his or her movement and look in the player's direction.
27040
+ *
27041
+ * ```ts
27042
+ * // Code in an event
27043
+ * player.showText('Hello World', {
27044
+ * talkWith: this
27045
+ * })
27046
+ * ```
27047
+ *
27048
+ * @title Show Text
27049
+ * @method player.showText(text,options)
27050
+ * @param {string} text
27051
+ * @param {object} [options] the different options, see usage below
27052
+ * @returns {Promise}
27053
+ * @memberof GuiManager
27054
+ */
26970
27055
  showText(msg, options = {}) {
26971
27056
  const gui = new DialogGui(this);
26972
27057
  this._gui[gui.id] = gui;
26973
27058
  return gui.openDialog(msg, options);
26974
27059
  }
27060
+ /**
27061
+ * Shows a dialog box with a choice. Opens the GUI named `rpg-dialog`
27062
+ *
27063
+ * ```ts
27064
+ * const choice = await player.showChoices('What color do you prefer?', [
27065
+ * { text: 'Black', value: 'black' },
27066
+ * { text: 'Rather the blue', value: 'blue' },
27067
+ * { text: 'I don\'t have a preference!', value: 'none' }
27068
+ * ])
27069
+ *
27070
+ * // If the player selects the first
27071
+ * console.log(choice) // { text: 'Black', value: 'black' }
27072
+ * ```
27073
+ *
27074
+ * @title Show Choices
27075
+ * @method player.showChoices(text,choices)
27076
+ * @param {string} text
27077
+ * @param {Array<{ text: string, value: any }>} choices
27078
+ * @param {object} [options] Same options as the openDialog method
27079
+ * @returns {Promise<Choice | null>}
27080
+ * @memberof GuiManager
27081
+ */
26975
27082
  showChoices(msg, choices, options) {
26976
27083
  return this.showText(msg, {
26977
27084
  choices,
@@ -26981,6 +27088,19 @@ function WithGuiManager(Base) {
26981
27088
  return choices[indexSelected];
26982
27089
  });
26983
27090
  }
27091
+ /**
27092
+ * Displays a notification . Opens the GUI named `rpg-notification`
27093
+ *
27094
+ * @title Displays a notification
27095
+ * @method player.showNotification()
27096
+ * @param {string} message - The message to display in the notification
27097
+ * @param {object} options - An object containing options for the notification
27098
+ * @param {number} options.time - The time to display the notification for (in ms). Default: 2000ms
27099
+ * @param {string} options.icon - The icon to display in the notification. Put the identifier of the spritesheet (defined on the client side)
27100
+ * @param {string} options.sound - The sound to play when the notification is shown. Set the sound ID (defined on the client side)
27101
+ * @returns {void}
27102
+ * @memberof GuiManager
27103
+ */
26984
27104
  showNotification(message, options = {}) {
26985
27105
  const gui = new NotificationGui(this);
26986
27106
  this._gui[gui.id] = gui;
@@ -26990,6 +27110,14 @@ function WithGuiManager(Base) {
26990
27110
  };
26991
27111
  return gui.open(data);
26992
27112
  }
27113
+ /**
27114
+ * Calls main menu. Opens the GUI named `rpg-main-menu`
27115
+ *
27116
+ * @title Call Main Menu
27117
+ * @method player.callMainMenu()
27118
+ * @returns {void}
27119
+ * @memberof GuiManager
27120
+ */
26993
27121
  callMainMenu() {
26994
27122
  const gui = new MenuGui(this);
26995
27123
  this._gui[gui.id] = gui;
@@ -27122,12 +27250,23 @@ function WithGuiManager(Base) {
27122
27250
  const _players = players || this;
27123
27251
  this._attachedGui(_players, false);
27124
27252
  }
27125
- }
27126
- return GuiManagerMixin;
27253
+ };
27127
27254
  }
27128
27255
 
27129
27256
  function WithGoldManager(Base) {
27130
27257
  return class extends Base {
27258
+ /**
27259
+ * You can change the game money
27260
+ *
27261
+ * ```ts
27262
+ * player.gold += 100
27263
+ * ```
27264
+ *
27265
+ * @title Change Gold
27266
+ * @prop {number} player.gold
27267
+ * @default 0
27268
+ * @memberof GoldManager
27269
+ * */
27131
27270
  set gold(val) {
27132
27271
  if (val < 0) {
27133
27272
  val = 0;
@@ -27149,168 +27288,52 @@ function WithVariableManager(Base) {
27149
27288
  /**
27150
27289
  * Assign a variable to the player
27151
27290
  *
27152
- * Stores a key-value pair in the player's variable map. This is useful for
27153
- * tracking game state, quest progress, flags, and other player-specific data.
27154
- * The variable system provides a flexible way to store any type of data
27155
- * associated with the player that persists throughout the game session.
27156
- *
27157
- * @param key - The variable identifier (string key to reference the variable)
27158
- * @param val - The value to store (can be any type: boolean, number, string, object, array)
27159
- * @returns void
27160
- *
27161
- * @example
27162
27291
  * ```ts
27163
- * // Set different types of variables
27164
- * player.setVariable('CHEST_OPENED', true);
27165
- * player.setVariable('playerLevel', 5);
27166
- * player.setVariable('questProgress', { step: 1, completed: false });
27167
- * player.setVariable('inventory', ['sword', 'potion', 'key']);
27168
- * player.setVariable('lastSaveTime', new Date().toISOString());
27292
+ * player.setVariable('OPEN_CHEST', true)
27169
27293
  * ```
27170
- */
27294
+ *
27295
+ * @title Set variable
27296
+ * @method player.setVariable(key,val)
27297
+ * @param {string} key
27298
+ * @param {any} val
27299
+ * @returns {void}
27300
+ * @memberof VariableManager
27301
+ * */
27171
27302
  setVariable(key, val) {
27172
27303
  this.variables.set(key, val);
27173
27304
  }
27174
27305
  /**
27175
- * Get a variable value
27176
- *
27177
- * Retrieves the value associated with the given key from the player's variables.
27178
- * Returns undefined if the variable doesn't exist. This method is type-safe
27179
- * and can be used with generic types for better TypeScript support.
27180
- *
27181
- * @param key - The variable identifier to retrieve
27182
- * @returns The stored value or undefined if not found
27306
+ * Get a variable
27183
27307
  *
27184
- * @example
27185
27308
  * ```ts
27186
- * // Get variables with type inference
27187
- * const hasKey = player.getVariable('CHEST_OPENED'); // boolean | undefined
27188
- * const level = player.getVariable('playerLevel'); // number | undefined
27189
- * const quest = player.getVariable('questProgress'); // object | undefined
27190
- * const missing = player.getVariable('nonexistent'); // undefined
27191
- *
27192
- * // Use with default values
27193
- * const level = player.getVariable('playerLevel') ?? 1;
27194
- * const isChestOpened = player.getVariable('CHEST_OPENED') ?? false;
27309
+ * const val = player.getVariable('OPEN_CHEST')
27195
27310
  * ```
27196
- */
27311
+ *
27312
+ * @title Get variable
27313
+ * @method player.setVariable(key,val)
27314
+ * @param {string} key
27315
+ * @returns {any}
27316
+ * @memberof VariableManager
27317
+ * */
27197
27318
  getVariable(key) {
27198
27319
  return this.variables.get(key);
27199
27320
  }
27200
27321
  /**
27201
27322
  * Remove a variable
27202
27323
  *
27203
- * Deletes a variable from the player's variable map. This is useful for
27204
- * cleaning up temporary flags, resetting certain game states, or managing
27205
- * memory by removing unused variables. The method returns a boolean indicating
27206
- * whether the variable existed and was successfully removed.
27207
- *
27208
- * @param key - The variable identifier to remove
27209
- * @returns true if a variable existed and has been removed, false if the variable does not exist
27210
- *
27211
- * @example
27212
27324
  * ```ts
27213
- * // Remove variables and check if they existed
27214
- * const removed = player.removeVariable('CHEST_OPENED'); // true if existed
27215
- * const notFound = player.removeVariable('nonexistent'); // false
27216
- *
27217
- * // Clean up temporary variables
27218
- * player.removeVariable('tempQuestFlag');
27219
- * player.removeVariable('battleTempData');
27220
- *
27221
- * // Conditional removal
27222
- * if (player.getVariable('questCompleted')) {
27223
- * player.removeVariable('questProgress');
27224
- * }
27325
+ * player.removeVariable('OPEN_CHEST')
27225
27326
  * ```
27226
- */
27327
+ *
27328
+ * @title Remove variable
27329
+ * @method player.removeVariable(key)
27330
+ * @param {string} key
27331
+ * @returns {boolean} true if a variable existed and has been removed, or false if the variable does not exist.
27332
+ * @memberof VariableManager
27333
+ * */
27227
27334
  removeVariable(key) {
27228
27335
  return this.variables.delete(key);
27229
27336
  }
27230
- /**
27231
- * Check if a variable exists
27232
- *
27233
- * Determines whether a variable with the given key exists in the player's
27234
- * variable map, regardless of its value (including falsy values like false, 0, '').
27235
- * This is useful when you need to distinguish between a variable that doesn't
27236
- * exist and one that has a falsy value.
27237
- *
27238
- * @param key - The variable identifier to check
27239
- * @returns true if the variable exists, false otherwise
27240
- *
27241
- * @example
27242
- * ```ts
27243
- * // Check variable existence
27244
- * player.setVariable('flag', false);
27245
- * player.hasVariable('flag'); // true (even though value is false)
27246
- * player.hasVariable('missing'); // false
27247
- *
27248
- * // Use in conditional logic
27249
- * if (player.hasVariable('questStarted')) {
27250
- * // Quest has been started, check progress
27251
- * const progress = player.getVariable('questProgress');
27252
- * } else {
27253
- * // Quest not started yet
27254
- * player.setVariable('questStarted', true);
27255
- * }
27256
- * ```
27257
- */
27258
- hasVariable(key) {
27259
- return this.variables.has(key);
27260
- }
27261
- /**
27262
- * Get all variable keys
27263
- *
27264
- * Returns an array of all variable keys currently stored for this player.
27265
- * This is useful for debugging, serialization, or iterating over all variables.
27266
- * The keys are returned in insertion order.
27267
- *
27268
- * @returns Array of all variable keys
27269
- *
27270
- * @example
27271
- * ```ts
27272
- * // Get all variable keys
27273
- * const keys = player.getVariableKeys();
27274
- * console.log('Player has variables:', keys);
27275
- *
27276
- * // Iterate over all variables
27277
- * keys.forEach(key => {
27278
- * const value = player.getVariable(key);
27279
- * console.log(`${key}: ${value}`);
27280
- * });
27281
- *
27282
- * // Filter specific variable types
27283
- * const questKeys = keys.filter(key => key.startsWith('quest_'));
27284
- * ```
27285
- */
27286
- getVariableKeys() {
27287
- return Array.from(this.variables.keys());
27288
- }
27289
- /**
27290
- * Clear all variables
27291
- *
27292
- * Removes all variables from the player's variable map. This is useful for
27293
- * resetting the player state, cleaning up before saving, or starting fresh.
27294
- * Use with caution as this operation cannot be undone.
27295
- *
27296
- * @returns void
27297
- *
27298
- * @example
27299
- * ```ts
27300
- * // Clear all variables (use with caution)
27301
- * player.clearVariables();
27302
- *
27303
- * // Clear variables conditionally
27304
- * if (gameReset) {
27305
- * player.clearVariables();
27306
- * // Re-initialize essential variables
27307
- * player.setVariable('gameStarted', true);
27308
- * }
27309
- * ```
27310
- */
27311
- clearVariables() {
27312
- this.variables.clear();
27313
- }
27314
27337
  };
27315
27338
  }
27316
27339
 
@@ -27863,67 +27886,292 @@ class StateLog {
27863
27886
  }
27864
27887
  }
27865
27888
 
27866
- function WithItemManager(Base) {
27889
+ function WithStateManager(Base) {
27867
27890
  return class extends Base {
27891
+ constructor() {
27892
+ super(...arguments);
27893
+ this._statesEfficiency = signal$2([]);
27894
+ }
27868
27895
  /**
27869
- * Retrieves the information of an object: the number and the instance
27870
- * @title Get Item
27871
- * @method player.getItem(itemClass)
27872
- * @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
27873
- * @returns {{ nb: number, item: instance of ItemClass }}
27874
- * @memberof ItemManager
27875
- * @example
27896
+ * Recovers the player's states defense on inventory. This list is generated from the `statesDefense` property defined on the weapons or armors equipped.
27897
+ * If several items have the same element, only the highest rate will be taken into account.
27876
27898
  *
27877
27899
  * ```ts
27878
- * import Potion from 'your-database/potion'
27900
+ * import { Armor, State } from '@rpgjs/server'
27879
27901
  *
27880
- * player.addItem(Potion, 5)
27881
- * const inventory = player.getItem(Potion)
27882
- * console.log(inventory) // { nb: 5, item: <instance of Potion> }
27883
- * ```
27884
- */
27885
- getItem(itemClass) {
27886
- const index = this._getItemIndex(itemClass);
27887
- return this.items()[index];
27902
+ * @State({
27903
+ * name: 'Paralyze'
27904
+ * })
27905
+ * class Paralyze {}
27906
+ *
27907
+ * @Armor({
27908
+ * name: 'Shield',
27909
+ * statesDefense: [{ rate: 1, state: Paralyze }]
27910
+ * })
27911
+ * class Shield {}
27912
+ *
27913
+ * @Armor({
27914
+ * name: 'FireShield',
27915
+ * statesDefense: [{ rate: 0.5, state: Paralyze }]
27916
+ * })
27917
+ * class FireShield {}
27918
+ *
27919
+ * player.addItem(Shield)
27920
+ * player.addItem(FireShield)
27921
+ * player.equip(Shield)
27922
+ * player.equip(FireShield)
27923
+ *
27924
+ * console.log(player.statesDefense) // [{ rate: 1, state: instance of Paralyze }]
27925
+ * ```
27926
+ * @title Get States Defense
27927
+ * @prop {Array<{ rate: number, state: StateClass}>} player.statesDefense
27928
+ * @readonly
27929
+ * @memberof StateManager
27930
+ * */
27931
+ get statesDefense() {
27932
+ return this.getFeature("statesDefense", "state");
27888
27933
  }
27889
27934
  /**
27890
- * Check if the player has the item in his inventory.
27891
- * @title Has Item
27892
- * @method player.hasItem(itemClass)
27893
- * @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
27894
- * @returns {boolean}
27895
- * @memberof ItemManager
27896
- * @example
27935
+ * Set or retrieves all the states where the player is vulnerable or not.
27897
27936
  *
27898
27937
  * ```ts
27899
- * import Potion from 'your-database/potion'
27938
+ * import { Class, State } from '@rpgjs/server'
27900
27939
  *
27901
- * player.hasItem(Potion) // false
27902
- * ```
27903
- */
27904
- hasItem(itemClass) {
27905
- return !!this.getItem(itemClass);
27940
+ * @State({
27941
+ * name: 'Paralyze'
27942
+ * })
27943
+ * class Paralyze {}
27944
+ *
27945
+ * @State({
27946
+ * name: 'Sleep'
27947
+ * })
27948
+ * class Sleep {}
27949
+ *
27950
+ * @Class({
27951
+ * name: 'Fighter',
27952
+ * statesEfficiency: [{ rate: 1, state: Paralyze }]
27953
+ * })
27954
+ * class Hero {}
27955
+ *
27956
+ * player.setClass(Hero)
27957
+ *
27958
+ * console.log(player.statesEfficiency) // [{ rate: 1, instance of Paralyze }]
27959
+ *
27960
+ * player.statesEfficiency = [{ rate: 2, state: Sleep }]
27961
+ *
27962
+ * console.log(player.statesEfficiency) // [{ rate: 1, state: instance of Paralyze }, { rate: 2, state: instance of Sleep }]
27963
+ * ```
27964
+ * @title Set/Get States Efficiency
27965
+ * @prop {Array<{ rate: number, state: StateClass}>} player.statesEfficiency
27966
+ * @memberof StateManager
27967
+ * */
27968
+ get statesEfficiency() {
27969
+ return this._statesEfficiency;
27906
27970
  }
27907
- _getItemIndex(itemClass) {
27908
- return this.items().findIndex((it) => {
27909
- if (isString(itemClass)) {
27910
- return it.id() == itemClass;
27971
+ set statesEfficiency(val) {
27972
+ this._statesEfficiency = val;
27973
+ }
27974
+ applyStates(player, { addStates, removeStates }) {
27975
+ if (addStates) {
27976
+ for (let { state, rate } of addStates) {
27977
+ player.addState(state, rate);
27911
27978
  }
27912
- return isInstanceOf(it, itemClass);
27913
- });
27979
+ }
27980
+ if (removeStates) {
27981
+ for (let { state, rate } of removeStates) {
27982
+ player.removeState(state, rate);
27983
+ }
27984
+ }
27914
27985
  }
27915
27986
  /**
27916
- * Add an item in the player's inventory. You can give more than one by specifying `nb`
27987
+ * Get a state to the player. Returns `null` if the state is not present on the player
27988
+ * ```ts
27989
+ * import Paralyze from 'your-database/states/paralyze'
27917
27990
  *
27918
- * `onAdd()` method is called on the ItemClass
27991
+ * player.getState(Paralyze)
27992
+ * ```
27919
27993
  *
27920
- * @title Add Item
27921
- * @method player.addItem(item,nb=1)
27922
- * @param {ItemClass} itemClass
27923
- * @param {number} [nb] Default 1
27924
- * @returns {{ nb: number, item: instance of ItemClass }}
27925
- * @memberof ItemManager
27926
- * @example
27994
+ * @title Get State
27995
+ * @method player.getState(stateClass)
27996
+ * @param {StateClass | string} stateClass or state id
27997
+ * @returns {instance of StateClass | null}
27998
+ * @memberof StateManager
27999
+ */
28000
+ getState(stateClass) {
28001
+ if (isString(stateClass)) stateClass = this.databaseById(stateClass);
28002
+ return this.states().find((state) => {
28003
+ if (isString(stateClass)) {
28004
+ return state.id == stateClass;
28005
+ }
28006
+ return isInstanceOf(state, stateClass);
28007
+ });
28008
+ }
28009
+ /**
28010
+ * Adds a state to the player. Set the chance between 0 and 1 that the state can apply
28011
+ * ```ts
28012
+ * import Paralyze from 'your-database/states/paralyze'
28013
+ *
28014
+ * try {
28015
+ * player.addState(Paralyze)
28016
+ * }
28017
+ * catch (err) {
28018
+ * console.log(err)
28019
+ * }
28020
+ * ```
28021
+ *
28022
+ * @title Add State
28023
+ * @method player.addState(stateClass,chance=1)
28024
+ * @param {StateClass | string} stateClass state class or state id
28025
+ * @param {number} [chance] 1 by default
28026
+ * @throws {StateLog} addFailed
28027
+ * If the chance to add the state has failed (defined with the `chance` param)
28028
+ * ```
28029
+ * {
28030
+ * id: ADD_STATE_FAILED,
28031
+ * msg: '...'
28032
+ * }
28033
+ * ```
28034
+ * @returns {instance of StateClass}
28035
+ * @memberof StateManager
28036
+ * @todo
28037
+ */
28038
+ addState(stateClass, chance = 1) {
28039
+ const state = this.getState(stateClass);
28040
+ if (isString(stateClass)) {
28041
+ stateClass = this.databaseById(stateClass);
28042
+ }
28043
+ if (!state) {
28044
+ if (Math.random() > chance) {
28045
+ throw StateLog.addFailed(stateClass);
28046
+ }
28047
+ const instance = new stateClass();
28048
+ this.states().push(instance);
28049
+ this.applyStates(this, instance);
28050
+ return instance;
28051
+ }
28052
+ return null;
28053
+ }
28054
+ /**
28055
+ * Remove a state to the player. Set the chance between 0 and 1 that the state can be removed
28056
+ * ```ts
28057
+ * import Paralyze from 'your-database/states/paralyze'
28058
+ *
28059
+ * try {
28060
+ * player.removeState(Paralyze)
28061
+ * }
28062
+ * catch (err) {
28063
+ * console.log(err)
28064
+ * }
28065
+ * ```
28066
+ *
28067
+ * @title Remove State
28068
+ * @method player.removeState(stateClass,chance=1)
28069
+ * @param {StateClass|string} stateClass class state or state id
28070
+ * @param {number} [chance] 1 by default
28071
+ * @throws {StateLog} removeFailed
28072
+ * If the chance to remove the state has failed (defined with the `chance` param)
28073
+ * ```
28074
+ * {
28075
+ * id: REMOVE_STATE_FAILED,
28076
+ * msg: '...'
28077
+ * }
28078
+ * ```
28079
+ * @throws {StateLog} notApplied
28080
+ * If the status does not exist
28081
+ * ```
28082
+ * {
28083
+ * id: STATE_NOT_APPLIED,
28084
+ * msg: '...'
28085
+ * }
28086
+ * ```
28087
+ * @returns {instance of StateClass}
28088
+ * @memberof StateManager
28089
+ */
28090
+ removeState(stateClass, chance = 1) {
28091
+ const index = this.states().findIndex((state) => {
28092
+ if (isString(stateClass)) {
28093
+ return state.id == stateClass;
28094
+ }
28095
+ return isInstanceOf(state, stateClass);
28096
+ });
28097
+ if (index != -1) {
28098
+ if (Math.random() > chance) {
28099
+ throw StateLog.removeFailed(stateClass);
28100
+ }
28101
+ this.states().splice(index, 1);
28102
+ } else {
28103
+ throw StateLog.notApplied(stateClass);
28104
+ }
28105
+ }
28106
+ findStateEfficiency(stateClass) {
28107
+ return this.statesEfficiency().find(
28108
+ (state) => isInstanceOf(state.state, stateClass)
28109
+ );
28110
+ }
28111
+ };
28112
+ }
28113
+
28114
+ function WithItemManager(Base) {
28115
+ return class extends Base {
28116
+ /**
28117
+ * Retrieves the information of an object: the number and the instance
28118
+ * @title Get Item
28119
+ * @method player.getItem(itemClass)
28120
+ * @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
28121
+ * @returns {{ nb: number, item: instance of ItemClass }}
28122
+ * @memberof ItemManager
28123
+ * @example
28124
+ *
28125
+ * ```ts
28126
+ * import Potion from 'your-database/potion'
28127
+ *
28128
+ * player.addItem(Potion, 5)
28129
+ * const inventory = player.getItem(Potion)
28130
+ * console.log(inventory) // { nb: 5, item: <instance of Potion> }
28131
+ * ```
28132
+ */
28133
+ getItem(itemClass) {
28134
+ const index = this._getItemIndex(itemClass);
28135
+ return this.items()[index];
28136
+ }
28137
+ /**
28138
+ * Check if the player has the item in his inventory.
28139
+ * @title Has Item
28140
+ * @method player.hasItem(itemClass)
28141
+ * @param {ItemClass | string} itemClass Identifier of the object if the parameter is a string
28142
+ * @returns {boolean}
28143
+ * @memberof ItemManager
28144
+ * @example
28145
+ *
28146
+ * ```ts
28147
+ * import Potion from 'your-database/potion'
28148
+ *
28149
+ * player.hasItem(Potion) // false
28150
+ * ```
28151
+ */
28152
+ hasItem(itemClass) {
28153
+ return !!this.getItem(itemClass);
28154
+ }
28155
+ _getItemIndex(itemClass) {
28156
+ return this.items().findIndex((it) => {
28157
+ if (isString(itemClass)) {
28158
+ return it.id() == itemClass;
28159
+ }
28160
+ return isInstanceOf(it, itemClass);
28161
+ });
28162
+ }
28163
+ /**
28164
+ * Add an item in the player's inventory. You can give more than one by specifying `nb`
28165
+ *
28166
+ * `onAdd()` method is called on the ItemClass
28167
+ *
28168
+ * @title Add Item
28169
+ * @method player.addItem(item,nb=1)
28170
+ * @param {ItemClass} itemClass
28171
+ * @param {number} [nb] Default 1
28172
+ * @returns {{ nb: number, item: instance of ItemClass }}
28173
+ * @memberof ItemManager
28174
+ * @example
27927
28175
  *
27928
28176
  * ```ts
27929
28177
  * import Potion from 'your-database/potion'
@@ -28334,68 +28582,31 @@ var Effect = /* @__PURE__ */ ((Effect2) => {
28334
28582
  function WithEffectManager(Base) {
28335
28583
  return class extends Base {
28336
28584
  /**
28337
- * Check if the player has a specific effect
28338
- *
28339
- * Determines whether the player currently has the specified effect active.
28340
- * This includes effects from states, equipment, and temporary conditions.
28341
- * The effect system provides a flexible way to apply various gameplay
28342
- * restrictions and enhancements to the player.
28343
- *
28344
- * @param effect - The effect identifier to check for
28345
- * @returns true if the player has the effect, false otherwise
28346
- *
28347
- * @example
28348
28585
  * ```ts
28349
28586
  * import { Effect } from '@rpgjs/database'
28350
28587
  *
28351
- * // Check for skill restriction
28352
- * const cannotUseSkills = player.hasEffect(Effect.CAN_NOT_SKILL);
28353
- * if (cannotUseSkills) {
28354
- * console.log('Player cannot use skills right now');
28355
- * }
28356
- *
28357
- * // Check for guard effect
28358
- * const isGuarding = player.hasEffect(Effect.GUARD);
28359
- * if (isGuarding) {
28360
- * console.log('Player is in guard stance');
28361
- * }
28362
- *
28363
- * // Check for cost reduction
28364
- * const halfCost = player.hasEffect(Effect.HALF_SP_COST);
28365
- * const actualCost = skillCost / (halfCost ? 2 : 1);
28588
+ * const bool = player.hasEffect(Effect.CAN_NOT_SKILL)
28366
28589
  * ```
28367
- */
28590
+ *
28591
+ * @title Has Effect
28592
+ * @method player.hasEffect(effect)
28593
+ * @param {string} effect
28594
+ * @returns {boolean}
28595
+ * @memberof EffectManager
28596
+ * */
28368
28597
  hasEffect(effect) {
28369
28598
  return this.effects.includes(effect);
28370
28599
  }
28371
28600
  /**
28372
28601
  * Retrieves a array of effects assigned to the player, state effects and effects of weapons and armors equipped with the player's own weapons.
28373
28602
  *
28374
- * Gets all currently active effects on the player from multiple sources:
28375
- * - Direct effects assigned to the player
28376
- * - Effects from active states (buffs/debuffs)
28377
- * - Effects from equipped weapons and armor
28378
- * The returned array contains unique effects without duplicates.
28379
- *
28380
- * @returns Array of all active effects on the player
28381
- *
28382
- * @example
28383
28603
  * ```ts
28384
- * // Get all active effects
28385
- * console.log(player.effects); // ['GUARD', 'HALF_SP_COST', ...]
28386
- *
28387
- * // Check multiple effects
28388
- * const effects = player.effects;
28389
- * const hasRestrictions = effects.some(effect =>
28390
- * effect.startsWith('CAN_NOT_')
28391
- * );
28392
- *
28393
- * // Count beneficial effects
28394
- * const beneficialEffects = effects.filter(effect =>
28395
- * ['GUARD', 'SUPER_GUARD', 'HALF_SP_COST'].includes(effect)
28396
- * );
28604
+ * console.log(player.effects)
28397
28605
  * ```
28398
- */
28606
+ * @title Get Effects
28607
+ * @prop {Array<Effect>} player.effects
28608
+ * @memberof EffectManager
28609
+ * */
28399
28610
  get effects() {
28400
28611
  const getEffects = (prop) => {
28401
28612
  return arrayFlat(this[prop]().map((el) => el.effects || []));
@@ -28409,243 +28620,113 @@ function WithEffectManager(Base) {
28409
28620
  /**
28410
28621
  * 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.
28411
28622
  *
28412
- * Sets the direct effects on the player. This only affects the player's own effects
28413
- * and does not modify effects from states or equipment. The total effects will be
28414
- * the combination of these direct effects plus any effects from states and equipment.
28415
- *
28416
- * @param val - Array of effect identifiers to assign to the player
28417
- *
28418
- * @example
28419
28623
  * ```ts
28420
28624
  * import { Effect } from '@rpgjs/database'
28421
28625
  *
28422
- * // Set direct player effects
28423
- * player.effects = [Effect.CAN_NOT_SKILL];
28424
- *
28425
- * // Add multiple effects
28426
- * player.effects = [
28427
- * Effect.GUARD,
28428
- * Effect.HALF_SP_COST,
28429
- * Effect.CAN_NOT_ITEM
28430
- * ];
28431
- *
28432
- * // Clear direct effects (equipment/state effects remain)
28433
- * player.effects = [];
28434
- *
28435
- * // Temporary effect application
28436
- * const originalEffects = player.effects;
28437
- * player.effects = [...originalEffects, Effect.SUPER_GUARD];
28438
- * // Later restore
28439
- * player.effects = originalEffects;
28626
+ * player.effects = [Effect.CAN_NOT_SKILL]
28440
28627
  * ```
28441
- */
28628
+ * @title Set Effects
28629
+ * @prop {Array<Effect>} player.effects
28630
+ * @memberof EffectManager
28631
+ * */
28442
28632
  set effects(val) {
28443
28633
  this._effects.set(val);
28444
28634
  }
28445
28635
  };
28446
28636
  }
28447
28637
 
28448
- function WithElementManager(Base) {
28638
+ function WithBattleManager(Base) {
28449
28639
  return class extends Base {
28450
- constructor() {
28451
- super(...arguments);
28452
- this._elementsEfficiency = [];
28453
- }
28454
28640
  /**
28455
- * Recovers the player's elements defense on inventory. This list is generated from the `elementsDefense` property defined on the weapons or armors equipped.
28456
- * If several items have the same element, only the highest rate will be taken into account.
28457
- *
28458
- * Gets the defensive capabilities against various elements from equipped items.
28459
- * The system automatically consolidates multiple defensive items, keeping only
28460
- * the highest protection rate for each element type. This provides a comprehensive
28461
- * view of the player's elemental resistances from all equipped gear.
28462
- *
28463
- * @returns Array of element defense objects with rate and element properties
28464
- *
28465
- * @example
28466
- * ```ts
28467
- * import { Armor } from '@rpgjs/server'
28468
- *
28469
- * enum Elements {
28470
- * Fire = 'fire'
28471
- * }
28472
- *
28473
- * @Armor({
28474
- * name: 'Shield',
28475
- * elementsDefense: [{ rate: 1, element: Elements.Fire }]
28476
- * })
28477
- * class Shield {}
28478
- *
28479
- * @Armor({
28480
- * name: 'FireShield',
28481
- * elementsDefense: [{ rate: 0.5, element: Elements.Fire }]
28482
- * })
28483
- * class FireShield {}
28484
- *
28485
- * player.addItem(Shield)
28486
- * player.addItem(FireShield)
28487
- * player.equip(Shield)
28488
- * player.equip(FireShield)
28641
+ * Apply damage. Player will lose HP. the `attackerPlayer` parameter is the other player, the one who attacks.
28489
28642
  *
28490
- * console.log(player.elementsDefense) // [{ rate: 1, element: 'fire' }]
28491
- *
28492
- * // Check specific element defense
28493
- * const fireDefense = player.elementsDefense.find(def => def.element === 'fire');
28494
- * if (fireDefense) {
28495
- * console.log(`Fire defense rate: ${fireDefense.rate}`);
28496
- * }
28497
- * ```
28498
- */
28499
- get elementsDefense() {
28500
- return this.getFeature("elementsDefense", "element");
28501
- }
28502
- /**
28503
- * Set or retrieves all the elements where the player is vulnerable or not.
28643
+ * If you don't set the skill parameter, it will be a physical attack.
28644
+ * The attack formula is already defined but you can customize it in the server options
28504
28645
  *
28505
- * Manages the player's elemental efficiency modifiers, which determine how
28506
- * effective different elements are against this player. Values greater than 1
28507
- * indicate vulnerability, while values less than 1 indicate resistance.
28508
- * This combines both class-based efficiency and player-specific modifiers.
28509
- *
28510
- * @returns Array of element efficiency objects with rate and element properties
28511
- *
28512
- * @example
28513
28646
  * ```ts
28514
- * import { Class } from '@rpgjs/server'
28515
- *
28516
- * enum Elements {
28517
- * Fire = 'fire',
28518
- * Ice = 'ice'
28519
- * }
28520
- *
28521
- * @Class({
28522
- * name: 'Fighter',
28523
- * elementsEfficiency: [{ rate: 1, element: Elements.Fire }]
28524
- * })
28525
- * class Hero {}
28526
- *
28527
- * player.setClass(Hero)
28528
- *
28529
- * console.log(player.elementsEfficiency) // [{ rate: 1, element: 'fire' }]
28530
- *
28531
- * player.elementsEfficiency = [{ rate: 2, element: Elements.Ice }]
28532
- *
28533
- * console.log(player.elementsEfficiency) // [{ rate: 1, element: 'fire' }, { rate: 2, element: 'ice' }]
28534
- *
28535
- * // Check for vulnerabilities
28536
- * const vulnerabilities = player.elementsEfficiency.filter(eff => eff.rate > 1);
28537
- * console.log('Vulnerable to:', vulnerabilities.map(v => v.element));
28538
- *
28539
- * // Check for resistances
28540
- * const resistances = player.elementsEfficiency.filter(eff => eff.rate < 1);
28541
- * console.log('Resistant to:', resistances.map(r => r.element));
28647
+ * player.applyDamage(attackerPlayer) // returns { damage: number }
28542
28648
  * ```
28543
- */
28544
- get elementsEfficiency() {
28545
- if (this._class()) {
28546
- return [
28547
- ...this._elementsEfficiency,
28548
- ...this._class()?.elementsEfficiency || []
28549
- ];
28550
- }
28551
- return this._elementsEfficiency;
28552
- }
28553
- set elementsEfficiency(val) {
28554
- this._elementsEfficiency = val;
28555
- }
28556
- /**
28557
- * Retrieves a array of elements assigned to the player and the elements of the weapons / armor equipped
28558
28649
  *
28559
- * Gets all offensive elements available to the player from equipped weapons and armor.
28560
- * This determines what elemental damage types the player can deal in combat.
28561
- * The system automatically combines elements from all equipped items and removes duplicates.
28562
- *
28563
- * @returns Array of element objects with rate and element properties for offensive capabilities
28564
- *
28565
- * @example
28566
- * ```ts
28567
- * // Get all offensive elements
28568
- * console.log(player.elements); // [{ rate: 1.5, element: 'fire' }, { rate: 1.2, element: 'ice' }]
28569
- *
28570
- * // Check if player can deal fire damage
28571
- * const hasFireElement = player.elements.some(el => el.element === 'fire');
28572
- * if (hasFireElement) {
28573
- * console.log('Player can deal fire damage');
28574
- * }
28575
- *
28576
- * // Get strongest element
28577
- * const strongestElement = player.elements.reduce((max, current) =>
28578
- * current.rate > max.rate ? current : max
28579
- * );
28580
- * console.log(`Strongest element: ${strongestElement.element} (${strongestElement.rate})`);
28581
- * ```
28582
- */
28583
- get elements() {
28584
- let elements = [];
28585
- for (let item of this.equipments()) {
28586
- if (item.elements) {
28587
- elements = [...elements, ...item.elements];
28650
+ * @title Apply Damage
28651
+ * @method player.applyDamage(attackerPlayer,skill)
28652
+ * @param {RpgPlayer} attackerPlayer The attacking player
28653
+ * @param {any} [skill]
28654
+ * @returns {object}
28655
+ * @memberof BattleManager
28656
+ * */
28657
+ applyDamage(attackerPlayer, skill) {
28658
+ const getParam = (player) => {
28659
+ const params = {};
28660
+ this.parameters.forEach((val, key) => {
28661
+ params[key] = player.param[key];
28662
+ });
28663
+ return {
28664
+ [ATK]: player.atk,
28665
+ [PDEF]: player.pdef,
28666
+ [SDEF]: player.sdef,
28667
+ ...params
28668
+ };
28669
+ };
28670
+ let damage = 0, fn;
28671
+ let critical = false;
28672
+ let guard = false;
28673
+ let superGuard = false;
28674
+ let elementVulnerable = false;
28675
+ const paramA = getParam(attackerPlayer);
28676
+ const paramB = getParam(this);
28677
+ console.log(paramA, paramB);
28678
+ if (skill) {
28679
+ fn = this.getFormulas("damageSkill");
28680
+ if (!fn) {
28681
+ throw new Error("Skill Formulas not exists");
28588
28682
  }
28589
- }
28590
- return arrayUniq(elements);
28591
- }
28592
- /**
28593
- * Calculate elemental damage coefficient against another player
28594
- *
28595
- * Determines the damage multiplier when this player attacks another player,
28596
- * taking into account the attacker's offensive elements, the defender's
28597
- * elemental efficiency, and elemental defense from equipment. This is used
28598
- * in the battle system to calculate elemental damage modifiers.
28599
- *
28600
- * @param otherPlayer - The target player to calculate coefficient against
28601
- * @returns Numerical coefficient to multiply base damage by
28602
- *
28603
- * @example
28604
- * ```ts
28605
- * // Calculate elemental damage coefficient
28606
- * const firePlayer = new MyPlayer();
28607
- * const icePlayer = new MyPlayer();
28608
- *
28609
- * // Fire player attacks ice player (assuming ice is weak to fire)
28610
- * const coefficient = icePlayer.coefficientElements(firePlayer);
28611
- * console.log(`Damage multiplier: ${coefficient}`); // e.g., 2.0 for double damage
28612
- *
28613
- * // Use in damage calculation
28614
- * const baseDamage = 100;
28615
- * const finalDamage = baseDamage * coefficient;
28616
- * console.log(`Final damage: ${finalDamage}`);
28617
- *
28618
- * // Check for elemental advantage
28619
- * if (coefficient > 1) {
28620
- * console.log('Attacker has elemental advantage!');
28621
- * } else if (coefficient < 1) {
28622
- * console.log('Defender resists this element');
28623
- * }
28624
- * ```
28625
- */
28626
- coefficientElements(otherPlayer) {
28627
- const atkPlayerElements = otherPlayer.elements;
28628
- const playerElements = this.elementsEfficiency;
28629
- let coefficient = 1;
28630
- for (let atkElement of atkPlayerElements) {
28631
- const elementPlayer = playerElements.find(
28632
- (el) => el.element == atkElement.element
28633
- );
28634
- const elementPlayerDef = this.elementsDefense.find(
28635
- (el) => el.element == atkElement.element
28636
- );
28637
- if (!elementPlayer) continue;
28638
- const fn = this.getFormulas("coefficientElements");
28683
+ damage = fn(paramA, paramB, skill);
28684
+ } else {
28685
+ fn = this.getFormulas("damagePhysic");
28639
28686
  if (!fn) {
28640
- return coefficient;
28687
+ throw new Error("Physic Formulas not exists");
28688
+ }
28689
+ damage = fn(paramA, paramB);
28690
+ const coef = this.coefficientElements(attackerPlayer);
28691
+ if (coef >= 2) {
28692
+ elementVulnerable = true;
28693
+ }
28694
+ damage *= coef;
28695
+ fn = this.getFormulas("damageCritical");
28696
+ if (fn) {
28697
+ let newDamage = fn(damage, paramA, paramB);
28698
+ if (damage != newDamage) {
28699
+ critical = true;
28700
+ }
28701
+ damage = newDamage;
28641
28702
  }
28642
- coefficient += fn(
28643
- atkElement,
28644
- elementPlayer,
28645
- elementPlayerDef || { rate: 0 }
28646
- );
28647
28703
  }
28648
- return coefficient;
28704
+ if (this.hasEffect(Effect.GUARD)) {
28705
+ fn = this.getFormulas("damageGuard");
28706
+ if (fn) {
28707
+ let newDamage = fn(damage, paramA, paramB);
28708
+ if (damage != newDamage) {
28709
+ guard = true;
28710
+ }
28711
+ damage = newDamage;
28712
+ }
28713
+ }
28714
+ if (this.hasEffect(Effect.SUPER_GUARD)) {
28715
+ damage /= 4;
28716
+ superGuard = true;
28717
+ }
28718
+ this.hp -= damage;
28719
+ return {
28720
+ damage,
28721
+ critical,
28722
+ elementVulnerable,
28723
+ guard,
28724
+ superGuard
28725
+ };
28726
+ }
28727
+ getFormulas(name) {
28728
+ const map = this.getCurrentMap();
28729
+ return map.damageFormulas[name];
28649
28730
  }
28650
28731
  };
28651
28732
  }
@@ -28864,176 +28945,23 @@ function WithSkillManager(Base) {
28864
28945
  };
28865
28946
  }
28866
28947
 
28867
- function WithBattleManager(Base) {
28868
- return class extends Base {
28869
- /**
28870
- * Apply damage. Player will lose HP. the `attackerPlayer` parameter is the other player, the one who attacks.
28871
- *
28872
- * If you don't set the skill parameter, it will be a physical attack.
28873
- * The attack formula is already defined but you can customize it in the server options.
28874
- * This method handles all aspects of damage calculation including critical hits,
28875
- * elemental vulnerabilities, guard effects, and applies the final damage to HP.
28876
- *
28877
- * @param attackerPlayer - The attacking player who deals the damage
28878
- * @param skill - Optional skill object for magical attacks, if not provided uses physical attack
28879
- * @returns Object containing damage details and special effects that occurred
28880
- *
28881
- * @example
28882
- * ```ts
28883
- * // Physical attack
28884
- * const result = player.applyDamage(attackerPlayer);
28885
- * console.log(`Physical damage: ${result.damage}, Critical: ${result.critical}`);
28886
- *
28887
- * // Magical attack with skill
28888
- * const fireSkill = { id: 'fire', power: 50, element: 'fire' };
28889
- * const magicResult = player.applyDamage(attackerPlayer, fireSkill);
28890
- * console.log(`Magic damage: ${magicResult.damage}, Vulnerable: ${magicResult.elementVulnerable}`);
28891
- *
28892
- * // Check for guard effects
28893
- * if (result.guard) {
28894
- * console.log('Attack was partially blocked!');
28895
- * }
28896
- * if (result.superGuard) {
28897
- * console.log('Attack was heavily reduced by super guard!');
28898
- * }
28899
- * ```
28900
- */
28901
- applyDamage(attackerPlayer, skill) {
28902
- const getParam = (player) => {
28903
- const params = {};
28904
- this.parameters.forEach((val, key) => {
28905
- params[key] = player.param[key];
28906
- });
28907
- return {
28908
- [ATK]: player.atk,
28909
- [PDEF]: player.pdef,
28910
- [SDEF]: player.sdef,
28911
- ...params
28912
- };
28913
- };
28914
- let damage = 0, fn;
28915
- let critical = false;
28916
- let guard = false;
28917
- let superGuard = false;
28918
- let elementVulnerable = false;
28919
- const paramA = getParam(attackerPlayer);
28920
- const paramB = getParam(this);
28921
- console.log(paramA, paramB);
28922
- if (skill) {
28923
- fn = this.getFormulas("damageSkill");
28924
- if (!fn) {
28925
- throw new Error("Skill Formulas not exists");
28926
- }
28927
- damage = fn(paramA, paramB, skill);
28928
- } else {
28929
- fn = this.getFormulas("damagePhysic");
28930
- if (!fn) {
28931
- throw new Error("Physic Formulas not exists");
28932
- }
28933
- damage = fn(paramA, paramB);
28934
- const coef = this.coefficientElements(attackerPlayer);
28935
- if (coef >= 2) {
28936
- elementVulnerable = true;
28937
- }
28938
- damage *= coef;
28939
- fn = this.getFormulas("damageCritical");
28940
- if (fn) {
28941
- let newDamage = fn(damage, paramA, paramB);
28942
- if (damage != newDamage) {
28943
- critical = true;
28944
- }
28945
- damage = newDamage;
28946
- }
28947
- }
28948
- if (this.hasEffect(Effect.GUARD)) {
28949
- fn = this.getFormulas("damageGuard");
28950
- if (fn) {
28951
- let newDamage = fn(damage, paramA, paramB);
28952
- if (damage != newDamage) {
28953
- guard = true;
28954
- }
28955
- damage = newDamage;
28956
- }
28957
- }
28958
- if (this.hasEffect(Effect.SUPER_GUARD)) {
28959
- damage /= 4;
28960
- superGuard = true;
28961
- }
28962
- this.hp -= damage;
28963
- return {
28964
- damage,
28965
- critical,
28966
- elementVulnerable,
28967
- guard,
28968
- superGuard
28969
- };
28970
- }
28971
- /**
28972
- * Get damage formulas from the current map
28973
- *
28974
- * Retrieves the damage calculation formulas defined in the current map's configuration.
28975
- * These formulas are used to calculate different types of damage including physical,
28976
- * magical, critical hits, and guard effects. The formulas provide flexibility in
28977
- * customizing the battle system's damage calculations.
28978
- *
28979
- * @param name - The name of the formula to retrieve (e.g., 'damagePhysic', 'damageSkill')
28980
- * @returns The formula function or undefined if not found
28981
- *
28982
- * @example
28983
- * ```ts
28984
- * // Get physical damage formula
28985
- * const physicFormula = player.getFormulas('damagePhysic');
28986
- * if (physicFormula) {
28987
- * const damage = physicFormula(attackerParams, defenderParams);
28988
- * }
28989
- *
28990
- * // Get critical damage formula
28991
- * const criticalFormula = player.getFormulas('damageCritical');
28992
- * if (criticalFormula) {
28993
- * const criticalDamage = criticalFormula(baseDamage, attackerParams, defenderParams);
28994
- * }
28995
- * ```
28996
- */
28997
- getFormulas(name) {
28998
- const map = this.getCurrentMap();
28999
- return map.damageFormulas[name];
29000
- }
29001
- };
29002
- }
29003
-
29004
28948
  function WithClassManager(Base) {
29005
28949
  return class extends Base {
29006
28950
  /**
29007
28951
  * Assign a class to the player
29008
28952
  *
29009
- * Sets the player's class, which defines their combat abilities, stat growth,
29010
- * and available skills. The class system provides the foundation for character
29011
- * progression and specialization. When a class is set, it automatically triggers
29012
- * the class's onSet method for any additional initialization.
29013
- *
29014
- * @param _class - The class constructor or class ID to assign to the player
29015
- * @returns The instantiated class object
29016
- *
29017
- * @example
29018
28953
  * ```ts
29019
28954
  * import { Fighter } from 'my-database/classes/fighter'
29020
28955
  *
29021
- * // Set class using constructor
29022
- * const fighterClass = player.setClass(Fighter);
29023
- * console.log('Class set:', fighterClass.name);
29024
- *
29025
- * // Set class using string ID
29026
- * player.setClass('fighter');
29027
- *
29028
- * // Class affects available skills and stats
29029
- * console.log('Available skills:', player.skills);
29030
- * console.log('Class bonuses applied to stats');
29031
- *
29032
- * // Class determines level progression
29033
- * player.level = 5;
29034
- * // Skills may be automatically learned based on class definition
28956
+ * player.setClass(Fighter)
29035
28957
  * ```
29036
- */
28958
+ *
28959
+ * @title Set Class
28960
+ * @method player.setClass(ClassClass)
28961
+ * @param {ClassClass | string} class class or id
28962
+ * @returns {instance of ClassClass}
28963
+ * @memberof ClassManager
28964
+ * */
29037
28965
  setClass(_class) {
29038
28966
  if (isString(_class)) _class = this.databaseById(_class);
29039
28967
  const classInstance = new _class();
@@ -29043,39 +28971,18 @@ function WithClassManager(Base) {
29043
28971
  /**
29044
28972
  * Allows to give a set of already defined properties to the player (default equipment, or a list of skills to learn according to the level)
29045
28973
  *
29046
- * Sets up the player as a specific actor archetype, which includes predefined
29047
- * characteristics like starting equipment, parameters, level ranges, and associated class.
29048
- * This is typically used for creating pre-configured character templates or NPCs
29049
- * with specific roles and equipment loadouts.
29050
- *
29051
- * @param actorClass - The actor constructor or actor ID to assign to the player
29052
- * @returns The instantiated actor object
29053
- *
29054
- * @example
29055
28974
  * ```ts
29056
28975
  * import { Hero } from 'my-database/classes/hero'
29057
28976
  *
29058
- * // Set up player as Hero actor
29059
- * const heroActor = player.setActor(Hero);
29060
- * console.log('Actor configured:', heroActor.name);
29061
- *
29062
- * // Actor automatically sets up:
29063
- * // - Starting equipment (sword, armor, etc.)
29064
- * console.log('Starting equipment:', player.equipments());
29065
- *
29066
- * // - Parameter ranges and growth
29067
- * console.log('Level range:', player.initialLevel, '-', player.finalLevel);
29068
- *
29069
- * // - Associated class
29070
- * console.log('Assigned class:', player.class);
29071
- *
29072
- * // - Experience curve
29073
- * console.log('EXP curve:', player.expCurve);
29074
- *
29075
- * // Actor setup is comprehensive
29076
- * player.setActor('hero'); // Can also use string ID
28977
+ * player.setActor(Hero)
29077
28978
  * ```
29078
- */
28979
+ *
28980
+ * @title Set Actor
28981
+ * @method player.setActor(ActorClass)
28982
+ * @param {ActorClass | string} actorClass actor class or id
28983
+ * @returns {instance of ActorClass}
28984
+ * @memberof ClassManager
28985
+ * */
29079
28986
  setActor(actorClass) {
29080
28987
  if (isString(actorClass)) actorClass = this.databaseById(actorClass);
29081
28988
  const actor = new actorClass();
@@ -29096,41 +29003,32 @@ function WithClassManager(Base) {
29096
29003
  };
29097
29004
  }
29098
29005
 
29099
- function WithStateManager(Base) {
29006
+ function WithElementManager(Base) {
29100
29007
  return class extends Base {
29101
29008
  constructor() {
29102
29009
  super(...arguments);
29103
- this._statesEfficiency = signal$2([]);
29010
+ this._elementsEfficiency = [];
29104
29011
  }
29105
29012
  /**
29106
- * Recovers the player's states defense on inventory. This list is generated from the `statesDefense` property defined on the weapons or armors equipped.
29013
+ * Recovers the player's elements defense on inventory. This list is generated from the `elementsDefense` property defined on the weapons or armors equipped.
29107
29014
  * If several items have the same element, only the highest rate will be taken into account.
29108
29015
  *
29109
- * Gets the defensive capabilities against various states from equipped items.
29110
- * The system automatically consolidates multiple defensive items, keeping only
29111
- * the highest protection rate for each state type. This provides comprehensive
29112
- * protection against debuffs and negative status effects.
29113
- *
29114
- * @returns Array of state defense objects with rate and state properties
29115
- *
29116
- * @example
29117
29016
  * ```ts
29118
- * import { Armor, State } from '@rpgjs/server'
29017
+ * import { Armor } from '@rpgjs/server'
29119
29018
  *
29120
- * @State({
29121
- * name: 'Paralyze'
29122
- * })
29123
- * class Paralyze {}
29019
+ * enum Elements {
29020
+ * Fire = 'fire'
29021
+ * }
29124
29022
  *
29125
29023
  * @Armor({
29126
29024
  * name: 'Shield',
29127
- * statesDefense: [{ rate: 1, state: Paralyze }]
29025
+ * elementsDefense: [{ rate: 1, element: Elements.Fire }]
29128
29026
  * })
29129
29027
  * class Shield {}
29130
29028
  *
29131
29029
  * @Armor({
29132
29030
  * name: 'FireShield',
29133
- * statesDefense: [{ rate: 0.5, state: Paralyze }]
29031
+ * elementsDefense: [{ rate: 0.5, element: Elements.Fire }]
29134
29032
  * })
29135
29033
  * class FireShield {}
29136
29034
  *
@@ -29139,291 +29037,100 @@ function WithStateManager(Base) {
29139
29037
  * player.equip(Shield)
29140
29038
  * player.equip(FireShield)
29141
29039
  *
29142
- * console.log(player.statesDefense) // [{ rate: 1, state: instance of Paralyze }]
29143
- *
29144
- * // Check specific state defense
29145
- * const paralyzeDefense = player.statesDefense.find(def => def.state instanceof Paralyze);
29146
- * if (paralyzeDefense) {
29147
- * console.log(`Paralyze defense rate: ${paralyzeDefense.rate}`);
29148
- * }
29040
+ * console.log(player.elementsDefense) // [{ rate: 1, element: 'fire' }]
29149
29041
  * ```
29150
- */
29151
- get statesDefense() {
29152
- return this.getFeature("statesDefense", "state");
29042
+ * @title Get Elements Defense
29043
+ * @prop {Array<{ rate: number, element: Element}>} player.elementsDefense
29044
+ * @readonly
29045
+ * @memberof ElementManager
29046
+ * */
29047
+ get elementsDefense() {
29048
+ return this.getFeature("elementsDefense", "element");
29153
29049
  }
29154
29050
  /**
29155
- * Set or retrieves all the states where the player is vulnerable or not.
29051
+ * Set or retrieves all the elements where the player is vulnerable or not.
29156
29052
  *
29157
- * Manages the player's state efficiency modifiers, which determine how
29158
- * effective different states are against this player. Values greater than 1
29159
- * indicate vulnerability, while values less than 1 indicate resistance.
29160
- * This combines both class-based efficiency and player-specific modifiers.
29161
- *
29162
- * @returns Array of state efficiency objects with rate and state properties
29163
- *
29164
- * @example
29165
29053
  * ```ts
29166
- * import { Class, State } from '@rpgjs/server'
29167
- *
29168
- * @State({
29169
- * name: 'Paralyze'
29170
- * })
29171
- * class Paralyze {}
29054
+ * import { Class } from '@rpgjs/server'
29172
29055
  *
29173
- * @State({
29174
- * name: 'Sleep'
29175
- * })
29176
- * class Sleep {}
29056
+ * enum Elements {
29057
+ * Fire = 'fire',
29058
+ * Ice = 'ice'
29059
+ * }
29177
29060
  *
29178
29061
  * @Class({
29179
29062
  * name: 'Fighter',
29180
- * statesEfficiency: [{ rate: 1, state: Paralyze }]
29063
+ * elementsEfficiency: [{ rate: 1, element: Elements.Fire }]
29181
29064
  * })
29182
29065
  * class Hero {}
29183
29066
  *
29184
29067
  * player.setClass(Hero)
29185
29068
  *
29186
- * console.log(player.statesEfficiency) // [{ rate: 1, instance of Paralyze }]
29069
+ * console.log(player.elementsEfficiency) // [{ rate: 1, element: 'fire' }]
29187
29070
  *
29188
- * player.statesEfficiency = [{ rate: 2, state: Sleep }]
29071
+ * player.elementsEfficiency = [{ rate: 2, element: Elements.Ice }]
29189
29072
  *
29190
- * console.log(player.statesEfficiency) // [{ rate: 1, state: instance of Paralyze }, { rate: 2, state: instance of Sleep }]
29191
- *
29192
- * // Check for vulnerabilities
29193
- * const vulnerabilities = player.statesEfficiency.filter(eff => eff.rate > 1);
29194
- * console.log('Vulnerable to states:', vulnerabilities.map(v => v.state.name));
29195
- *
29196
- * // Check for resistances
29197
- * const resistances = player.statesEfficiency.filter(eff => eff.rate < 1);
29198
- * console.log('Resistant to states:', resistances.map(r => r.state.name));
29199
- * ```
29200
- */
29201
- get statesEfficiency() {
29202
- return this._statesEfficiency;
29203
- }
29204
- set statesEfficiency(val) {
29205
- this._statesEfficiency = val;
29206
- }
29207
- /**
29208
- * Apply states to a player from skill or item effects
29209
- *
29210
- * Processes state application and removal based on skill or item effects.
29211
- * This method handles both adding beneficial states and removing negative ones,
29212
- * with proper chance calculation and resistance checks.
29213
- *
29214
- * @param player - The target player to apply states to
29215
- * @param states - Object containing arrays of states to add or remove
29216
- *
29217
- * @example
29218
- * ```ts
29219
- * // Apply states from a healing skill
29220
- * const healingStates = {
29221
- * addStates: [{ state: Regeneration, rate: 0.8 }],
29222
- * removeStates: [{ state: Poison, rate: 1.0 }]
29223
- * };
29224
- * player.applyStates(targetPlayer, healingStates);
29225
- *
29226
- * // Apply debuff from an enemy attack
29227
- * const debuffStates = {
29228
- * addStates: [
29229
- * { state: Paralyze, rate: 0.3 },
29230
- * { state: Slow, rate: 0.5 }
29231
- * ]
29232
- * };
29233
- * player.applyStates(targetPlayer, debuffStates);
29073
+ * console.log(player.elementsEfficiency) // [{ rate: 1, element: 'fire' }, { rate: 2, element: 'ice' }]
29234
29074
  * ```
29235
- */
29236
- applyStates(player, { addStates, removeStates }) {
29237
- if (addStates) {
29238
- for (let { state, rate } of addStates) {
29239
- player.addState(state, rate);
29240
- }
29241
- }
29242
- if (removeStates) {
29243
- for (let { state, rate } of removeStates) {
29244
- player.removeState(state, rate);
29245
- }
29075
+ * @title Set/Get Elements Efficiency
29076
+ * @prop {Array<{ rate: number, element: Element}>} player.elementsEfficiency
29077
+ * @memberof ElementManager
29078
+ * */
29079
+ get elementsEfficiency() {
29080
+ if (this._class) {
29081
+ return [
29082
+ ...this._elementsEfficiency,
29083
+ ...this._class()?.elementsEfficiency || []
29084
+ ];
29246
29085
  }
29086
+ return this._elementsEfficiency;
29247
29087
  }
29248
- /**
29249
- * Get a state to the player. Returns `null` if the state is not present on the player
29250
- *
29251
- * Retrieves a specific state instance from the player's active states.
29252
- * This is useful for checking state properties, duration, or performing
29253
- * state-specific operations. Returns null if the state is not currently active.
29254
- *
29255
- * @param stateClass - The state class constructor or state ID to search for
29256
- * @returns The state instance if found, null otherwise
29257
- *
29258
- * @example
29259
- * ```ts
29260
- * import Paralyze from 'your-database/states/paralyze'
29261
- *
29262
- * // Check if player has a specific state
29263
- * const paralyzeState = player.getState(Paralyze);
29264
- * if (paralyzeState) {
29265
- * console.log('Player is paralyzed');
29266
- * console.log('Remaining duration:', paralyzeState.duration);
29267
- * }
29268
- *
29269
- * // Check using string ID
29270
- * const poisonState = player.getState('poison');
29271
- * if (poisonState) {
29272
- * console.log('Player is poisoned');
29273
- * }
29274
- *
29275
- * // Use in conditional logic
29276
- * if (player.getState(Sleep)) {
29277
- * console.log('Player cannot act while sleeping');
29278
- * return; // Skip player turn
29279
- * }
29280
- * ```
29281
- */
29282
- getState(stateClass) {
29283
- if (isString(stateClass)) stateClass = this.databaseById(stateClass);
29284
- return this.states().find((state) => {
29285
- if (isString(stateClass)) {
29286
- return state.id == stateClass;
29287
- }
29288
- return isInstanceOf(state, stateClass);
29289
- });
29088
+ set elementsEfficiency(val) {
29089
+ this._elementsEfficiency = val;
29290
29090
  }
29291
29091
  /**
29292
- * Adds a state to the player. Set the chance between 0 and 1 that the state can apply
29293
- *
29294
- * Attempts to apply a state to the player with a specified success chance.
29295
- * The method considers state resistance, efficiency modifiers, and random chance
29296
- * to determine if the state is successfully applied. If successful, the state
29297
- * is added to the player's active states list.
29298
- *
29299
- * @param stateClass - The state class constructor or state ID to apply
29300
- * @param chance - Probability of successful application (0-1, default 1)
29301
- * @returns The state instance if successfully applied, null if already present
29302
- * @throws StateLog.addFailed if the chance roll fails
29303
- *
29304
- * @example
29305
- * ```ts
29306
- * import Paralyze from 'your-database/states/paralyze'
29092
+ * Retrieves a array of elements assigned to the player and the elements of the weapons / armor equipped
29307
29093
  *
29308
- * try {
29309
- * // Attempt to apply paralyze with 100% chance
29310
- * const state = player.addState(Paralyze);
29311
- * if (state) {
29312
- * console.log('Paralyze applied successfully');
29313
- * }
29314
- * } catch (err) {
29315
- * console.log('Failed to apply paralyze:', err.msg);
29316
- * }
29317
- *
29318
- * // Apply with reduced chance
29319
- * try {
29320
- * player.addState(Poison, 0.3); // 30% chance
29321
- * } catch (err) {
29322
- * console.log('Poison application failed');
29323
- * }
29324
- *
29325
- * // Apply multiple states with different chances
29326
- * const debuffs = [
29327
- * { state: Slow, chance: 0.8 },
29328
- * { state: Weak, chance: 0.6 }
29329
- * ];
29330
- * debuffs.forEach(({ state, chance }) => {
29331
- * try {
29332
- * player.addState(state, chance);
29333
- * } catch (err) {
29334
- * // Handle failed applications
29335
- * }
29336
- * });
29094
+ * ```ts
29095
+ * console.log(player.elements)
29337
29096
  * ```
29338
- */
29339
- addState(stateClass, chance = 1) {
29340
- const state = this.getState(stateClass);
29341
- if (isString(stateClass)) {
29342
- stateClass = this.databaseById(stateClass);
29343
- }
29344
- if (!state) {
29345
- if (Math.random() > chance) {
29346
- throw StateLog.addFailed(stateClass);
29097
+ * @title Get Elements
29098
+ * @prop {Array<Element>} player.elements
29099
+ * @readonly
29100
+ * @memberof ElementManager
29101
+ * */
29102
+ get elements() {
29103
+ let elements = [];
29104
+ for (let item of this.equipments()) {
29105
+ if (item.elements) {
29106
+ elements = [...elements, ...item.elements];
29347
29107
  }
29348
- const instance = new stateClass();
29349
- this.states().push(instance);
29350
- this.applyStates(this, instance);
29351
- return instance;
29352
29108
  }
29353
- return null;
29109
+ return arrayUniq(elements);
29354
29110
  }
29355
- /**
29356
- * Remove a state to the player. Set the chance between 0 and 1 that the state can be removed
29357
- *
29358
- * Attempts to remove a state from the player with a specified success chance.
29359
- * This is useful for cure spells, items, or time-based state removal.
29360
- * The method considers removal resistance and random chance.
29361
- *
29362
- * @param stateClass - The state class constructor or state ID to remove
29363
- * @param chance - Probability of successful removal (0-1, default 1)
29364
- * @throws StateLog.removeFailed if the chance roll fails
29365
- * @throws StateLog.notApplied if the state is not currently active
29366
- *
29367
- * @example
29368
- * ```ts
29369
- * import Paralyze from 'your-database/states/paralyze'
29370
- *
29371
- * try {
29372
- * // Attempt to remove paralyze with 100% chance
29373
- * player.removeState(Paralyze);
29374
- * console.log('Paralyze removed successfully');
29375
- * } catch (err) {
29376
- * if (err.id === 'STATE_NOT_APPLIED') {
29377
- * console.log('Player was not paralyzed');
29378
- * } else {
29379
- * console.log('Failed to remove paralyze:', err.msg);
29380
- * }
29381
- * }
29382
- *
29383
- * // Remove with reduced chance (for weak cure spells)
29384
- * try {
29385
- * player.removeState(Poison, 0.7); // 70% chance
29386
- * } catch (err) {
29387
- * console.log('Cure failed');
29388
- * }
29389
- *
29390
- * // Remove all negative states (cure-all effect)
29391
- * const negativeStates = [Poison, Paralyze, Sleep, Slow];
29392
- * negativeStates.forEach(state => {
29393
- * try {
29394
- * player.removeState(state);
29395
- * } catch (err) {
29396
- * // State wasn't active, continue
29397
- * }
29398
- * });
29399
- * ```
29400
- */
29401
- removeState(stateClass, chance = 1) {
29402
- const index = this.states().findIndex((state) => {
29403
- if (isString(stateClass)) {
29404
- return state.id == stateClass;
29405
- }
29406
- return isInstanceOf(state, stateClass);
29407
- });
29408
- if (index != -1) {
29409
- if (Math.random() > chance) {
29410
- throw StateLog.removeFailed(stateClass);
29111
+ coefficientElements(otherPlayer) {
29112
+ const atkPlayerElements = otherPlayer.elements;
29113
+ const playerElements = this.elementsEfficiency;
29114
+ let coefficient = 1;
29115
+ for (let atkElement of atkPlayerElements) {
29116
+ const elementPlayer = playerElements.find(
29117
+ (el) => el.element == atkElement.element
29118
+ );
29119
+ const elementPlayerDef = this.elementsDefense.find(
29120
+ (el) => el.element == atkElement.element
29121
+ );
29122
+ if (!elementPlayer) continue;
29123
+ const fn = this.getFormulas("coefficientElements");
29124
+ if (!fn) {
29125
+ return coefficient;
29411
29126
  }
29412
- this.states().splice(index, 1);
29413
- } else {
29414
- throw StateLog.notApplied(stateClass);
29127
+ coefficient += fn(
29128
+ atkElement,
29129
+ elementPlayer,
29130
+ elementPlayerDef || { rate: 0 }
29131
+ );
29415
29132
  }
29416
- }
29417
- /**
29418
- * Find state efficiency modifier for a specific state class
29419
- *
29420
- * @param stateClass - The state class to find efficiency for
29421
- * @returns The efficiency object if found, undefined otherwise
29422
- */
29423
- findStateEfficiency(stateClass) {
29424
- return this.statesEfficiency().find(
29425
- (state) => isInstanceOf(state.state, stateClass)
29426
- );
29133
+ return coefficient;
29427
29134
  }
29428
29135
  };
29429
29136
  }
@@ -29440,23 +29147,23 @@ var __decorateClass$2 = (decorators, target, key, kind) => {
29440
29147
  function combinePlayerMixins(mixins) {
29441
29148
  return (Base) => mixins.reduce((ExtendedClass, mixin) => mixin(ExtendedClass), Base);
29442
29149
  }
29443
- const BasicPlayerMixins = combinePlayerMixins([
29150
+ const PlayerMixins = combinePlayerMixins([
29444
29151
  WithComponentManager,
29445
29152
  WithEffectManager,
29446
29153
  WithGuiManager,
29447
29154
  WithMoveManager,
29448
29155
  WithGoldManager,
29156
+ WithVariableManager,
29449
29157
  WithParameterManager,
29450
29158
  WithItemFixture,
29451
- WithItemManager,
29452
- WithElementManager,
29453
- WithVariableManager,
29454
29159
  WithStateManager,
29455
- WithClassManager,
29160
+ WithItemManager,
29456
29161
  WithSkillManager,
29457
- WithBattleManager
29162
+ WithClassManager,
29163
+ WithBattleManager,
29164
+ WithElementManager
29458
29165
  ]);
29459
- const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29166
+ const _RpgPlayer = class _RpgPlayer extends PlayerMixins(RpgCommonPlayer) {
29460
29167
  constructor() {
29461
29168
  super();
29462
29169
  this.map = null;
@@ -29525,47 +29232,7 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29525
29232
  value
29526
29233
  });
29527
29234
  }
29528
- /**
29529
- * Set the current animation of the player's sprite
29530
- *
29531
- * This method changes the animation state of the player's current sprite.
29532
- * It's used to trigger character animations like attack, skill, or custom movements.
29533
- * When `nbTimes` is set to a finite number, the animation will play that many times
29534
- * before returning to the previous animation state.
29535
- *
29536
- * @param animationName - The name of the animation to play (e.g., 'attack', 'skill', 'walk')
29537
- * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)
29538
- *
29539
- * @example
29540
- * ```ts
29541
- * // Set continuous walk animation
29542
- * player.setAnimation('walk');
29543
- *
29544
- * // Play attack animation 3 times then return to previous state
29545
- * player.setAnimation('attack', 3);
29546
- *
29547
- * // Play skill animation once
29548
- * player.setAnimation('skill', 1);
29549
- *
29550
- * // Set idle/stand animation
29551
- * player.setAnimation('stand');
29552
- * ```
29553
- */
29554
- setAnimation(animationName, nbTimes = Infinity) {
29555
- const map = this.getCurrentMap();
29556
- if (!map) return;
29557
- if (nbTimes === Infinity) {
29558
- this.animationName.set(animationName);
29559
- } else {
29560
- map.$broadcast({
29561
- type: "setAnimation",
29562
- value: {
29563
- animationName,
29564
- nbTimes,
29565
- object: this.id
29566
- }
29567
- });
29568
- }
29235
+ showAnimation(params) {
29569
29236
  }
29570
29237
  /**
29571
29238
  * Run the change detection cycle. Normally, as soon as a hook is called in a class, the cycle is started. But you can start it manually
@@ -29635,35 +29302,11 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29635
29302
  }
29636
29303
  );
29637
29304
  }
29638
- /**
29639
- * Show a temporary component animation on this player
29640
- *
29641
- * This method broadcasts a component animation to all clients, allowing
29642
- * temporary visual effects like hit indicators, spell effects, or status animations
29643
- * to be displayed on the player.
29644
- *
29645
- * @param id - The ID of the component animation to display
29646
- * @param params - Parameters to pass to the component animation
29647
- *
29648
- * @example
29649
- * ```ts
29650
- * // Show a hit animation with damage text
29651
- * player.showComponentAnimation("hit", {
29652
- * text: "150",
29653
- * color: "red"
29654
- * });
29655
- *
29656
- * // Show a heal animation
29657
- * player.showComponentAnimation("heal", {
29658
- * amount: 50
29659
- * });
29660
- * ```
29661
- */
29662
- showComponentAnimation(id, params) {
29305
+ broadcastEffect(id, params) {
29663
29306
  const map = this.getCurrentMap();
29664
29307
  if (!map) return;
29665
29308
  map.$broadcast({
29666
- type: "showComponentAnimation",
29309
+ type: "showEffect",
29667
29310
  value: {
29668
29311
  id,
29669
29312
  params,
@@ -29671,45 +29314,8 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29671
29314
  }
29672
29315
  });
29673
29316
  }
29674
- /**
29675
- * Display a spritesheet animation on the player
29676
- *
29677
- * This method displays a temporary visual animation using a spritesheet.
29678
- * The animation can either be displayed as an overlay on the player or replace
29679
- * the player's current graphic temporarily. This is useful for spell effects,
29680
- * transformations, or other visual feedback that uses predefined spritesheets.
29681
- *
29682
- * @param graphic - The ID of the spritesheet to use for the animation
29683
- * @param animationName - The name of the animation within the spritesheet (default: 'default')
29684
- * @param replaceGraphic - Whether to replace the player's sprite with the animation (default: false)
29685
- *
29686
- * @example
29687
- * ```ts
29688
- * // Show explosion animation as overlay on player
29689
- * player.showAnimation("explosion");
29690
- *
29691
- * // Show specific spell effect animation
29692
- * player.showAnimation("spell-effects", "fireball");
29693
- *
29694
- * // Transform player graphic temporarily with animation
29695
- * player.showAnimation("transformation", "werewolf", true);
29696
- *
29697
- * // Show healing effect on player
29698
- * player.showAnimation("healing-effects", "holy-light");
29699
- * ```
29700
- */
29701
- showAnimation(graphic, animationName = "default", replaceGraphic = false) {
29702
- if (replaceGraphic) {
29703
- this.setAnimation(animationName, 1);
29704
- return;
29705
- }
29706
- this.showComponentAnimation("animation", {
29707
- graphic,
29708
- animationName
29709
- });
29710
- }
29711
29317
  showHit(text) {
29712
- this.showComponentAnimation("hit", {
29318
+ this.broadcastEffect("hit", {
29713
29319
  text,
29714
29320
  direction: this.direction()
29715
29321
  });
@@ -29737,7 +29343,6 @@ class RpgEvent extends RpgPlayer {
29737
29343
  }
29738
29344
 
29739
29345
  const context$1 = new Context();
29740
- context$1["side"] = "server";
29741
29346
 
29742
29347
  var __defProp$1 = Object.defineProperty;
29743
29348
  var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
@@ -29928,84 +29533,18 @@ let RpgMap = class extends RpgCommonMap {
29928
29533
  removeEvent(eventId) {
29929
29534
  delete this.events()[eventId];
29930
29535
  }
29931
- /**
29932
- * Display a component animation at a specific position on the map
29933
- *
29934
- * This method broadcasts a component animation to all clients connected to the map,
29935
- * allowing temporary visual effects to be displayed at any location on the map.
29936
- * Component animations are custom Canvas Engine components that can display
29937
- * complex effects with custom logic and parameters.
29938
- *
29939
- * @param id - The ID of the component animation to display
29940
- * @param position - The x, y coordinates where to display the animation
29941
- * @param params - Parameters to pass to the component animation
29942
- *
29943
- * @example
29944
- * ```ts
29945
- * // Show explosion at specific coordinates
29946
- * map.showComponentAnimation("explosion", { x: 300, y: 400 }, {
29947
- * intensity: 2.5,
29948
- * duration: 1500
29949
- * });
29950
- *
29951
- * // Show area damage effect
29952
- * map.showComponentAnimation("area-damage", { x: player.x, y: player.y }, {
29953
- * radius: 100,
29954
- * color: "red",
29955
- * damage: 50
29956
- * });
29957
- *
29958
- * // Show treasure spawn effect
29959
- * map.showComponentAnimation("treasure-spawn", { x: 150, y: 200 }, {
29960
- * sparkle: true,
29961
- * sound: "treasure-appear"
29962
- * });
29963
- * ```
29964
- */
29965
- showComponentAnimation(id, position, params) {
29536
+ showAnimation(animationName, object) {
29966
29537
  this.$broadcast({
29967
- type: "showComponentAnimation",
29538
+ type: "showEffect",
29968
29539
  value: {
29969
- id,
29970
- params,
29971
- position
29540
+ id: "animation",
29541
+ params: {
29542
+ name: animationName
29543
+ },
29544
+ object: object.id
29972
29545
  }
29973
29546
  });
29974
29547
  }
29975
- /**
29976
- * Display a spritesheet animation at a specific position on the map
29977
- *
29978
- * This method displays a temporary visual animation using a spritesheet at any
29979
- * location on the map. It's a convenience method that internally uses showComponentAnimation
29980
- * with the built-in 'animation' component. This is useful for spell effects, environmental
29981
- * animations, or any visual feedback that uses predefined spritesheets.
29982
- *
29983
- * @param position - The x, y coordinates where to display the animation
29984
- * @param graphic - The ID of the spritesheet to use for the animation
29985
- * @param animationName - The name of the animation within the spritesheet (default: 'default')
29986
- *
29987
- * @example
29988
- * ```ts
29989
- * // Show explosion at specific coordinates
29990
- * map.showAnimation({ x: 100, y: 200 }, "explosion");
29991
- *
29992
- * // Show spell effect at player position
29993
- * const playerPos = { x: player.x, y: player.y };
29994
- * map.showAnimation(playerPos, "spell-effects", "lightning");
29995
- *
29996
- * // Show environmental effect
29997
- * map.showAnimation({ x: 300, y: 150 }, "nature-effects", "wind-gust");
29998
- *
29999
- * // Show portal opening animation
30000
- * map.showAnimation({ x: 500, y: 400 }, "portals", "opening");
30001
- * ```
30002
- */
30003
- showAnimation(position, graphic, animationName = "default") {
30004
- this.showComponentAnimation("animation", position, {
30005
- graphic,
30006
- animationName
30007
- });
30008
- }
30009
29548
  };
30010
29549
  __decorateClass$1([
30011
29550
  users$1(RpgPlayer)