enefel 2.9.1 → 2.11.0
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/.claude/settings.local.json +7 -0
- package/2025/newSkills.ts +769 -0
- package/2025/raceMigration.ts +66 -0
- package/2025/rawTeamsData.ts +1726 -0
- package/2025/skillMigration.ts +155 -0
- package/avatarsSeason.ts +61 -0
- package/career.ts +64 -8
- package/career2025.ts +2752 -0
- package/dice.ts +40 -8
- package/dist/2025/newSkills.d.ts +10 -0
- package/dist/2025/newSkills.js +663 -0
- package/dist/2025/raceMigration.d.ts +10 -0
- package/dist/2025/raceMigration.js +53 -0
- package/dist/2025/rawTeamsData.d.ts +12 -0
- package/dist/2025/rawTeamsData.js +1699 -0
- package/dist/2025/skillMigration.d.ts +31 -0
- package/dist/2025/skillMigration.js +95 -0
- package/dist/avatarsSeason.d.ts +22 -0
- package/dist/avatarsSeason.js +54 -0
- package/dist/career.d.ts +13 -4
- package/dist/career.js +36 -7
- package/dist/career2025.d.ts +192 -0
- package/dist/career2025.js +2611 -0
- package/dist/dice.d.ts +10 -2
- package/dist/dice.js +31 -8
- package/dist/index.d.ts +17 -2
- package/dist/index.js +44 -5
- package/dist/move.d.ts +6 -2
- package/dist/move.js +35 -0
- package/dist/package-lock.json +913 -7
- package/dist/package.json +6 -2
- package/dist/pitch.d.ts +10 -1
- package/dist/pitch.js +16 -0
- package/dist/player.d.ts +8 -4
- package/dist/player.js +104 -20
- package/dist/position.d.ts +4 -0
- package/dist/position.js +17 -1
- package/dist/race.d.ts +23 -12
- package/dist/race.js +210 -2
- package/dist/skill.d.ts +26 -3
- package/dist/skill.js +199 -81
- package/dist/skills/hitAndRun.d.ts +10 -0
- package/dist/skills/hitAndRun.js +12 -0
- package/dist/skills/safePairOfHands.d.ts +28 -0
- package/dist/skills/safePairOfHands.js +18 -0
- package/dist/skills/sidestep.d.ts +21 -0
- package/dist/skills/sidestep.js +20 -0
- package/dist/status.d.ts +4 -1
- package/dist/status.js +14 -4
- package/dist/store.d.ts +3 -0
- package/dist/store.js +3 -0
- package/dist/teams/career_v2025.d.ts +246 -0
- package/dist/teams/career_v2025.js +3512 -0
- package/dist/teams/convert-csv-to-career.d.ts +1 -0
- package/dist/teams/convert-csv-to-career.js +1085 -0
- package/dist/types/models.d.ts +4 -0
- package/index.ts +57 -4
- package/jest.config.js +3 -0
- package/move.ts +50 -2
- package/npm-login.sh +0 -0
- package/package.json +6 -2
- package/pitch.ts +22 -0
- package/player.ts +105 -22
- package/position.ts +16 -0
- package/race.ts +227 -13
- package/skill.ts +217 -83
- package/skills/hitAndRun.ts +14 -0
- package/skills/safePairOfHands.ts +33 -0
- package/skills/sidestep.ts +25 -0
- package/status.ts +15 -3
- package/store.ts +3 -0
- package/teams/README.md +53 -0
- package/teams/clean-stats.js +54 -0
- package/teams/convert-csv-to-career.ts +1209 -0
- package/teams/players_clean.csv +107 -0
- package/teams/players_next.csv +21 -0
- package/types/models.ts +4 -0
package/race.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import alea from "seedrandom";
|
|
2
2
|
import { AVATAR_LIST } from "./avatars";
|
|
3
3
|
import { AVATAR_DEFAULT_LIST } from "./avatarsDefault";
|
|
4
|
+
import { findSeasonAvatar, getSeasonAvatarPath } from "./avatarsSeason";
|
|
4
5
|
import { BADGE_NAMES, hasBadge } from "./badge";
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
AVATAR,
|
|
8
|
+
CAREER_ID_ALL,
|
|
9
|
+
getAvailableCareers,
|
|
10
|
+
getCareers,
|
|
11
|
+
RACE,
|
|
12
|
+
} from "./career";
|
|
6
13
|
import { getRandomNumber } from "./random";
|
|
7
14
|
import { isSpecialSkill, SKILL_NAMES } from "./skill";
|
|
8
15
|
import { canBeSelectedByUser } from "./state";
|
|
@@ -91,19 +98,152 @@ const hasUnlockCareer = (user: User, careerId: string) => {
|
|
|
91
98
|
if (!user.badges) {
|
|
92
99
|
throw Error("no badges for player");
|
|
93
100
|
}
|
|
94
|
-
const race = getRaceFromCareer(careerId as
|
|
101
|
+
const race = getRaceFromCareer(careerId as CAREER_ID_ALL);
|
|
95
102
|
|
|
96
|
-
return hasUnlockRace(user, race);
|
|
103
|
+
return hasUnlockRace(user, race as RACE);
|
|
97
104
|
};
|
|
98
105
|
|
|
99
|
-
const getCareerFromKey = (key:
|
|
106
|
+
const getCareerFromKey = (key: CAREER_ID_ALL) => {
|
|
100
107
|
const careers = getCareers();
|
|
101
108
|
return careers[key];
|
|
102
109
|
};
|
|
103
110
|
|
|
104
111
|
const getCareerKeyFromPlayer = (player: Player) => {
|
|
105
112
|
// Attention la career est le race_id dans la table player
|
|
106
|
-
return player.race_id as
|
|
113
|
+
return player.race_id as CAREER_ID_ALL;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Maps legacy (pre-2025) career IDs to their 2025 equivalents.
|
|
118
|
+
* Derived by inverting the ICON_ADAPTER from convert-csv-to-career.ts:
|
|
119
|
+
* old icon name (strip "1") → new 2025 career ID
|
|
120
|
+
*/
|
|
121
|
+
const LEGACY_TO_2025_CAREER_ID: Record<string, string> = {
|
|
122
|
+
// Amazon
|
|
123
|
+
"amazon-linewomen": "amazon-linewoman-2025",
|
|
124
|
+
"amazon-blocker": "amazon-blocker-2025",
|
|
125
|
+
"amazon-blitzer": "amazon-blitzer-2025",
|
|
126
|
+
"amazon-catcher": "amazon-catcher-2025",
|
|
127
|
+
"amazon-thrower": "amazon-thrower-2025",
|
|
128
|
+
// Chaos Chosen
|
|
129
|
+
"chaos-beastman": "chaos-chosen-beastman-2025",
|
|
130
|
+
"chaos-warrior": "chaos-chosen-chosen-2025",
|
|
131
|
+
"chaos-minotaur": "chaos-chosen-minotaur-2025",
|
|
132
|
+
// Chaos Dwarf
|
|
133
|
+
"chaos-dwarf-blocker": "chaos-dwarf-blocker-2025",
|
|
134
|
+
"chaos-dwarf-bull-centaur": "chaos-dwarf-bull-centaur-2025",
|
|
135
|
+
"chaos-dwarf-hobgobelin": "chaos-dwarf-hobgoblin-2025",
|
|
136
|
+
// Dark Elf
|
|
137
|
+
"dark-elfe-blitzer": "dark-elf-blitzer-2025",
|
|
138
|
+
"dark-elfe-lineman": "dark-elf-lineman-2025",
|
|
139
|
+
"dark-elfe-runner": "dark-elf-runner-2025",
|
|
140
|
+
"dark-elfe-witch": "dark-elf-witch-elf-2025",
|
|
141
|
+
// Dwarf
|
|
142
|
+
"dwarf": "dwarf-lineman-2025",
|
|
143
|
+
"dwarf-blocker": "dwarf-lineman-2025",
|
|
144
|
+
"dwarf-blitzer": "dwarf-blitzer-2025",
|
|
145
|
+
"dwarf-deathroller": "dwarf-deathroller-2025",
|
|
146
|
+
"dwarf-runner": "dwarf-runner-2025",
|
|
147
|
+
"dwarf-troll-slayer": "dwarf-troll-slayer-2025",
|
|
148
|
+
// Elven Union
|
|
149
|
+
"elven-union-blitzer": "elven-union-blitzer-2025",
|
|
150
|
+
"elven-union-catcher": "elven-union-catcher-2025",
|
|
151
|
+
"elven-union-lineman": "elven-union-lineman-2025",
|
|
152
|
+
"elven-union-thrower": "elven-union-thrower-2025",
|
|
153
|
+
// Goblin
|
|
154
|
+
"gobelin-lineman": "goblin-lineman-2025",
|
|
155
|
+
"gobelin-looney": "goblin-loony-2025",
|
|
156
|
+
"gobelin-pogoer": "goblin-pogoer-2025",
|
|
157
|
+
"gobelin-troll": "goblin-troll-2025",
|
|
158
|
+
// Halfling
|
|
159
|
+
"halfling-lineman": "halfling-lineman-2025",
|
|
160
|
+
"halfling-hefty": "halfling-hefty-2025",
|
|
161
|
+
"halfling-catcher": "halfling-catcher-2025",
|
|
162
|
+
"halfling-treeman": "halfling-treeman-2025",
|
|
163
|
+
// Human
|
|
164
|
+
"human": "human-lineman-2025",
|
|
165
|
+
"human-lineman": "human-lineman-2025",
|
|
166
|
+
"human-blitzer": "human-blitzer-2025",
|
|
167
|
+
"human-catcher": "human-catcher-2025",
|
|
168
|
+
"human-ogre": "human-ogre-2025",
|
|
169
|
+
"human-thrower": "human-thrower-2025",
|
|
170
|
+
// Imperial Nobility
|
|
171
|
+
"imperial-lineman": "imperial-nobility-retainer-2025",
|
|
172
|
+
"imperial-blitzer": "imperial-nobility-blitzer-2025",
|
|
173
|
+
"imperial-bodyguard": "imperial-nobility-bodyguard-2025",
|
|
174
|
+
"imperial-ogre": "imperial-nobility-ogre-2025",
|
|
175
|
+
"imperial-thrower": "imperial-nobility-thrower-2025",
|
|
176
|
+
// Khorne
|
|
177
|
+
"khorne-lineman": "khorne-marauder-2025",
|
|
178
|
+
"khorne-khorngor": "khorne-khorngor-2025",
|
|
179
|
+
"khorne-bloodseeker": "khorne-bloodseeker-2025",
|
|
180
|
+
"khorne-bloodspawn": "khorne-bloodspawn-2025",
|
|
181
|
+
// Lizardmen
|
|
182
|
+
"lizardmen-chameleon": "lizardmen-chameleon-2025",
|
|
183
|
+
"lizardmen-kroxigor": "lizardmen-kroxigor-2025",
|
|
184
|
+
"lizardmen-saurus": "lizardmen-saurus-2025",
|
|
185
|
+
"lizardmen-skink": "lizardmen-skink-2025",
|
|
186
|
+
// Necromantic
|
|
187
|
+
"necromantic-zombie": "necromantic-horror-zombie-2025",
|
|
188
|
+
"necromantic-ghoul": "necromantic-horror-ghoul-2025",
|
|
189
|
+
"necromantic-wraith": "necromantic-horror-wraith-2025",
|
|
190
|
+
"necromantic-werewolf": "necromantic-horror-werewolf-2025",
|
|
191
|
+
"necromantic-golem": "necromantic-horror-flesh-golem-2025",
|
|
192
|
+
// Norse
|
|
193
|
+
"norse-lineman": "norse-raider-2025",
|
|
194
|
+
"norse-berserker": "norse-berserker-2025",
|
|
195
|
+
"norse-catcher": "norse-catcher-2025",
|
|
196
|
+
"norse-thrower": "norse-thrower-2025",
|
|
197
|
+
"norse-ulfwereners": "norse-ulfwerner-2025",
|
|
198
|
+
"norse-yhetee": "norse-yhetee-2025",
|
|
199
|
+
// Nurgle
|
|
200
|
+
"nurgle-rotter": "nurgle-rotter-2025",
|
|
201
|
+
"nurgle-pestigor": "nurgle-pestigor-2025",
|
|
202
|
+
"nurgle-bloater": "nurgle-bloater-2025",
|
|
203
|
+
"nurgle-rotspawn": "nurgle-rotspawn-2025",
|
|
204
|
+
// Orc
|
|
205
|
+
"orc": "orc-lineman-2025",
|
|
206
|
+
"orc-lineman": "orc-lineman-2025",
|
|
207
|
+
"orc-black-orc": "orc-big-un-2025",
|
|
208
|
+
"orc-blitzer": "orc-blitzer-2025",
|
|
209
|
+
"orc-thrower": "orc-thrower-2025",
|
|
210
|
+
"orc-troll": "orc-troll-2025",
|
|
211
|
+
// Skaven (anciens "rat")
|
|
212
|
+
"rat": "skaven-clanrat-2025",
|
|
213
|
+
"rat-lineman": "skaven-clanrat-2025",
|
|
214
|
+
"rat-runner": "skaven-gutter-2025",
|
|
215
|
+
"rat-blitzer": "skaven-blitzer-2025",
|
|
216
|
+
"rat-thrower": "skaven-thrower-2025",
|
|
217
|
+
"rat-ogre": "skaven-rat-ogre-2025",
|
|
218
|
+
// Shambling Undead (anciens "undead")
|
|
219
|
+
"undead-skeleton": "shambling-undead-skeleton-2025",
|
|
220
|
+
"undead-zombie": "shambling-undead-zombie-2025",
|
|
221
|
+
"undead-ghoul": "shambling-undead-ghoul-2025",
|
|
222
|
+
"undead-wight": "shambling-undead-wight-2025",
|
|
223
|
+
"undead-mummies": "shambling-undead-mummy-2025",
|
|
224
|
+
// Snotling
|
|
225
|
+
"snotling-lineman": "snotling-lineman-2025",
|
|
226
|
+
"snotling-runner": "snotling-runna-2025",
|
|
227
|
+
"snotling-wagon": "snotling-pump-wagon-2025",
|
|
228
|
+
"snotling-troll": "snotling-troll-2025",
|
|
229
|
+
// Vampire
|
|
230
|
+
"vampire-thrall": "vampire-thrall-2025",
|
|
231
|
+
"vampire-vampire": "vampire-blitzer-2025",
|
|
232
|
+
// Wood Elf (anciens "silvan")
|
|
233
|
+
"silvan": "wood-elf-lineman-2025",
|
|
234
|
+
"silvan-lineman": "wood-elf-lineman-2025",
|
|
235
|
+
"silvan-thrower": "wood-elf-thrower-2025",
|
|
236
|
+
"silvan-catcher": "wood-elf-catcher-2025",
|
|
237
|
+
"silvan-wardancer": "wood-elf-wardancer-2025",
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Returns the 2025 career ID for a given career ID (legacy or already 2025).
|
|
242
|
+
* Returns undefined for careers without a 2025 equivalent (e.g. Slann).
|
|
243
|
+
*/
|
|
244
|
+
const getCareerId2025 = (careerId: string): string | undefined => {
|
|
245
|
+
if (careerId.endsWith("-2025")) return careerId;
|
|
246
|
+
return LEGACY_TO_2025_CAREER_ID[careerId];
|
|
107
247
|
};
|
|
108
248
|
|
|
109
249
|
const getCareerFromPlayer = (player: Player) => {
|
|
@@ -114,7 +254,7 @@ const getCareerFromPlayer = (player: Player) => {
|
|
|
114
254
|
const getCareerFromIcon = (nameIcon: string) => {
|
|
115
255
|
for (const [key, values] of Object.entries(getCareers())) {
|
|
116
256
|
if (values.icons.includes(nameIcon)) {
|
|
117
|
-
return getCareerFromKey(key as
|
|
257
|
+
return getCareerFromKey(key as CAREER_ID_ALL);
|
|
118
258
|
}
|
|
119
259
|
}
|
|
120
260
|
return null;
|
|
@@ -155,11 +295,26 @@ const getPlayerAvatar = (player: Player) => {
|
|
|
155
295
|
if (!av) {
|
|
156
296
|
return null;
|
|
157
297
|
}
|
|
298
|
+
// Les avatars saisonniers (format "s17/1.png" ou trouvés dans la liste) gardent leur extension
|
|
299
|
+
// Normalise .jpeg → .png car les fichiers sont PNG (anciens enregistrements DB peuvent avoir .jpeg)
|
|
300
|
+
if (av.includes("/") || findSeasonAvatar(av)) {
|
|
301
|
+
return av.replace(".jpeg", ".png");
|
|
302
|
+
}
|
|
158
303
|
return av.replace(".png", ".jpeg");
|
|
159
304
|
};
|
|
160
305
|
|
|
161
306
|
const getPlayerAvatarPath = (player: Player) => {
|
|
162
307
|
if (player.avatar) {
|
|
308
|
+
// Nouveau format "s17/1.png"
|
|
309
|
+
if (player.avatar.includes("/")) {
|
|
310
|
+
const slashIdx = player.avatar.indexOf("/");
|
|
311
|
+
const season = parseInt(player.avatar.slice(1, slashIdx), 10);
|
|
312
|
+
return getSeasonAvatarPath(season);
|
|
313
|
+
}
|
|
314
|
+
const seasonAvatar = findSeasonAvatar(player.avatar);
|
|
315
|
+
if (seasonAvatar) {
|
|
316
|
+
return getSeasonAvatarPath(seasonAvatar.season);
|
|
317
|
+
}
|
|
163
318
|
return "tile/shop/avatar";
|
|
164
319
|
} else if (player.avatarDefault) {
|
|
165
320
|
return "tile/shop/avatar-default";
|
|
@@ -167,9 +322,9 @@ const getPlayerAvatarPath = (player: Player) => {
|
|
|
167
322
|
return null;
|
|
168
323
|
};
|
|
169
324
|
|
|
170
|
-
const getRaceFromCareer = (careerId:
|
|
325
|
+
const getRaceFromCareer = (careerId: CAREER_ID_ALL): RACE | undefined => {
|
|
171
326
|
const career = getCareerFromKey(careerId);
|
|
172
|
-
return career?.badge;
|
|
327
|
+
return career?.badge as RACE | undefined;
|
|
173
328
|
};
|
|
174
329
|
|
|
175
330
|
const getAvatarTypeFromPlayer = (player: Player, avatarFile: string) => {
|
|
@@ -199,6 +354,39 @@ const getAvatarTypeFromPlayer = (player: Player, avatarFile: string) => {
|
|
|
199
354
|
return null;
|
|
200
355
|
};
|
|
201
356
|
|
|
357
|
+
/** Returns the correct base path for an avatar file based on which list it belongs to,
|
|
358
|
+
* independent of the player's currently active avatar. */
|
|
359
|
+
const getAvatarBasePathFromFile = (player: Player, avatarFile: string): string | null => {
|
|
360
|
+
const career = getCareerFromPlayer(player);
|
|
361
|
+
if (!avatarFile) return null;
|
|
362
|
+
for (const avatarType of career.avatars) {
|
|
363
|
+
const avatars = AVATAR_LIST[avatarType as keyof typeof AVATAR_LIST];
|
|
364
|
+
if (avatars?.find((al) => al.file === avatarFile)) {
|
|
365
|
+
return "tile/shop/avatar";
|
|
366
|
+
}
|
|
367
|
+
const avatarsDefault = AVATAR_DEFAULT_LIST[avatarType as keyof typeof AVATAR_DEFAULT_LIST];
|
|
368
|
+
if (avatarsDefault?.find((al) => al.file === avatarFile)) {
|
|
369
|
+
return "tile/shop/avatar-default";
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return null;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
/** Returns the rarity string of a standard avatar file for the given player's career. */
|
|
376
|
+
const getAvatarRarityFromFile = (player: Player, avatarFile: string): string | undefined => {
|
|
377
|
+
const career = getCareerFromPlayer(player);
|
|
378
|
+
if (!avatarFile) return undefined;
|
|
379
|
+
for (const avatarType of career.avatars) {
|
|
380
|
+
const avatars = AVATAR_LIST[avatarType as keyof typeof AVATAR_LIST];
|
|
381
|
+
const found = avatars?.find((al) => al.file === avatarFile);
|
|
382
|
+
if (found) return found.rarity;
|
|
383
|
+
const avatarsDefault = AVATAR_DEFAULT_LIST[avatarType as keyof typeof AVATAR_DEFAULT_LIST];
|
|
384
|
+
const foundDefault = avatarsDefault?.find((al) => al.file === avatarFile);
|
|
385
|
+
if (foundDefault) return foundDefault.rarity;
|
|
386
|
+
}
|
|
387
|
+
return undefined;
|
|
388
|
+
};
|
|
389
|
+
|
|
202
390
|
const getRaceFromPlayer = (player: Player) => {
|
|
203
391
|
return getRaceFromCareer(getCareerKeyFromPlayer(player));
|
|
204
392
|
};
|
|
@@ -218,6 +406,21 @@ const getCareersByRace = () => {
|
|
|
218
406
|
return carrers;
|
|
219
407
|
};
|
|
220
408
|
|
|
409
|
+
const getAvailableCareersByRace = () => {
|
|
410
|
+
const carrers: any = {};
|
|
411
|
+
for (const [name, values] of Object.entries(getAvailableCareers())) {
|
|
412
|
+
const badge = values.badge;
|
|
413
|
+
if (!carrers[badge]) {
|
|
414
|
+
carrers[badge] = [];
|
|
415
|
+
}
|
|
416
|
+
if (!carrers[badge][values.range]) {
|
|
417
|
+
carrers[badge][values.range] = {};
|
|
418
|
+
}
|
|
419
|
+
carrers[badge][values.range][name] = values;
|
|
420
|
+
}
|
|
421
|
+
return carrers;
|
|
422
|
+
};
|
|
423
|
+
|
|
221
424
|
const GAIN_CAREER_POINT = 2;
|
|
222
425
|
const GAIN_CAREER_POINT_FRIENDLY = 2;
|
|
223
426
|
|
|
@@ -255,7 +458,11 @@ const COMPATIBILITY: CompatibilityType = {
|
|
|
255
458
|
} as const;
|
|
256
459
|
|
|
257
460
|
const getPlayerGroup = (player: Player) => {
|
|
258
|
-
|
|
461
|
+
const race = getRaceFromPlayer(player);
|
|
462
|
+
if (!race) {
|
|
463
|
+
return undefined;
|
|
464
|
+
}
|
|
465
|
+
return getRaceGroup(race);
|
|
259
466
|
};
|
|
260
467
|
|
|
261
468
|
const getRaceGroup = (race: RACE): GROUP_NAME | undefined => {
|
|
@@ -283,6 +490,9 @@ const getRaceCompatibility = (race1: RACE, race2: RACE) => {
|
|
|
283
490
|
const getPlayerCompatibility = (player1: Player, player2: Player) => {
|
|
284
491
|
const race1 = getRaceFromPlayer(player1);
|
|
285
492
|
const race2 = getRaceFromPlayer(player2);
|
|
493
|
+
if (!race1 || !race2) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
286
496
|
getRaceCompatibility(race1, race2);
|
|
287
497
|
};
|
|
288
498
|
|
|
@@ -303,7 +513,7 @@ function getPlayersAvailableForPromo(players = []) {
|
|
|
303
513
|
);
|
|
304
514
|
}
|
|
305
515
|
|
|
306
|
-
function getPromoCareer(careerId:
|
|
516
|
+
function getPromoCareer(careerId: CAREER_ID_ALL, userPlayers: Player[]) {
|
|
307
517
|
const race = getRaceFromCareer(careerId);
|
|
308
518
|
let promo = userPlayers
|
|
309
519
|
.filter((p, i) => p && i < NB_MAX_PLAYERS && getRaceFromPlayer(p) === race)
|
|
@@ -315,7 +525,7 @@ function getPromoCareer(careerId: CAREER_ID, userPlayers: Player[]) {
|
|
|
315
525
|
return promo;
|
|
316
526
|
}
|
|
317
527
|
|
|
318
|
-
function getPriceCareer(careerId:
|
|
528
|
+
function getPriceCareer(careerId: CAREER_ID_ALL) {
|
|
319
529
|
return getCareerRanges()[getCareerFromKey(careerId).range];
|
|
320
530
|
}
|
|
321
531
|
|
|
@@ -377,7 +587,7 @@ const getPlayersByState = (players: Player[]) => {
|
|
|
377
587
|
const getRaceSpecialSkills = (race: RACE) => {
|
|
378
588
|
const careers = getCareers();
|
|
379
589
|
const raceCareerIds = Object.keys(careers).filter(
|
|
380
|
-
(careerId) => careers[careerId as
|
|
590
|
+
(careerId) => careers[careerId as CAREER_ID_ALL].badge === race
|
|
381
591
|
);
|
|
382
592
|
|
|
383
593
|
if (raceCareerIds.length === 0) {
|
|
@@ -388,7 +598,7 @@ const getRaceSpecialSkills = (race: RACE) => {
|
|
|
388
598
|
const skillCount: Record<string, number> = {};
|
|
389
599
|
|
|
390
600
|
raceCareerIds.forEach((careerId) => {
|
|
391
|
-
const careerSkills = careers[careerId as
|
|
601
|
+
const careerSkills = careers[careerId as CAREER_ID_ALL].skills;
|
|
392
602
|
careerSkills.forEach((skill) => {
|
|
393
603
|
const skillName = Array.isArray(skill) ? skill[0] : skill;
|
|
394
604
|
// Ne compter que les compétences spéciales
|
|
@@ -418,7 +628,11 @@ export {
|
|
|
418
628
|
COMPATIBILITY,
|
|
419
629
|
GAIN_CAREER_POINT,
|
|
420
630
|
GAIN_CAREER_POINT_FRIENDLY,
|
|
631
|
+
getAvailableCareersByRace,
|
|
632
|
+
getAvatarBasePathFromFile,
|
|
633
|
+
getAvatarRarityFromFile,
|
|
421
634
|
getAvatarTypeFromPlayer,
|
|
635
|
+
getCareerId2025,
|
|
422
636
|
getCareerFromIcon,
|
|
423
637
|
getCareerFromKey,
|
|
424
638
|
getCareerFromPlayer,
|