enefel 1.0.101 → 1.0.104

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/badge.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const { ranges } = require("./improvement");
2
- const race = require("./race");
2
+ const { getCareers } = require("./race");
3
3
 
4
4
  const BADGE_NAMES = {
5
5
  KILL: "kill",
@@ -10,7 +10,7 @@ const badges = {};
10
10
  // "human-career": ranges,
11
11
  // "orc-career": ranges,
12
12
  // ...
13
- Object.values(race).forEach((r) => {
13
+ Object.values(getCareers()).forEach((r) => {
14
14
  if (!badges[r.badge]) {
15
15
  badges[r.badge] = ranges;
16
16
  }
package/index.js CHANGED
@@ -4,7 +4,7 @@ const {
4
4
  getDisturbingPresenceMalus,
5
5
  } = require("./skill");
6
6
  const { ranges } = require("./improvement");
7
- const races = require("./race");
7
+
8
8
  const {
9
9
  hasStatusStanding,
10
10
  hasStatusTacleZone,
@@ -19,6 +19,8 @@ const {
19
19
  METEO,
20
20
  } = require("./meteo");
21
21
  const { distance } = require("./calcul");
22
+ const { getCareerFromPlayer, getCareers } = require("./race");
23
+ const { getMaxMA } = require("./player");
22
24
  const INITIAL_REROLL = 2;
23
25
  const POSTULATION_HOURS = 24;
24
26
  const INACTIVE_DAYS = 10;
@@ -158,6 +160,8 @@ const GAME_HISTORY_INFO = {
158
160
  PASS: "p",
159
161
  REJECTION: "r",
160
162
  REROLL_COACH: "rc",
163
+ REROLL_RACE_MALUS: "rrm",
164
+ REROLL_METEO: "rm",
161
165
  REROLL: "re",
162
166
  SCATTER: "sc",
163
167
  SKILL: "sk",
@@ -222,21 +226,6 @@ const TAKE_BALL_TYPE = {
222
226
  CATCH_BOUNCE: "bounce",
223
227
  };
224
228
 
225
- const getCareers = () => {
226
- const carrers = {};
227
- for (const [name, values] of Object.entries(races)) {
228
- const badge = values.badge;
229
- if (!carrers[badge]) {
230
- carrers[badge] = [];
231
- }
232
- if (!carrers[badge][values.range]) {
233
- carrers[badge][values.range] = {};
234
- }
235
- carrers[badge][values.range][name] = values;
236
- }
237
- return carrers;
238
- };
239
-
240
229
  const p = (x, y) => {
241
230
  return { x: +x, y: +y };
242
231
  };
@@ -245,10 +234,6 @@ function shuffleArray(array) {
245
234
  return [...array].sort(() => 0.5 - Math.random());
246
235
  }
247
236
 
248
- function getMaxGfi(player) {
249
- return hasSkill(player, SKILL_NAMES.SPRINT) ? 3 : 2;
250
- }
251
-
252
237
  function addSeconds(date, days) {
253
238
  const result = new Date(date);
254
239
  result.setSeconds(result.getSeconds() + days);
@@ -709,7 +694,7 @@ function getEnemyTackleZones(location, teamId, players) {
709
694
  });
710
695
  }
711
696
 
712
- function canBlock(attacker, defender, attackerTeam) {
697
+ function canBlock(attacker, defender, attackerTeam, game) {
713
698
  if (
714
699
  !attacker ||
715
700
  !defender ||
@@ -733,7 +718,7 @@ function canBlock(attacker, defender, attackerTeam) {
733
718
 
734
719
  // No blitz available
735
720
  if (attackerTeam.date_next_blitz !== null) {
736
- return attacker.current_MA === attacker.MA;
721
+ return attacker.current_MA === getMaxMA(attacker, game);
737
722
  } else {
738
723
  // Blitz available
739
724
 
@@ -768,10 +753,10 @@ function canPass(player, playerTeam, playerIdWithBall) {
768
753
  );
769
754
  }
770
755
 
771
- function canEndTurn(player) {
756
+ function canEndTurn(player, game) {
772
757
  return (
773
758
  player.date_next_action === null &&
774
- (player.has_action === false || player.current_MA < player.MA)
759
+ (player.has_action === false || player.current_MA < getMaxMA(player, game))
775
760
  );
776
761
  }
777
762
 
@@ -851,12 +836,12 @@ const isCoach = (player, team = null) => {
851
836
  };
852
837
 
853
838
  const getMoralModifier = (player) => {
854
- const race = races[player.race_id];
839
+ const career = getCareerFromPlayer(player);
855
840
  let range = ranges.findIndex((range) => player.experience < range);
856
841
  if (range === -1) {
857
842
  range = ranges.length;
858
843
  }
859
- return race.cost / 10 + range;
844
+ return career.cost / 10 + range;
860
845
  };
861
846
 
862
847
  const getAttackerStrength = (
@@ -898,7 +883,17 @@ const swapArrayLocs = (arr, index1, index2) => {
898
883
  return arr;
899
884
  };
900
885
 
886
+ const getInactiveDays = (isDev = false) => {
887
+ return isDev ? 10000 : INACTIVE_DAYS;
888
+ };
889
+
890
+ const getMaxPlayers = (isDev = false) => {
891
+ return isDev ? 10000 : MAX_PLAYER_USER;
892
+ };
893
+
901
894
  module.exports = {
895
+ getInactiveDays,
896
+ getMaxPlayers,
902
897
  addSeconds,
903
898
  availableSquaresToPushBack,
904
899
  canBlock,
@@ -919,17 +914,14 @@ module.exports = {
919
914
  getAttackerStrength,
920
915
  getBestInterceptor,
921
916
  getBlockAssistance,
922
- getCareers,
923
917
  getDefenderStrength,
924
918
  getDicesBlock,
925
919
  getEnemyTackleZones,
926
- getMaxGfi,
927
920
  getMoralModifier,
928
921
  getPlayerOnCell,
929
922
  getTeamColor,
930
923
  getThrowingBonus,
931
924
  haveSameTeam,
932
- INACTIVE_DAYS,
933
925
  INITIAL_REROLL,
934
926
  isAdjacent,
935
927
  isCoach,
@@ -941,7 +933,6 @@ module.exports = {
941
933
  isSquareValidToPushBack,
942
934
  LAST_SEASON_ALPHA,
943
935
  MAX_PLAYER_TEAM,
944
- MAX_PLAYER_USER,
945
936
  swapArrayLocs,
946
937
  p,
947
938
  PLAYER_HISTORY_INFO,
package/league.js CHANGED
@@ -120,7 +120,7 @@ const calculateTeamsStandingForNextSeason = (division) => {
120
120
  .reduce((p, c) => [...p, ...c.teams], [])
121
121
  .filter((t) => t && canPlayLeague(t));
122
122
 
123
- if (HAS_NEXT_SEASON_PLAYOFF && GROUP_SIZE * 3 >= flatTeams.length) {
123
+ if (HAS_NEXT_SEASON_PLAYOFF && GROUP_SIZE * 3 < flatTeams.length) {
124
124
  return calculateTeamsStandingForPlayoff(flatTeams, division);
125
125
  }
126
126
  return calculateTeamsStandingForLeagues(newStandings, division);
@@ -238,16 +238,7 @@ function sortLeagues(a, b) {
238
238
  return 0;
239
239
  }
240
240
 
241
- function getWinner(game) {
242
- // TODO
243
- if (game.score1 > game.score2) {
244
- return game.team1_id;
245
- } else {
246
- return game.team2_id;
247
- }
248
- }
249
241
  module.exports = {
250
- getWinner,
251
242
  calculateTeamsStandingForNextSeason,
252
243
  hasCalendar,
253
244
  playoffNextSeason,
package/meteo.js CHANGED
@@ -8,22 +8,40 @@ const METEO = {
8
8
  PERFECT_CONDITION: 7,
9
9
  HEAVY_SNOW: 8,
10
10
  BLIZZARD: 9,
11
+ MORNING_DEW: 10,
12
+ BLOSSOMING_FLOWERS: 11,
13
+ MISTY_MORNING: 12,
14
+ HIGH_WINDS: 13,
11
15
  };
12
16
 
13
17
  const SEASON = {
14
- AUTUMN: 4,
18
+ WINTER: 1,
15
19
  SPRING: 2,
16
20
  SUMMER: 3,
17
- WINTER: 1,
21
+ AUTUMN: 4,
18
22
  };
19
23
 
20
24
  const getSeason = () => {
21
- return SEASON.WINTER;
25
+ return SEASON.SPRING;
22
26
  // return SEASON.AUTUMN;
23
27
  };
24
28
 
25
29
  const getMeteo = (value) => {
26
30
  const season = getSeason();
31
+ if (season === SEASON.SPRING) {
32
+ switch (value) {
33
+ case 2:
34
+ return METEO.MORNING_DEW;
35
+ case 3:
36
+ return METEO.BLOSSOMING_FLOWERS;
37
+ case 11:
38
+ return METEO.MISTY_MORNING;
39
+ case 12:
40
+ return METEO.HIGH_WINDS;
41
+ default:
42
+ return METEO.PERFECT_CONDITION;
43
+ }
44
+ }
27
45
  if (season === SEASON.WINTER) {
28
46
  switch (value) {
29
47
  case 2:
@@ -85,6 +103,17 @@ const meteoKO = (meteoValue) => {
85
103
  return modif;
86
104
  };
87
105
 
106
+ // only pickup ball interaction
107
+ const meteoPickUpBall = (meteoValue) => {
108
+ let modif = 0;
109
+
110
+ if (meteoValue === METEO.MORNING_DEW) {
111
+ modif = -1;
112
+ }
113
+ return modif;
114
+ };
115
+
116
+ // All ball interaction
88
117
  const meteoTakeBall = (meteoValue) => {
89
118
  let modif = 0;
90
119
  if (meteoValue === METEO.POURING_RAIN) {
@@ -117,28 +146,55 @@ const meteoGfi = (meteoValue) => {
117
146
  if (meteoValue === METEO.BLIZZARD) {
118
147
  modif = -1;
119
148
  }
149
+ if (meteoValue === METEO.MORNING_DEW) {
150
+ modif = -1;
151
+ }
120
152
  return modif;
121
153
  };
122
154
 
123
155
  const meteoMaxPassDistance = (meteoValue) => {
124
156
  // 3.5, 7, 10.2, 13.1
125
157
  let max = 14;
126
- if (meteoValue === METEO.BLIZZARD) {
158
+ if (meteoValue === METEO.BLIZZARD || meteoValue === METEO.MISTY_MORNING) {
127
159
  max = 7;
128
160
  }
129
161
  return max;
130
162
  };
131
163
 
164
+ const meteoHasExpulsion = (meteoValue) => {
165
+ if (meteoValue === METEO.BLOSSOMING_FLOWERS) {
166
+ return false;
167
+ }
168
+ return true;
169
+ };
170
+
171
+ const meteoMaxMA = (meteoValue) => {
172
+ if (meteoValue === METEO.MISTY_MORNING) {
173
+ return 6;
174
+ }
175
+ return Infinity;
176
+ };
177
+
178
+ const meteoRerollRoll = (meteoValue) => {
179
+ if (meteoValue === METEO.HIGH_WINDS) {
180
+ return 2;
181
+ }
182
+ return 1;
183
+ };
132
184
  const tools = {
133
185
  getMeteo,
134
186
  METEO,
135
187
  meteoAttackerStrengthBlitz,
136
188
  meteoGfi,
189
+ meteoHasExpulsion,
137
190
  meteoKO,
191
+ meteoMaxMA,
138
192
  meteoMaxPassDistance,
139
193
  meteoPassBonus,
140
194
  meteoPassRebound,
195
+ meteoPickUpBall,
141
196
  meteoPlayerFall,
197
+ meteoRerollRoll,
142
198
  meteoTakeBall,
143
199
  };
144
200
  module.exports = tools;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enefel",
3
- "version": "1.0.101",
3
+ "version": "1.0.104",
4
4
  "main": "index.js",
5
5
  "author": "Manest",
6
6
  "license": "MIT",
package/player.js ADDED
@@ -0,0 +1,23 @@
1
+ const { meteoMaxMA } = require("./meteo");
2
+ const { hasSkill, SKILL_NAMES } = require("./skill");
3
+
4
+ function getMaxMA(player, game) {
5
+ if (!player) {
6
+ return null;
7
+ }
8
+
9
+ if (game) {
10
+ const maxMA = meteoMaxMA(game.meteo);
11
+ if (player.MA > maxMA) {
12
+ return maxMA;
13
+ }
14
+ }
15
+
16
+ return player.MA;
17
+ }
18
+
19
+ function getMaxGfi(player) {
20
+ return hasSkill(player, SKILL_NAMES.SPRINT) ? 3 : 2;
21
+ }
22
+
23
+ module.exports = { getMaxGfi, getMaxMA };
package/race.js CHANGED
@@ -1,7 +1,24 @@
1
1
  const { SKILL_NAMES } = require("./skill");
2
2
 
3
+ const ANIMOSITY_NUMBER = 2;
4
+
5
+ const RACE = {
6
+ AMAZON: "amazon-career",
7
+ CHAOS_DWARF: "chaos-dwarf-career",
8
+ CHAOS: "chaos-career",
9
+ DARK_ELFE: "dark-elfe-career",
10
+ DWARF: "dwarf-career",
11
+ HALFLING: "halfling-career",
12
+ HUMAN: "human-career",
13
+ LIZARDMEN: "lizardmen-career",
14
+ NORSE: "norse-career",
15
+ ORC: "orc-career",
16
+ RAT: "rat-career",
17
+ SILVAN: "silvan-career",
18
+ };
19
+
3
20
  // MA: Movement Allowance
4
- // : Strength
21
+ // ST : Strength
5
22
  // AG: Agility
6
23
  // AV: Armour Value
7
24
 
@@ -17,7 +34,7 @@ const { SKILL_NAMES } = require("./skill");
17
34
  // TODO: skills??
18
35
  // const ranges = [6, 16, 31, 51, 76, 176];
19
36
  // https://web.archive.org/web/20090403112513/http://enefel.org/carriere.php
20
- module.exports = {
37
+ const CAREER = {
21
38
  // LIZARDMEN
22
39
  "lizardmen-skink": {
23
40
  MA: 8,
@@ -29,7 +46,7 @@ module.exports = {
29
46
  normalCoach: "G",
30
47
  icons: ["lizardmen-skink1"],
31
48
  skills: [SKILL_NAMES.DODGE, SKILL_NAMES.STUNTY],
32
- badge: "lizardmen-career",
49
+ badge: RACE.LIZARDMEN,
33
50
  range: 0,
34
51
  cost: 60,
35
52
  },
@@ -48,7 +65,7 @@ module.exports = {
48
65
  SKILL_NAMES.SHADOWING,
49
66
  SKILL_NAMES.STUNTY,
50
67
  ],
51
- badge: "lizardmen-career",
68
+ badge: RACE.LIZARDMEN,
52
69
  range: 1,
53
70
  cost: 70,
54
71
  },
@@ -62,8 +79,8 @@ module.exports = {
62
79
  normalCoach: "G",
63
80
  icons: ["lizardmen-saurus1"],
64
81
  skills: [SKILL_NAMES.STAR],
65
- badge: "lizardmen-career",
66
- range: 4,
82
+ badge: RACE.LIZARDMEN,
83
+ range: 5,
67
84
  cost: 85,
68
85
  },
69
86
  "lizardmen-kroxigor": {
@@ -83,8 +100,8 @@ module.exports = {
83
100
  SKILL_NAMES.THICK_SKULL,
84
101
  SKILL_NAMES.BIG_GUY,
85
102
  ],
86
- badge: "lizardmen-career",
87
- range: 5,
103
+ badge: RACE.LIZARDMEN,
104
+ range: 6,
88
105
  cost: 140,
89
106
  },
90
107
 
@@ -99,7 +116,7 @@ module.exports = {
99
116
  normalCoach: "G",
100
117
  icons: ["norse-lineman1"],
101
118
  skills: [SKILL_NAMES.BLOCK],
102
- badge: "norse-career",
119
+ badge: RACE.NORSE,
103
120
  range: 0,
104
121
  cost: 50,
105
122
  },
@@ -113,7 +130,7 @@ module.exports = {
113
130
  normalCoach: "G",
114
131
  icons: ["norse-thrower1"],
115
132
  skills: [SKILL_NAMES.BLOCK, SKILL_NAMES.PASS, SKILL_NAMES.SPECIALIST],
116
- badge: "norse-career",
133
+ badge: RACE.NORSE,
117
134
  range: 1,
118
135
  cost: 70,
119
136
  },
@@ -127,7 +144,7 @@ module.exports = {
127
144
  normalCoach: "G",
128
145
  icons: ["norse-catcher1"],
129
146
  skills: [SKILL_NAMES.BLOCK, SKILL_NAMES.DAUNTLESS, SKILL_NAMES.SPECIALIST],
130
- badge: "norse-career",
147
+ badge: RACE.NORSE,
131
148
  range: 2,
132
149
  cost: 90,
133
150
  },
@@ -146,7 +163,7 @@ module.exports = {
146
163
  SKILL_NAMES.FRENZY,
147
164
  SKILL_NAMES.SPECIALIST,
148
165
  ],
149
- badge: "norse-career",
166
+ badge: RACE.NORSE,
150
167
  range: 3,
151
168
  cost: 90,
152
169
  },
@@ -160,8 +177,8 @@ module.exports = {
160
177
  normalCoach: "G",
161
178
  icons: ["norse-ulfwereners1"],
162
179
  skills: [SKILL_NAMES.FRENZY, SKILL_NAMES.STAR],
163
- badge: "norse-career",
164
- range: 4,
180
+ badge: RACE.NORSE,
181
+ range: 5,
165
182
  cost: 105,
166
183
  },
167
184
  "norse-yhetee": {
@@ -181,7 +198,7 @@ module.exports = {
181
198
  SKILL_NAMES.UNCHANNELLED_FURY,
182
199
  SKILL_NAMES.BIG_GUY,
183
200
  ],
184
- badge: "norse-career",
201
+ badge: RACE.NORSE,
185
202
  range: 6,
186
203
  cost: 140,
187
204
  },
@@ -197,7 +214,7 @@ module.exports = {
197
214
  normalCoach: "G",
198
215
  icons: ["amazon-linewomen1"],
199
216
  skills: [SKILL_NAMES.DODGE],
200
- badge: "amazon-career",
217
+ badge: RACE.AMAZON,
201
218
  range: 0,
202
219
  cost: 50,
203
220
  },
@@ -211,7 +228,7 @@ module.exports = {
211
228
  normalCoach: "G",
212
229
  icons: ["amazon-thrower1"],
213
230
  skills: [SKILL_NAMES.PASS, SKILL_NAMES.DODGE, SKILL_NAMES.SPECIALIST],
214
- badge: "amazon-career",
231
+ badge: RACE.AMAZON,
215
232
  range: 1,
216
233
  cost: 75,
217
234
  },
@@ -225,7 +242,7 @@ module.exports = {
225
242
  normalCoach: "G",
226
243
  icons: ["amazon-catcher1"],
227
244
  skills: [SKILL_NAMES.CATCH, SKILL_NAMES.DODGE, SKILL_NAMES.SPECIALIST],
228
- badge: "amazon-career",
245
+ badge: RACE.AMAZON,
229
246
  range: 2,
230
247
  cost: 75,
231
248
  },
@@ -239,8 +256,8 @@ module.exports = {
239
256
  normalCoach: "G",
240
257
  icons: ["amazon-blitzer1"],
241
258
  skills: [SKILL_NAMES.BLOCK, SKILL_NAMES.DODGE, SKILL_NAMES.SPECIALIST],
242
- badge: "amazon-career",
243
- range: 4,
259
+ badge: RACE.AMAZON,
260
+ range: 3,
244
261
  cost: 90,
245
262
  },
246
263
 
@@ -256,7 +273,7 @@ module.exports = {
256
273
  normalCoach: "G",
257
274
  icons: ["human1"],
258
275
  skills: [],
259
- badge: "human-career",
276
+ badge: RACE.HUMAN,
260
277
  range: 0,
261
278
  cost: 50,
262
279
  },
@@ -270,7 +287,7 @@ module.exports = {
270
287
  normalCoach: "G",
271
288
  icons: ["human-catcher1"],
272
289
  skills: [SKILL_NAMES.CATCH, SKILL_NAMES.DODGE, SKILL_NAMES.SPECIALIST],
273
- badge: "human-career",
290
+ badge: RACE.HUMAN,
274
291
  range: 1,
275
292
  cost: 70,
276
293
  },
@@ -284,7 +301,7 @@ module.exports = {
284
301
  normalCoach: "G",
285
302
  icons: ["human-thrower1"],
286
303
  skills: [SKILL_NAMES.SURE_HANDS, SKILL_NAMES.PASS, SKILL_NAMES.SPECIALIST],
287
- badge: "human-career",
304
+ badge: RACE.HUMAN,
288
305
  range: 2,
289
306
  cost: 70,
290
307
  },
@@ -298,7 +315,7 @@ module.exports = {
298
315
  normalCoach: "G",
299
316
  icons: ["human-blitzer1"],
300
317
  skills: [SKILL_NAMES.BLOCK, SKILL_NAMES.STAR],
301
- badge: "human-career",
318
+ badge: RACE.HUMAN,
302
319
  range: 4,
303
320
  cost: 90,
304
321
  },
@@ -319,7 +336,7 @@ module.exports = {
319
336
  SKILL_NAMES.THROW_TEAM_MATE,
320
337
  SKILL_NAMES.BIG_GUY,
321
338
  ],
322
- badge: "human-career",
339
+ badge: RACE.HUMAN,
323
340
  range: 6,
324
341
  cost: 140,
325
342
  },
@@ -336,7 +353,7 @@ module.exports = {
336
353
  normalCoach: "G",
337
354
  icons: ["orc1"],
338
355
  skills: [],
339
- badge: "orc-career",
356
+ badge: RACE.ORC,
340
357
  range: 0,
341
358
  cost: 50,
342
359
  },
@@ -350,7 +367,7 @@ module.exports = {
350
367
  normalCoach: "G",
351
368
  icons: ["orc-thrower1"],
352
369
  skills: [SKILL_NAMES.SURE_HANDS, SKILL_NAMES.PASS, SKILL_NAMES.SPECIALIST],
353
- badge: "orc-career",
370
+ badge: RACE.ORC,
354
371
  range: 1,
355
372
  cost: 70,
356
373
  },
@@ -364,7 +381,7 @@ module.exports = {
364
381
  normalCoach: "G",
365
382
  icons: ["orc-blitzer1"],
366
383
  skills: [SKILL_NAMES.BLOCK, SKILL_NAMES.SPECIALIST],
367
- badge: "orc-career",
384
+ badge: RACE.ORC,
368
385
  range: 2,
369
386
  cost: 80,
370
387
  },
@@ -378,8 +395,8 @@ module.exports = {
378
395
  normalCoach: "G",
379
396
  icons: ["orc-black-orc1"],
380
397
  skills: [SKILL_NAMES.STAR],
381
- badge: "orc-career",
382
- range: 4,
398
+ badge: RACE.ORC,
399
+ range: 5,
383
400
  cost: 80,
384
401
  },
385
402
  "orc-troll": {
@@ -400,7 +417,7 @@ module.exports = {
400
417
  SKILL_NAMES.REGENERATION,
401
418
  SKILL_NAMES.THROW_TEAM_MATE,
402
419
  ],
403
- badge: "orc-career",
420
+ badge: RACE.ORC,
404
421
  range: 6,
405
422
  cost: 115,
406
423
  },
@@ -417,7 +434,7 @@ module.exports = {
417
434
  normalCoach: "G",
418
435
  icons: ["dwarf1"],
419
436
  skills: [SKILL_NAMES.BLOCK, SKILL_NAMES.TACKLE, SKILL_NAMES.THICK_SKULL],
420
- badge: "dwarf-career",
437
+ badge: RACE.DWARF,
421
438
  range: 0,
422
439
  cost: 70,
423
440
  },
@@ -435,7 +452,7 @@ module.exports = {
435
452
  SKILL_NAMES.THICK_SKULL,
436
453
  SKILL_NAMES.SPECIALIST,
437
454
  ],
438
- badge: "dwarf-career",
455
+ badge: RACE.DWARF,
439
456
  range: 1,
440
457
  cost: 80,
441
458
  },
@@ -453,7 +470,7 @@ module.exports = {
453
470
  SKILL_NAMES.THICK_SKULL,
454
471
  SKILL_NAMES.SPECIALIST,
455
472
  ],
456
- badge: "dwarf-career",
473
+ badge: RACE.DWARF,
457
474
  range: 2,
458
475
  cost: 80,
459
476
  },
@@ -473,8 +490,8 @@ module.exports = {
473
490
  SKILL_NAMES.FRENZY,
474
491
  SKILL_NAMES.THICK_SKULL,
475
492
  ],
476
- badge: "dwarf-career",
477
- range: 3,
493
+ badge: RACE.DWARF,
494
+ range: 4,
478
495
  cost: 90,
479
496
  },
480
497
 
@@ -490,7 +507,7 @@ module.exports = {
490
507
  normalCoach: "G",
491
508
  icons: ["rat1"],
492
509
  skills: [],
493
- badge: "rat-career",
510
+ badge: RACE.RAT,
494
511
  range: 0,
495
512
  cost: 50,
496
513
  },
@@ -504,7 +521,7 @@ module.exports = {
504
521
  normalCoach: "G",
505
522
  icons: ["rat-thrower1"],
506
523
  skills: [SKILL_NAMES.PASS, SKILL_NAMES.SURE_HANDS, SKILL_NAMES.SPECIALIST],
507
- badge: "rat-career",
524
+ badge: RACE.RAT,
508
525
  range: 1,
509
526
  cost: 70,
510
527
  },
@@ -518,8 +535,8 @@ module.exports = {
518
535
  normalCoach: "G",
519
536
  icons: ["rat-runner1"],
520
537
  skills: [SKILL_NAMES.DODGE, SKILL_NAMES.SPECIALIST],
521
- badge: "rat-career",
522
- range: 3,
538
+ badge: RACE.RAT,
539
+ range: 2,
523
540
  cost: 80,
524
541
  },
525
542
  "rat-blitzer": {
@@ -532,7 +549,7 @@ module.exports = {
532
549
  normalCoach: "G",
533
550
  icons: ["rat-blitzer1"],
534
551
  skills: [SKILL_NAMES.STAR, SKILL_NAMES.BLOCK],
535
- badge: "rat-career",
552
+ badge: RACE.RAT,
536
553
  range: 4,
537
554
  cost: 90,
538
555
  },
@@ -553,7 +570,7 @@ module.exports = {
553
570
  SKILL_NAMES.MIGHTY_BLOW,
554
571
  SKILL_NAMES.PREHENSILE_TAIL,
555
572
  ],
556
- badge: "rat-career",
573
+ badge: RACE.RAT,
557
574
  range: 6,
558
575
  cost: 150,
559
576
  },
@@ -570,7 +587,7 @@ module.exports = {
570
587
  normalCoach: "G",
571
588
  icons: ["silvan1"],
572
589
  skills: [],
573
- badge: "silvan-career",
590
+ badge: RACE.SILVAN,
574
591
  range: 0,
575
592
  cost: 70,
576
593
  },
@@ -589,8 +606,8 @@ module.exports = {
589
606
  SKILL_NAMES.SPRINT,
590
607
  SKILL_NAMES.SPECIALIST,
591
608
  ],
592
- badge: "silvan-career",
593
- range: 3,
609
+ badge: RACE.SILVAN,
610
+ range: 1,
594
611
  cost: 90,
595
612
  },
596
613
  "silvan-thrower": {
@@ -603,8 +620,8 @@ module.exports = {
603
620
  normalCoach: "G",
604
621
  icons: ["silvan-thrower1"],
605
622
  skills: [SKILL_NAMES.PASS, SKILL_NAMES.SPECIALIST],
606
- badge: "silvan-career",
607
- range: 4,
623
+ badge: RACE.SILVAN,
624
+ range: 2,
608
625
  cost: 90,
609
626
  },
610
627
  "silvan-wardancer": {
@@ -622,7 +639,7 @@ module.exports = {
622
639
  SKILL_NAMES.DODGE,
623
640
  SKILL_NAMES.LEAP,
624
641
  ],
625
- badge: "silvan-career",
642
+ badge: RACE.SILVAN,
626
643
  range: 5,
627
644
  cost: 120,
628
645
  },
@@ -639,7 +656,7 @@ module.exports = {
639
656
  normalCoach: "G",
640
657
  icons: ["chaos-beastman1"],
641
658
  skills: [SKILL_NAMES.HORNS],
642
- badge: "chaos-career",
659
+ badge: RACE.CHAOS,
643
660
  range: 0,
644
661
  cost: 60,
645
662
  },
@@ -653,10 +670,32 @@ module.exports = {
653
670
  normalCoach: "G",
654
671
  icons: ["chaos-warrior1"],
655
672
  skills: [SKILL_NAMES.STAR],
656
- badge: "chaos-career",
657
- range: 4,
673
+ badge: RACE.CHAOS,
674
+ range: 5,
658
675
  cost: 100,
659
676
  },
677
+ "chaos-minotaur": {
678
+ MA: 5,
679
+ ST: 5,
680
+ AG: 2,
681
+ AV: 8,
682
+ normal: "MS",
683
+ double: "AG",
684
+ normalCoach: "G",
685
+ icons: ["chaos-minotaur1"],
686
+ skills: [
687
+ [SKILL_NAMES.LONER, 4],
688
+ SKILL_NAMES.FRENZY,
689
+ SKILL_NAMES.HORNS,
690
+ SKILL_NAMES.MIGHTY_BLOW,
691
+ SKILL_NAMES.THICK_SKULL,
692
+ SKILL_NAMES.UNCHANNELLED_FURY,
693
+ SKILL_NAMES.BIG_GUY,
694
+ ],
695
+ badge: RACE.CHAOS,
696
+ range: 6,
697
+ cost: 150,
698
+ },
660
699
 
661
700
  // DARK ELFE
662
701
  "dark-elfe-lineman": {
@@ -669,7 +708,7 @@ module.exports = {
669
708
  normalCoach: "G",
670
709
  icons: ["dark-elfe-lineman1"],
671
710
  skills: [],
672
- badge: "dark-elfe-career",
711
+ badge: RACE.DARK_ELFE,
673
712
  range: 0,
674
713
  cost: 70,
675
714
  },
@@ -683,8 +722,8 @@ module.exports = {
683
722
  normalCoach: "G",
684
723
  icons: ["dark-elfe-runner1"],
685
724
  skills: [SKILL_NAMES.DUMP_OFF, SKILL_NAMES.SPECIALIST],
686
- badge: "dark-elfe-career",
687
- range: 3,
725
+ badge: RACE.DARK_ELFE,
726
+ range: 1,
688
727
  cost: 80,
689
728
  },
690
729
  "dark-elfe-blitzer": {
@@ -697,8 +736,8 @@ module.exports = {
697
736
  normalCoach: "G",
698
737
  icons: ["dark-elfe-blitzer1"],
699
738
  skills: [SKILL_NAMES.BLOCK, SKILL_NAMES.SPECIALIST],
700
- badge: "dark-elfe-career",
701
- range: 4,
739
+ badge: RACE.DARK_ELFE,
740
+ range: 2,
702
741
  cost: 100,
703
742
  },
704
743
  "dark-elfe-witch": {
@@ -716,7 +755,7 @@ module.exports = {
716
755
  SKILL_NAMES.DODGE,
717
756
  SKILL_NAMES.JUMP_UP,
718
757
  ],
719
- badge: "dark-elfe-career",
758
+ badge: RACE.DARK_ELFE,
720
759
  range: 5,
721
760
  cost: 110,
722
761
  },
@@ -732,7 +771,7 @@ module.exports = {
732
771
  normalCoach: "G",
733
772
  icons: ["chaos-dwarf-hobgobelin1"],
734
773
  skills: [],
735
- badge: "chaos-dwarf-career",
774
+ badge: RACE.CHAOS_DWARF,
736
775
  range: 0,
737
776
  cost: 40,
738
777
  },
@@ -751,7 +790,7 @@ module.exports = {
751
790
  SKILL_NAMES.THICK_SKULL,
752
791
  SKILL_NAMES.SPECIALIST,
753
792
  ],
754
- badge: "chaos-dwarf-career",
793
+ badge: RACE.CHAOS_DWARF,
755
794
  range: 1,
756
795
  cost: 70,
757
796
  },
@@ -770,7 +809,7 @@ module.exports = {
770
809
  SKILL_NAMES.THICK_SKULL,
771
810
  SKILL_NAMES.STAR,
772
811
  ],
773
- badge: "chaos-dwarf-career",
812
+ badge: RACE.CHAOS_DWARF,
774
813
  range: 5,
775
814
  cost: 130,
776
815
  },
@@ -786,7 +825,7 @@ module.exports = {
786
825
  normalCoach: "G",
787
826
  icons: ["halfling-lineman1"],
788
827
  skills: [SKILL_NAMES.DODGE, SKILL_NAMES.RIGHT_STUFF, SKILL_NAMES.STUNTY],
789
- badge: "halfling-career",
828
+ badge: RACE.HALFLING,
790
829
  range: 0,
791
830
  cost: 30,
792
831
  },
@@ -800,7 +839,7 @@ module.exports = {
800
839
  normalCoach: "G",
801
840
  icons: ["halfling-hefty1"],
802
841
  skills: [SKILL_NAMES.DODGE, SKILL_NAMES.FEND, SKILL_NAMES.STUNTY],
803
- badge: "halfling-career",
842
+ badge: RACE.HALFLING,
804
843
  range: 1,
805
844
  cost: 50,
806
845
  },
@@ -820,7 +859,7 @@ module.exports = {
820
859
  SKILL_NAMES.SPRINT,
821
860
  SKILL_NAMES.STUNTY,
822
861
  ],
823
- badge: "halfling-career",
862
+ badge: RACE.HALFLING,
824
863
  range: 2,
825
864
  cost: 55,
826
865
  },
@@ -841,8 +880,170 @@ module.exports = {
841
880
  SKILL_NAMES.THICK_SKULL,
842
881
  SKILL_NAMES.THROW_TEAM_MATE,
843
882
  ],
844
- badge: "halfling-career",
845
- range: 5,
883
+ badge: RACE.HALFLING,
884
+ range: 6,
846
885
  cost: 130,
847
886
  },
848
887
  };
888
+
889
+ const getCareers = () => {
890
+ return CAREER;
891
+ };
892
+
893
+ const getCareerFromKey = (key) => {
894
+ return getCareers()[key];
895
+ };
896
+
897
+ const getCareerKeyFromPlayer = (player) => {
898
+ // Attention la career est le race_id dans la table player
899
+ return player.race_id;
900
+ };
901
+
902
+ const getCareerFromPlayer = (player) => {
903
+ return getCareerFromKey(getCareerKeyFromPlayer(player));
904
+ };
905
+
906
+ const getRaceFromCareer = (careerId) => {
907
+ const career = getCareerFromKey(careerId);
908
+ return career.badge;
909
+ };
910
+
911
+ const getRaceFromPlayer = (player) => {
912
+ return getRaceFromCareer(getCareerKeyFromPlayer(player));
913
+ };
914
+
915
+ const getCareersByRace = () => {
916
+ const carrers = {};
917
+ for (const [name, values] of Object.entries(getCareers())) {
918
+ const badge = values.badge;
919
+ if (!carrers[badge]) {
920
+ carrers[badge] = [];
921
+ }
922
+ if (!carrers[badge][values.range]) {
923
+ carrers[badge][values.range] = {};
924
+ }
925
+ carrers[badge][values.range][name] = values;
926
+ }
927
+ return carrers;
928
+ };
929
+
930
+ const GAIN_CAREER_POINT = 2;
931
+ const GAIN_CAREER_POINT_FRIENDLY = 2;
932
+
933
+ const GROUP_NAME = {
934
+ AGILE: "group-agile",
935
+ CHAOTIC: "group-chaotic",
936
+ EXOTIC: "group-exotic",
937
+ NEUTRAL: "group-neutral",
938
+ VICIOUS: "group-vicious",
939
+ };
940
+
941
+ const COMPATIBILITY = {
942
+ [GROUP_NAME.AGILE]: [RACE.AMAZON, RACE.SILVAN],
943
+ [GROUP_NAME.CHAOTIC]: [RACE.ORC, RACE.CHAOS_DWARF, RACE.CHAOS],
944
+ [GROUP_NAME.EXOTIC]: [RACE.DWARF, RACE.NORSE, RACE.LIZARDMEN],
945
+ [GROUP_NAME.NEUTRAL]: [RACE.HALFLING, RACE.HUMAN],
946
+ [GROUP_NAME.VICIOUS]: [RACE.DARK_ELFE, RACE.RAT],
947
+ };
948
+
949
+ const getPlayerGroup = (player) => {
950
+ return getRaceGroup(getRaceFromPlayer(player));
951
+ };
952
+
953
+ const getRaceGroup = (race) => {
954
+ for (const group of Object.keys(COMPATIBILITY)) {
955
+ if (COMPATIBILITY[group].includes(race)) {
956
+ return group;
957
+ }
958
+ }
959
+ };
960
+
961
+ const getRaceCompatibility = (race1, race2) => {
962
+ const group1 = getRaceGroup(race1);
963
+ const group2 = getRaceGroup(race2);
964
+ if (
965
+ group1 === group2 ||
966
+ group1 === GROUP_NAME.NEUTRAL ||
967
+ group2 === GROUP_NAME.NEUTRAL
968
+ ) {
969
+ return true;
970
+ }
971
+ return false;
972
+ };
973
+
974
+ const getPlayerCompatibility = (player1, player2) => {
975
+ const race1 = getRaceFromPlayer(player1);
976
+ const race2 = getRaceFromPlayer(player2);
977
+ getRaceCompatibility(race1, race2);
978
+ };
979
+
980
+ const ranges = [16, 32, 48, 64, 80, 96];
981
+
982
+ function getCareerRanges() {
983
+ return [0, ...ranges];
984
+ }
985
+
986
+ function getPromoCareer(careerId, userPlayers) {
987
+ const NB_MAX_PLAYERS = 2;
988
+ const race = getRaceFromCareer(careerId);
989
+ let promo = userPlayers
990
+ .filter((p, i) => p && i < NB_MAX_PLAYERS && getRaceFromPlayer(p) === race)
991
+ .reduce((p, c) => c.pc + p, 0);
992
+ const price = getPriceCareer(careerId);
993
+ if (promo > price / 2) {
994
+ promo = price / 2;
995
+ }
996
+ return promo;
997
+ }
998
+
999
+ function getPriceCareer(careerId) {
1000
+ return getCareerRanges()[getCareerFromKey(careerId).range];
1001
+ }
1002
+
1003
+ function getTeamGroups(team) {
1004
+ const groups = {};
1005
+ for (const player of team.players) {
1006
+ const group = getPlayerGroup(player);
1007
+ if (!groups[group]) {
1008
+ groups[group] = [];
1009
+ }
1010
+ groups[group].push(player);
1011
+ }
1012
+ return groups;
1013
+ }
1014
+
1015
+ function isNeutralGroup(group) {
1016
+ const neutrals = [GROUP_NAME.NEUTRAL];
1017
+ return neutrals.includes(group);
1018
+ }
1019
+
1020
+ function getTeamIncompatibleGroups(team) {
1021
+ const groups = getTeamGroups(team);
1022
+ // return array of [name, players]: [['group-vicious', Array(8)], ...]
1023
+ return Object.entries(groups).filter((group) => !isNeutralGroup(group[0]));
1024
+ }
1025
+
1026
+ module.exports = {
1027
+ ANIMOSITY_NUMBER,
1028
+ COMPATIBILITY,
1029
+ GAIN_CAREER_POINT_FRIENDLY,
1030
+ GAIN_CAREER_POINT,
1031
+ getCareerFromKey,
1032
+ getCareerFromPlayer,
1033
+ getCareerKeyFromPlayer,
1034
+ getCareerRanges,
1035
+ getCareers,
1036
+ getCareersByRace,
1037
+ getPlayerCompatibility,
1038
+ getPlayerGroup,
1039
+ getPriceCareer,
1040
+ getPromoCareer,
1041
+ getRaceFromCareer,
1042
+ getRaceFromPlayer,
1043
+ getRaceGroup,
1044
+ getTeamGroups,
1045
+ getTeamIncompatibleGroups,
1046
+ GROUP_NAME,
1047
+ isNeutralGroup,
1048
+ RACE,
1049
+ };
package/skill.js CHANGED
@@ -14,6 +14,7 @@ const SKILL_NAMES = {
14
14
  ACCURATE: "accurate",
15
15
  ALWAYS_HUNGRY: "always-hungry",
16
16
  ANIMAL_SAVAGERY: "animal-salvagery",
17
+ ANIMOSITY: "animosity",
17
18
  BIG_GUY: "big-guy",
18
19
  BIG_HAND: "big-hand",
19
20
  BLOCK: "block",
@@ -78,6 +79,7 @@ const SKILL_TYPE = {
78
79
  MUTATION: "M",
79
80
  PASSING: "P",
80
81
  STRENGTH: "S",
82
+ SPECIAL: "SP",
81
83
  };
82
84
  // type : "E", "P", "M", "S", "A", "G"
83
85
  // E: EXTRAORDINARY
@@ -86,12 +88,14 @@ const SKILL_TYPE = {
86
88
  // S: STRENGTH
87
89
  // A: AGILITY
88
90
  // G: GENERAL
91
+ // SP: SPECIAL
89
92
  // TODO: add text translation when add a skill
90
93
  const SKILLS = {
91
94
  [SKILL_NAMES.ACCURATE]: SKILL_TYPE.PASSING,
92
95
  [SKILL_NAMES.ALWAYS_HUNGRY]: SKILL_TYPE.EXTRAORDINARY,
93
96
  [SKILL_NAMES.ANIMAL_SAVAGERY]: SKILL_TYPE.EXTRAORDINARY,
94
- [SKILL_NAMES.BIG_GUY]: SKILL_TYPE.EXTRAORDINARY,
97
+ [SKILL_NAMES.ANIMOSITY]: SKILL_TYPE.SPECIAL,
98
+ [SKILL_NAMES.BIG_GUY]: SKILL_TYPE.SPECIAL,
95
99
  [SKILL_NAMES.BIG_HAND]: SKILL_TYPE.MUTATION,
96
100
  [SKILL_NAMES.BLOCK]: SKILL_TYPE.GENERAL,
97
101
  [SKILL_NAMES.BONE_HEAD]: SKILL_TYPE.EXTRAORDINARY,
@@ -131,10 +135,10 @@ const SKILLS = {
131
135
  [SKILL_NAMES.SAFE_PASS]: SKILL_TYPE.PASSING,
132
136
  [SKILL_NAMES.SHADOWING]: SKILL_TYPE.GENERAL,
133
137
  [SKILL_NAMES.SNEAKY_GIT]: SKILL_TYPE.AGILITY,
134
- [SKILL_NAMES.SPECIALIST]: SKILL_TYPE.EXTRAORDINARY,
138
+ [SKILL_NAMES.SPECIALIST]: SKILL_TYPE.SPECIAL,
135
139
  [SKILL_NAMES.SPRINT]: SKILL_TYPE.AGILITY,
136
140
  [SKILL_NAMES.STAND_FIRM]: SKILL_TYPE.STRENGTH,
137
- [SKILL_NAMES.STAR]: SKILL_TYPE.EXTRAORDINARY,
141
+ [SKILL_NAMES.STAR]: SKILL_TYPE.SPECIAL,
138
142
  [SKILL_NAMES.STRIP_BALL]: SKILL_TYPE.GENERAL,
139
143
  [SKILL_NAMES.STRONG_ARM]: SKILL_TYPE.STRENGTH,
140
144
  [SKILL_NAMES.STUNTY]: SKILL_TYPE.EXTRAORDINARY,
@@ -212,6 +216,11 @@ const getPlayersWithSkill = (players, skillId) => {
212
216
  return list;
213
217
  };
214
218
 
219
+ const hasSkillDisplayableInfo = (skillId) => {
220
+ const activables = [SKILL_NAMES.LONER, SKILL_NAMES.ANIMOSITY];
221
+ return activables.includes(skillId);
222
+ };
223
+
215
224
  const isActivableSkills = (skill) => {
216
225
  const activables = [
217
226
  SKILL_NAMES.BRAWLER,
@@ -288,19 +297,26 @@ function getDisturbingPresenceMalus(player, players) {
288
297
  return malus;
289
298
  }
290
299
 
300
+ const isSpecialSkill = (skill) => {
301
+ skillId = skill.skill_id ? skill.skill_id : skill;
302
+ return SKILLS[skillId] === SKILL_TYPE.SPECIAL;
303
+ };
304
+
291
305
  module.exports = {
292
306
  BIG_GUY_LIMIT,
307
+ getDisturbingPresenceMalus,
293
308
  getPlayersWithSkill,
294
309
  getSkill,
295
310
  getSkillLimitSizeTeam,
296
311
  getSpecialistLimit,
297
312
  getStarLimit,
298
313
  hasSkill,
314
+ hasSkillDisplayableInfo,
299
315
  isActivableSkills,
316
+ isSpecialSkill,
300
317
  SKILL_INFO_ACTIVE,
301
318
  SKILL_INFO_INACTIVE,
302
319
  SKILL_NAMES,
303
320
  SKILLS,
304
321
  useSkill,
305
- getDisturbingPresenceMalus,
306
322
  };
package/stadium.js CHANGED
@@ -1,4 +1,4 @@
1
- const { INITIAL_REROLL, p } = require(".");
1
+ const { INITIAL_REROLL } = require(".");
2
2
  const { d6 } = require("./random");
3
3
 
4
4
  const MIN_SCRIMMAGE = 3; // TODO: in league param
package/state.js CHANGED
@@ -85,12 +85,42 @@ function shouldBeRemovedFromTeam(state) {
85
85
  return state === PLAYER_STATE.BLOCKED || state === PLAYER_STATE.DEAD;
86
86
  }
87
87
 
88
+ const getPlayersByState = (players) => {
89
+ const playerActives = [];
90
+ const playerInactives = [];
91
+ let lastRetired = null;
92
+
93
+ for (const p of players) {
94
+ if (canBeSelectedByUser(p.state)) {
95
+ playerActives.push(p);
96
+ } else {
97
+ playerInactives.push(p);
98
+ }
99
+ }
100
+
101
+ for (player of playerInactives) {
102
+ if (!lastRetired) {
103
+ lastRetired = player;
104
+ }
105
+ if (player.connectedAt > lastRetired.connectedAt) {
106
+ lastRetired = player;
107
+ }
108
+ }
109
+
110
+ return {
111
+ actives: playerActives,
112
+ inactives: playerInactives,
113
+ lastRetired,
114
+ };
115
+ };
116
+
88
117
  module.exports = {
89
118
  canBeSelectedByUser,
90
119
  canJoinTeamWithState,
91
120
  canPlayLeague,
92
121
  canTeamPlayLeague,
93
122
  getPlayableStates,
123
+ getPlayersByState,
94
124
  isActive,
95
125
  isBlocked,
96
126
  isDead,