@rpgjs/server 5.0.0-alpha.4 → 5.0.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpgjs/server",
3
- "version": "5.0.0-alpha.4",
3
+ "version": "5.0.0-alpha.6",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "publishConfig": {
@@ -11,7 +11,7 @@
11
11
  "license": "MIT",
12
12
  "description": "",
13
13
  "dependencies": {
14
- "@rpgjs/common": "5.0.0-alpha.4",
14
+ "@rpgjs/common": "5.0.0-alpha.6",
15
15
  "@rpgjs/database": "^4.3.0",
16
16
  "@signe/di": "^2.3.2",
17
17
  "@signe/reactive": "^2.3.2",
@@ -1,4 +1,4 @@
1
- import { Constructor, RpgCommonPlayer } from "@rpgjs/common";
1
+ import { Constructor, PlayerCtor, RpgCommonPlayer } from "@rpgjs/common";
2
2
  import { RpgPlayer } from "./Player";
3
3
  import { ATK, PDEF, SDEF } from "../presets";
4
4
  import { Effect } from "./EffectManager";
@@ -9,41 +9,68 @@ interface PlayerWithMixins extends RpgCommonPlayer {
9
9
  hasEffect(effect: string): boolean;
10
10
  coefficientElements(attackerPlayer: RpgPlayer): number;
11
11
  hp: number;
12
- getFormulas(name: string): any;
13
- hasEffect(effect: string): boolean;
14
- }
15
-
16
- export interface IBattleManager {
17
- applyDamage(attackerPlayer: RpgPlayer, skill?: any): {
18
- damage: number;
19
- critical: boolean;
20
- elementVulnerable: boolean;
21
- guard: boolean;
22
- superGuard: boolean;
23
- };
12
+ getCurrentMap(): any;
24
13
  }
25
14
 
26
- export function WithBattleManager<TBase extends Constructor<PlayerWithMixins>>(
27
- Base: TBase
28
- ): Constructor<IBattleManager> & TBase {
29
- return class extends Base implements IBattleManager {
15
+ /**
16
+ * Battle Manager Mixin
17
+ *
18
+ * Provides battle management capabilities to any class. This mixin handles
19
+ * damage calculation, critical hits, elemental vulnerabilities, and guard effects.
20
+ * It implements a comprehensive battle system with customizable formulas and effects.
21
+ *
22
+ * @param Base - The base class to extend with battle management
23
+ * @returns Extended class with battle management methods
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * class MyPlayer extends WithBattleManager(BasePlayer) {
28
+ * constructor() {
29
+ * super();
30
+ * // Battle system is automatically initialized
31
+ * }
32
+ * }
33
+ *
34
+ * const player = new MyPlayer();
35
+ * const attacker = new MyPlayer();
36
+ * const result = player.applyDamage(attacker);
37
+ * console.log(`Damage dealt: ${result.damage}`);
38
+ * ```
39
+ */
40
+ export function WithBattleManager<TBase extends PlayerCtor>(Base: TBase) {
41
+ return class extends Base {
30
42
  /**
31
43
  * Apply damage. Player will lose HP. the `attackerPlayer` parameter is the other player, the one who attacks.
32
44
  *
33
45
  * If you don't set the skill parameter, it will be a physical attack.
34
- * The attack formula is already defined but you can customize it in the server options
46
+ * The attack formula is already defined but you can customize it in the server options.
47
+ * This method handles all aspects of damage calculation including critical hits,
48
+ * elemental vulnerabilities, guard effects, and applies the final damage to HP.
35
49
  *
50
+ * @param attackerPlayer - The attacking player who deals the damage
51
+ * @param skill - Optional skill object for magical attacks, if not provided uses physical attack
52
+ * @returns Object containing damage details and special effects that occurred
53
+ *
54
+ * @example
36
55
  * ```ts
37
- * player.applyDamage(attackerPlayer) // returns { damage: number }
56
+ * // Physical attack
57
+ * const result = player.applyDamage(attackerPlayer);
58
+ * console.log(`Physical damage: ${result.damage}, Critical: ${result.critical}`);
59
+ *
60
+ * // Magical attack with skill
61
+ * const fireSkill = { id: 'fire', power: 50, element: 'fire' };
62
+ * const magicResult = player.applyDamage(attackerPlayer, fireSkill);
63
+ * console.log(`Magic damage: ${magicResult.damage}, Vulnerable: ${magicResult.elementVulnerable}`);
64
+ *
65
+ * // Check for guard effects
66
+ * if (result.guard) {
67
+ * console.log('Attack was partially blocked!');
68
+ * }
69
+ * if (result.superGuard) {
70
+ * console.log('Attack was heavily reduced by super guard!');
71
+ * }
38
72
  * ```
39
- *
40
- * @title Apply Damage
41
- * @method player.applyDamage(attackerPlayer,skill)
42
- * @param {RpgPlayer} attackerPlayer The attacking player
43
- * @param {any} [skill]
44
- * @returns {object}
45
- * @memberof BattleManager
46
- * */
73
+ */
47
74
  applyDamage(
48
75
  attackerPlayer: RpgPlayer,
49
76
  skill?: any
@@ -56,13 +83,13 @@ export function WithBattleManager<TBase extends Constructor<PlayerWithMixins>>(
56
83
  } {
57
84
  const getParam = (player: RpgPlayer) => {
58
85
  const params = {};
59
- this.parameters.forEach((val, key) => {
60
- params[key] = player.param[key];
86
+ (this as any).parameters.forEach((val, key) => {
87
+ params[key] = (player as any).param[key];
61
88
  });
62
89
  return {
63
- [ATK]: player.atk,
64
- [PDEF]: player.pdef,
65
- [SDEF]: player.sdef,
90
+ [ATK]: (player as any).atk,
91
+ [PDEF]: (player as any).pdef,
92
+ [SDEF]: (player as any).sdef,
66
93
  ...params,
67
94
  };
68
95
  };
@@ -87,7 +114,7 @@ export function WithBattleManager<TBase extends Constructor<PlayerWithMixins>>(
87
114
  throw new Error("Physic Formulas not exists");
88
115
  }
89
116
  damage = fn(paramA, paramB);
90
- const coef = this.coefficientElements(attackerPlayer);
117
+ const coef = (this as any).coefficientElements(attackerPlayer);
91
118
  if (coef >= 2) {
92
119
  elementVulnerable = true;
93
120
  }
@@ -101,7 +128,7 @@ export function WithBattleManager<TBase extends Constructor<PlayerWithMixins>>(
101
128
  damage = newDamage;
102
129
  }
103
130
  }
104
- if (this.hasEffect(Effect.GUARD)) {
131
+ if ((this as any).hasEffect(Effect.GUARD)) {
105
132
  fn = this.getFormulas("damageGuard");
106
133
  if (fn) {
107
134
  let newDamage = fn(damage, paramA, paramB);
@@ -111,11 +138,11 @@ export function WithBattleManager<TBase extends Constructor<PlayerWithMixins>>(
111
138
  damage = newDamage;
112
139
  }
113
140
  }
114
- if (this.hasEffect(Effect.SUPER_GUARD)) {
141
+ if ((this as any).hasEffect(Effect.SUPER_GUARD)) {
115
142
  damage /= 4;
116
143
  superGuard = true;
117
144
  }
118
- this.hp -= damage;
145
+ (this as any).hp -= damage;
119
146
  return {
120
147
  damage,
121
148
  critical,
@@ -125,9 +152,41 @@ export function WithBattleManager<TBase extends Constructor<PlayerWithMixins>>(
125
152
  };
126
153
  }
127
154
 
155
+ /**
156
+ * Get damage formulas from the current map
157
+ *
158
+ * Retrieves the damage calculation formulas defined in the current map's configuration.
159
+ * These formulas are used to calculate different types of damage including physical,
160
+ * magical, critical hits, and guard effects. The formulas provide flexibility in
161
+ * customizing the battle system's damage calculations.
162
+ *
163
+ * @param name - The name of the formula to retrieve (e.g., 'damagePhysic', 'damageSkill')
164
+ * @returns The formula function or undefined if not found
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * // Get physical damage formula
169
+ * const physicFormula = player.getFormulas('damagePhysic');
170
+ * if (physicFormula) {
171
+ * const damage = physicFormula(attackerParams, defenderParams);
172
+ * }
173
+ *
174
+ * // Get critical damage formula
175
+ * const criticalFormula = player.getFormulas('damageCritical');
176
+ * if (criticalFormula) {
177
+ * const criticalDamage = criticalFormula(baseDamage, attackerParams, defenderParams);
178
+ * }
179
+ * ```
180
+ */
128
181
  getFormulas(name: string) {
129
- const map = this.getCurrentMap();
182
+ const map = (this as any).getCurrentMap();
130
183
  return map.damageFormulas[name];
131
184
  }
132
- };
185
+ } as unknown as TBase
133
186
  }
187
+
188
+ /**
189
+ * Type helper to extract the interface from the WithBattleManager mixin
190
+ * This provides the type without duplicating method signatures
191
+ */
192
+ export type IBattleManager = InstanceType<ReturnType<typeof WithBattleManager>>;
@@ -1,4 +1,4 @@
1
- import { Constructor, isString, RpgCommonPlayer } from "@rpgjs/common";
1
+ import { Constructor, isString, PlayerCtor, RpgCommonPlayer } from "@rpgjs/common";
2
2
 
3
3
  type ClassClass = any;
4
4
  type ActorClass = any;
@@ -10,69 +10,129 @@ interface PlayerWithMixins extends RpgCommonPlayer {
10
10
  equip(item: any, equip: boolean): void;
11
11
  }
12
12
 
13
- export interface IClassManager {
14
- setClass(_class: ClassClass | string): ClassClass;
15
- setActor(actorClass: ActorClass | string): ActorClass;
16
- }
17
-
18
- export function WithClassManager<TBase extends Constructor<PlayerWithMixins>>(
19
- Base: TBase
20
- ): Constructor<IClassManager> & TBase {
21
- return class extends Base implements IClassManager {
13
+ /**
14
+ * Class Manager Mixin
15
+ *
16
+ * Provides class and actor management capabilities to any class. This mixin handles
17
+ * character class assignment and actor setup, including automatic parameter configuration,
18
+ * starting equipment, and skill progression based on class definitions.
19
+ *
20
+ * @param Base - The base class to extend with class management
21
+ * @returns Extended class with class management methods
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * class MyPlayer extends WithClassManager(BasePlayer) {
26
+ * constructor() {
27
+ * super();
28
+ * // Class system is automatically initialized
29
+ * }
30
+ * }
31
+ *
32
+ * const player = new MyPlayer();
33
+ * player.setClass(Fighter);
34
+ * player.setActor(Hero);
35
+ * ```
36
+ */
37
+ export function WithClassManager<TBase extends PlayerCtor>(Base: TBase) {
38
+ return class extends Base {
22
39
 
23
40
  /**
24
41
  * Assign a class to the player
25
42
  *
43
+ * Sets the player's class, which defines their combat abilities, stat growth,
44
+ * and available skills. The class system provides the foundation for character
45
+ * progression and specialization. When a class is set, it automatically triggers
46
+ * the class's onSet method for any additional initialization.
47
+ *
48
+ * @param _class - The class constructor or class ID to assign to the player
49
+ * @returns The instantiated class object
50
+ *
51
+ * @example
26
52
  * ```ts
27
53
  * import { Fighter } from 'my-database/classes/fighter'
28
54
  *
29
- * player.setClass(Fighter)
55
+ * // Set class using constructor
56
+ * const fighterClass = player.setClass(Fighter);
57
+ * console.log('Class set:', fighterClass.name);
58
+ *
59
+ * // Set class using string ID
60
+ * player.setClass('fighter');
61
+ *
62
+ * // Class affects available skills and stats
63
+ * console.log('Available skills:', player.skills);
64
+ * console.log('Class bonuses applied to stats');
65
+ *
66
+ * // Class determines level progression
67
+ * player.level = 5;
68
+ * // Skills may be automatically learned based on class definition
30
69
  * ```
31
- *
32
- * @title Set Class
33
- * @method player.setClass(ClassClass)
34
- * @param {ClassClass | string} class class or id
35
- * @returns {instance of ClassClass}
36
- * @memberof ClassManager
37
- * */
70
+ */
38
71
  setClass(_class: ClassClass | string) {
39
- if (isString(_class)) _class = this.databaseById(_class);
72
+ if (isString(_class)) _class = (this as any).databaseById(_class);
40
73
  const classInstance = new (_class as ClassClass)();
41
- this["execMethod"]("onSet", [this], classInstance);
74
+ (this as any)["execMethod"]("onSet", [this], classInstance);
42
75
  return classInstance;
43
76
  }
44
77
 
45
78
  /**
46
79
  * 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)
47
80
  *
81
+ * Sets up the player as a specific actor archetype, which includes predefined
82
+ * characteristics like starting equipment, parameters, level ranges, and associated class.
83
+ * This is typically used for creating pre-configured character templates or NPCs
84
+ * with specific roles and equipment loadouts.
85
+ *
86
+ * @param actorClass - The actor constructor or actor ID to assign to the player
87
+ * @returns The instantiated actor object
88
+ *
89
+ * @example
48
90
  * ```ts
49
91
  * import { Hero } from 'my-database/classes/hero'
50
92
  *
51
- * player.setActor(Hero)
93
+ * // Set up player as Hero actor
94
+ * const heroActor = player.setActor(Hero);
95
+ * console.log('Actor configured:', heroActor.name);
96
+ *
97
+ * // Actor automatically sets up:
98
+ * // - Starting equipment (sword, armor, etc.)
99
+ * console.log('Starting equipment:', player.equipments());
100
+ *
101
+ * // - Parameter ranges and growth
102
+ * console.log('Level range:', player.initialLevel, '-', player.finalLevel);
103
+ *
104
+ * // - Associated class
105
+ * console.log('Assigned class:', player.class);
106
+ *
107
+ * // - Experience curve
108
+ * console.log('EXP curve:', player.expCurve);
109
+ *
110
+ * // Actor setup is comprehensive
111
+ * player.setActor('hero'); // Can also use string ID
52
112
  * ```
53
- *
54
- * @title Set Actor
55
- * @method player.setActor(ActorClass)
56
- * @param {ActorClass | string} actorClass actor class or id
57
- * @returns {instance of ActorClass}
58
- * @memberof ClassManager
59
- * */
113
+ */
60
114
  setActor(actorClass: ActorClass | string) {
61
- if (isString(actorClass)) actorClass = this.databaseById(actorClass);
115
+ if (isString(actorClass)) actorClass = (this as any).databaseById(actorClass);
62
116
  const actor = new (actorClass as ActorClass)();
63
117
  ["name", "initialLevel", "finalLevel", "expCurve"].forEach((key) => {
64
- if (actor[key]) this[key] = actor[key];
118
+ if (actor[key]) (this as any)[key] = actor[key];
65
119
  });
66
120
  for (let param in actor.parameters) {
67
- this.addParameter(param, actor.parameters[param]);
121
+ (this as any).addParameter(param, actor.parameters[param]);
68
122
  }
69
123
  for (let item of actor.startingEquipment) {
70
- this.addItem(item);
71
- this.equip(item, true);
124
+ (this as any).addItem(item);
125
+ (this as any).equip(item, true);
72
126
  }
73
127
  if (actor.class) this.setClass(actor.class);
74
- this["execMethod"]("onSet", [this], actor);
128
+ (this as any)["execMethod"]("onSet", [this], actor);
75
129
  return actor;
76
130
  }
77
- };
131
+ } as unknown as TBase;
78
132
  }
133
+
134
+ /**
135
+ * Type helper to extract the interface from the WithClassManager mixin
136
+ * This provides the type without duplicating method signatures
137
+ */
138
+ export type IClassManager = InstanceType<ReturnType<typeof WithClassManager>>;
@@ -1,29 +1,71 @@
1
- import { type Constructor } from "@rpgjs/common";
1
+ import { Constructor, PlayerCtor } from "@rpgjs/common";
2
2
  import { RpgCommonPlayer } from "@rpgjs/common";
3
3
 
4
4
  /**
5
- * Interface defining what ComponentManager adds to a class
5
+ * Component Manager Mixin
6
+ *
7
+ * Provides graphic management capabilities to any class. This mixin allows
8
+ * setting single or multiple graphics for player representation, enabling
9
+ * dynamic visual changes and animation sequences.
10
+ *
11
+ * @param Base - The base class to extend with component management
12
+ * @returns Extended class with component management methods
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * class MyPlayer extends WithComponentManager(BasePlayer) {
17
+ * constructor() {
18
+ * super();
19
+ * this.setGraphic("hero");
20
+ * }
21
+ * }
22
+ *
23
+ * const player = new MyPlayer();
24
+ * player.setGraphic(["hero_idle", "hero_walk"]);
25
+ * ```
6
26
  */
7
- export interface IComponentManager {
8
- setGraphic(graphic: string | string[]): void;
27
+ export function WithComponentManager<TBase extends PlayerCtor>(Base: TBase) {
28
+ return class extends Base {
29
+ /**
30
+ * Set the graphic(s) for this player
31
+ *
32
+ * Allows setting either a single graphic or multiple graphics for the player.
33
+ * When multiple graphics are provided, they are used for animation sequences.
34
+ * The graphics system provides flexible visual representation that can be
35
+ * dynamically changed during gameplay for different states, equipment, or animations.
36
+ *
37
+ * @param graphic - Single graphic name or array of graphic names for animation sequences
38
+ * @returns void
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * // Set a single graphic for static representation
43
+ * player.setGraphic("hero");
44
+ *
45
+ * // Set multiple graphics for animation sequences
46
+ * player.setGraphic(["hero_idle", "hero_walk", "hero_run"]);
47
+ *
48
+ * // Dynamic graphic changes based on equipment
49
+ * if (player.hasArmor('platemail')) {
50
+ * player.setGraphic("hero_armored");
51
+ * }
52
+ *
53
+ * // Animation sequences for different actions
54
+ * player.setGraphic(["mage_cast_1", "mage_cast_2", "mage_cast_3"]);
55
+ * ```
56
+ */
57
+ setGraphic(graphic: string | string[]): void {
58
+ if (Array.isArray(graphic)) {
59
+ this.graphics.set(graphic);
60
+ } else {
61
+ this.graphics.set([graphic]);
62
+ }
63
+ }
64
+ } as unknown as TBase;
9
65
  }
10
66
 
11
67
  /**
12
- * Component Manager mixin
13
- *
14
- * Adds methods to manage player graphics
15
- *
16
- * @param Base - The base class to extend
17
- * @returns A new class with component management capabilities
68
+ * Type helper to extract the interface from the WithComponentManager mixin
69
+ * This provides the type without duplicating method signatures
18
70
  */
19
- export function WithComponentManager<TBase extends Constructor<RpgCommonPlayer>>(Base: TBase) {
20
- return class extends Base implements IComponentManager {
21
- setGraphic(graphic: string | string[]) {
22
- if (Array.isArray(graphic)) {
23
- this.graphics.set(graphic);
24
- } else {
25
- this.graphics.set([graphic]);
26
- }
27
- }
28
- };
29
- }
71
+ export type IComponentManager = InstanceType<ReturnType<typeof WithComponentManager>>;
@@ -2,13 +2,10 @@ import {
2
2
  arrayFlat,
3
3
  arrayUniq,
4
4
  Constructor,
5
+ PlayerCtor,
5
6
  RpgCommonPlayer,
6
7
  } from "@rpgjs/common";
7
8
 
8
- export interface IWithEffectManager {
9
- effects: any[];
10
- }
11
-
12
9
  export enum Effect {
13
10
  CAN_NOT_SKILL = 'CAN_NOT_SKILL',
14
11
  CAN_NOT_ITEM = 'CAN_NOT_ITEM',
@@ -19,23 +16,64 @@ export enum Effect {
19
16
  SUPER_GUARD = 'SUPER_GUARD'
20
17
  }
21
18
 
22
- export function WithEffectManager<TBase extends Constructor<RpgCommonPlayer>>(
23
- Base: TBase
24
- ) {
25
- return class extends Base implements IWithEffectManager {
19
+ /**
20
+ * Effect Manager Mixin
21
+ *
22
+ * Provides effect management capabilities to any class. This mixin handles
23
+ * player effects including restrictions, buffs, and debuffs. Effects can come
24
+ * from various sources like states, equipment, and temporary conditions.
25
+ *
26
+ * @param Base - The base class to extend with effect management
27
+ * @returns Extended class with effect management methods
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * class MyPlayer extends WithEffectManager(BasePlayer) {
32
+ * constructor() {
33
+ * super();
34
+ * // Effect system is automatically initialized
35
+ * }
36
+ * }
37
+ *
38
+ * const player = new MyPlayer();
39
+ * player.effects = [Effect.GUARD];
40
+ * console.log(player.hasEffect(Effect.GUARD)); // true
41
+ * ```
42
+ */
43
+ export function WithEffectManager<TBase extends PlayerCtor>(Base: TBase) {
44
+ return class extends Base {
26
45
  /**
46
+ * Check if the player has a specific effect
47
+ *
48
+ * Determines whether the player currently has the specified effect active.
49
+ * This includes effects from states, equipment, and temporary conditions.
50
+ * The effect system provides a flexible way to apply various gameplay
51
+ * restrictions and enhancements to the player.
52
+ *
53
+ * @param effect - The effect identifier to check for
54
+ * @returns true if the player has the effect, false otherwise
55
+ *
56
+ * @example
27
57
  * ```ts
28
58
  * import { Effect } from '@rpgjs/database'
29
59
  *
30
- * const bool = player.hasEffect(Effect.CAN_NOT_SKILL)
60
+ * // Check for skill restriction
61
+ * const cannotUseSkills = player.hasEffect(Effect.CAN_NOT_SKILL);
62
+ * if (cannotUseSkills) {
63
+ * console.log('Player cannot use skills right now');
64
+ * }
65
+ *
66
+ * // Check for guard effect
67
+ * const isGuarding = player.hasEffect(Effect.GUARD);
68
+ * if (isGuarding) {
69
+ * console.log('Player is in guard stance');
70
+ * }
71
+ *
72
+ * // Check for cost reduction
73
+ * const halfCost = player.hasEffect(Effect.HALF_SP_COST);
74
+ * const actualCost = skillCost / (halfCost ? 2 : 1);
31
75
  * ```
32
- *
33
- * @title Has Effect
34
- * @method player.hasEffect(effect)
35
- * @param {string} effect
36
- * @returns {boolean}
37
- * @memberof EffectManager
38
- * */
76
+ */
39
77
  hasEffect(effect: string): boolean {
40
78
  return this.effects.includes(effect);
41
79
  }
@@ -43,13 +81,31 @@ export function WithEffectManager<TBase extends Constructor<RpgCommonPlayer>>(
43
81
  /**
44
82
  * Retrieves a array of effects assigned to the player, state effects and effects of weapons and armors equipped with the player's own weapons.
45
83
  *
84
+ * Gets all currently active effects on the player from multiple sources:
85
+ * - Direct effects assigned to the player
86
+ * - Effects from active states (buffs/debuffs)
87
+ * - Effects from equipped weapons and armor
88
+ * The returned array contains unique effects without duplicates.
89
+ *
90
+ * @returns Array of all active effects on the player
91
+ *
92
+ * @example
46
93
  * ```ts
47
- * console.log(player.effects)
94
+ * // Get all active effects
95
+ * console.log(player.effects); // ['GUARD', 'HALF_SP_COST', ...]
96
+ *
97
+ * // Check multiple effects
98
+ * const effects = player.effects;
99
+ * const hasRestrictions = effects.some(effect =>
100
+ * effect.startsWith('CAN_NOT_')
101
+ * );
102
+ *
103
+ * // Count beneficial effects
104
+ * const beneficialEffects = effects.filter(effect =>
105
+ * ['GUARD', 'SUPER_GUARD', 'HALF_SP_COST'].includes(effect)
106
+ * );
48
107
  * ```
49
- * @title Get Effects
50
- * @prop {Array<Effect>} player.effects
51
- * @memberof EffectManager
52
- * */
108
+ */
53
109
  get effects(): any[] {
54
110
  const getEffects = (prop) => {
55
111
  return arrayFlat(this[prop]().map((el) => el.effects || []));
@@ -64,17 +120,44 @@ export function WithEffectManager<TBase extends Constructor<RpgCommonPlayer>>(
64
120
  /**
65
121
  * 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.
66
122
  *
123
+ * Sets the direct effects on the player. This only affects the player's own effects
124
+ * and does not modify effects from states or equipment. The total effects will be
125
+ * the combination of these direct effects plus any effects from states and equipment.
126
+ *
127
+ * @param val - Array of effect identifiers to assign to the player
128
+ *
129
+ * @example
67
130
  * ```ts
68
131
  * import { Effect } from '@rpgjs/database'
69
132
  *
70
- * player.effects = [Effect.CAN_NOT_SKILL]
133
+ * // Set direct player effects
134
+ * player.effects = [Effect.CAN_NOT_SKILL];
135
+ *
136
+ * // Add multiple effects
137
+ * player.effects = [
138
+ * Effect.GUARD,
139
+ * Effect.HALF_SP_COST,
140
+ * Effect.CAN_NOT_ITEM
141
+ * ];
142
+ *
143
+ * // Clear direct effects (equipment/state effects remain)
144
+ * player.effects = [];
145
+ *
146
+ * // Temporary effect application
147
+ * const originalEffects = player.effects;
148
+ * player.effects = [...originalEffects, Effect.SUPER_GUARD];
149
+ * // Later restore
150
+ * player.effects = originalEffects;
71
151
  * ```
72
- * @title Set Effects
73
- * @prop {Array<Effect>} player.effects
74
- * @memberof EffectManager
75
- * */
152
+ */
76
153
  set effects(val) {
77
154
  this._effects.set(val);
78
155
  }
79
- };
156
+ } as unknown as TBase;
80
157
  }
158
+
159
+ /**
160
+ * Type helper to extract the interface from the WithEffectManager mixin
161
+ * This provides the type without duplicating method signatures
162
+ */
163
+ export type IEffectManager = InstanceType<ReturnType<typeof WithEffectManager>>;