@rpgjs/server 5.0.0-alpha.5 → 5.0.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Player/BattleManager.d.ts +32 -22
- package/dist/Player/ClassManager.d.ts +31 -18
- package/dist/Player/ComponentManager.d.ts +30 -0
- package/dist/Player/EffectManager.d.ts +40 -0
- package/dist/Player/ElementManager.d.ts +31 -0
- package/dist/Player/GoldManager.d.ts +22 -0
- package/dist/Player/GuiManager.d.ts +31 -0
- package/dist/Player/ItemFixture.d.ts +6 -0
- package/dist/Player/ItemManager.d.ts +27 -13
- package/dist/Player/MoveManager.d.ts +31 -43
- package/dist/Player/ParameterManager.d.ts +27 -19
- package/dist/Player/Player.d.ts +43 -6
- package/dist/Player/SkillManager.d.ts +27 -19
- package/dist/Player/StateManager.d.ts +28 -35
- package/dist/Player/VariableManager.d.ts +30 -0
- package/dist/index.js +984 -536
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/Player/BattleManager.ts +97 -38
- package/src/Player/ClassManager.ts +95 -35
- package/src/Player/ComponentManager.ts +63 -21
- package/src/Player/EffectManager.ts +110 -27
- package/src/Player/ElementManager.ts +126 -25
- package/src/Player/GoldManager.ts +32 -35
- package/src/Player/GuiManager.ts +36 -13
- package/src/Player/ItemFixture.ts +4 -5
- package/src/Player/ItemManager.ts +39 -26
- package/src/Player/MoveManager.ts +40 -31
- package/src/Player/ParameterManager.ts +35 -25
- package/src/Player/Player.ts +75 -35
- package/src/Player/SkillManager.ts +44 -23
- package/src/Player/StateManager.ts +210 -95
- package/src/Player/VariableManager.ts +180 -48
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpgjs/server",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.7",
|
|
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.
|
|
14
|
+
"@rpgjs/common": "5.0.0-alpha.7",
|
|
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
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
*
|
|
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
|
|
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 {
|
|
1
|
+
import { Constructor, PlayerCtor } from "@rpgjs/common";
|
|
2
2
|
import { RpgCommonPlayer } from "@rpgjs/common";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
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
|
|
8
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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>>;
|