gotchi-battler-game-logic 3.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.cursor/rules/cursor-rules.mdc +67 -0
  2. package/.cursor/rules/directory-structure.mdc +63 -0
  3. package/.cursor/rules/self-improvement.mdc +64 -0
  4. package/.cursor/rules/tech-stack.mdc +99 -0
  5. package/README.md +4 -0
  6. package/eslint.config.js +31 -0
  7. package/game-logic/index.js +2 -6
  8. package/game-logic/v1.4/constants.js +0 -23
  9. package/game-logic/v1.4/index.js +64 -56
  10. package/game-logic/v1.5/constants.js +0 -23
  11. package/game-logic/v1.5/index.js +27 -21
  12. package/game-logic/v1.6/constants.js +0 -23
  13. package/game-logic/v1.6/index.js +27 -21
  14. package/game-logic/v1.7/constants.js +0 -23
  15. package/game-logic/v1.7/helpers.js +2 -2
  16. package/game-logic/v1.7/index.js +24 -18
  17. package/game-logic/v1.8/constants.js +0 -23
  18. package/game-logic/v1.8/helpers.js +2 -2
  19. package/game-logic/v1.8/index.js +25 -19
  20. package/game-logic/v2.0/constants.js +112 -0
  21. package/game-logic/v2.0/helpers.js +713 -0
  22. package/game-logic/v2.0/index.js +782 -0
  23. package/game-logic/v2.0/statuses.json +439 -0
  24. package/package.json +11 -4
  25. package/schemas/crystal.js +14 -0
  26. package/schemas/effect.js +25 -0
  27. package/schemas/gotchi.js +53 -0
  28. package/schemas/ingameteam.js +14 -0
  29. package/schemas/item.js +13 -0
  30. package/schemas/leaderskill.js +15 -0
  31. package/schemas/leaderskillstatus.js +12 -0
  32. package/schemas/special.js +22 -0
  33. package/schemas/team.js +24 -0
  34. package/schemas/team.json +252 -114
  35. package/scripts/balancing/createTrainingGotchis.js +44 -44
  36. package/scripts/balancing/extractOnchainTraits.js +3 -3
  37. package/scripts/balancing/fixTrainingGotchis.js +41 -41
  38. package/scripts/balancing/processSims.js +5 -5
  39. package/scripts/balancing/sims.js +8 -15
  40. package/scripts/balancing/v1.7/setTeamPositions.js +2 -2
  41. package/scripts/balancing/v1.7.1/setTeamPositions.js +2 -2
  42. package/scripts/balancing/v1.7.2/setTeamPositions.js +2 -2
  43. package/scripts/balancing/v1.7.3/setTeamPositions.js +2 -2
  44. package/scripts/data/dungeon_mob_1.json +87 -0
  45. package/scripts/data/dungeon_mob_2.json +87 -0
  46. package/scripts/data/immaterialTeam1.json +374 -0
  47. package/scripts/data/immaterialTeam2.json +365 -0
  48. package/scripts/generateAllSpecialsLogs.js +93 -0
  49. package/scripts/generateSpecialLogs.js +94 -0
  50. package/scripts/runCampaignBattles.js +41 -0
  51. package/scripts/runLocalBattle.js +6 -3
  52. package/scripts/runLocalDungeon.js +52 -0
  53. package/scripts/runPvPBattle.js +15 -0
  54. package/scripts/runRealBattle.js +8 -8
  55. package/scripts/simRealBattle.js +8 -8
  56. package/scripts/validateBattle.js +12 -14
  57. package/scripts/validateTournament.js +9 -9
  58. package/tests/getModifiedStats.test.js +78 -0
  59. package/utils/errors.js +13 -13
  60. package/utils/transforms.js +2 -8
  61. package/scripts/output/.gitkeep +0 -0
@@ -128,7 +128,7 @@ const getNextToAct = (team1, team2, rng) => {
128
128
 
129
129
  const getTarget = (defendingTeam, rng) => {
130
130
  // Check for taunt gotchis
131
- const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes("taunt"))
131
+ const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes('taunt'))
132
132
 
133
133
  if (taunt.length) {
134
134
  if (taunt.length === 1) return taunt[0]
@@ -513,7 +513,7 @@ const scrambleGotchiIds = (allAliveGotchis, team1, team2) => {
513
513
  **/
514
514
  const prepareTeams = (allAliveGotchis, team1, team2) => {
515
515
  // check there's no duplicate gotchis
516
- scrambleGotchiIds(allAliveGotchis, team1, team2);
516
+ scrambleGotchiIds(allAliveGotchis, team1, team2)
517
517
 
518
518
  allAliveGotchis.forEach(x => {
519
519
  // Add statuses property to all gotchis
@@ -535,7 +535,7 @@ const prepareTeams = (allAliveGotchis, team1, team2) => {
535
535
 
536
536
  // Add leader passive to team
537
537
  addLeaderToTeam(team1)
538
- addLeaderToTeam(team2);
538
+ addLeaderToTeam(team2)
539
539
  }
540
540
 
541
541
  /**
@@ -581,20 +581,20 @@ const getLogGotchis = (allAliveGotchis) => {
581
581
  * @returns {Object} logs The battle logs
582
582
  */
583
583
  const gameLoop = (team1, team2, seed, debug) => {
584
- if (!team1) throw new Error("Team 1 not found")
585
- if (!team2) throw new Error("Team 2 not found")
586
- if (!seed) throw new Error("Seed not found")
584
+ if (!team1) throw new Error('Team 1 not found')
585
+ if (!team2) throw new Error('Team 2 not found')
586
+ if (!seed) throw new Error('Seed not found')
587
587
 
588
588
  // Validate team objects
589
589
  const team1Validation = validator.validate(team1, teamSchema)
590
590
  if (!team1Validation) {
591
591
  console.error('Team 1 validation failed: ', JSON.stringify(validator.getLastErrors(), null, 2))
592
- throw new Error(`Team 1 validation failed`)
592
+ throw new Error('Team 1 validation failed')
593
593
  }
594
594
  const team2Validation = validator.validate(team2, teamSchema)
595
595
  if (!team2Validation) {
596
596
  console.error('Team 2 validation failed: ', JSON.stringify(validator.getLastErrors(), null, 2))
597
- throw new Error(`Team 2 validation failed`)
597
+ throw new Error('Team 2 validation failed')
598
598
  }
599
599
 
600
600
  const rng = seedrandom(seed)
@@ -612,7 +612,7 @@ const gameLoop = (team1, team2, seed, debug) => {
612
612
  ]
613
613
  },
614
614
  turns: []
615
- };
615
+ }
616
616
 
617
617
  // Used for turn by turn health and status summaries
618
618
  // Deleted if not in development or no errors
@@ -640,7 +640,7 @@ const gameLoop = (team1, team2, seed, debug) => {
640
640
  turnLogs.statusesExpired = [...turnLogs.statusesExpired, ...getExpiredStatuses(team1, team2)]
641
641
  }
642
642
 
643
- logs.turns.push({index: turnCounter, ...turnLogs})
643
+ logs.turns.push({ index: turnCounter, ...turnLogs })
644
644
 
645
645
  if (debug) {
646
646
  logs.debug.push({
@@ -850,12 +850,10 @@ const attack = (attackingGotchi, attackingTeam, defendingTeam, defendingTargets,
850
850
  }
851
851
 
852
852
  // Deal with start of turn status effects
853
- const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
853
+ const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam) => {
854
854
  const statusEffects = []
855
855
  const passiveEffects = []
856
856
 
857
- const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
858
-
859
857
  // Check for cleansing_aura
860
858
  // if (attackingGotchi.statuses.includes('cleansing_aura')) {
861
859
  // // Remove all debuffs from all allies
@@ -1098,7 +1096,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1098
1096
  const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
1099
1097
 
1100
1098
  switch (specialId) {
1101
- case 1:
1099
+ case 1: {
1102
1100
  // Spectral Strike - ignore armor and appply bleed status
1103
1101
  // get single target
1104
1102
  const ssTarget = getTarget(defendingTeam, rng)
@@ -1113,7 +1111,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1113
1111
  noResistSpeedPenalty: true
1114
1112
  })
1115
1113
  break
1116
- case 2:
1114
+ }
1115
+ case 2: {
1117
1116
  // Meditate - Boost own speed, magic, physical by 30%
1118
1117
  // If gotchi already has 2 power_up statuses, do nothing
1119
1118
  if (!addStatusToGotchi(attackingGotchi, 'power_up_2')) {
@@ -1147,7 +1146,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1147
1146
  }
1148
1147
 
1149
1148
  break
1150
- case 3:
1149
+ }
1150
+ case 3: {
1151
1151
  // Cleave - attack all enemies in a row (that have the most gotchis) for 75% damage
1152
1152
  // Find row with most gotchis
1153
1153
  const cleaveRow = getAlive(defendingTeam, 'front').length > getAlive(defendingTeam, 'back').length ? 'front' : 'back'
@@ -1159,7 +1159,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1159
1159
  noPassiveStatuses: true
1160
1160
  })
1161
1161
  break
1162
- case 4:
1162
+ }
1163
+ case 4: {
1163
1164
  // Taunt - add taunt status to self
1164
1165
 
1165
1166
  // Check if gotchi already has taunt status
@@ -1181,7 +1182,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1181
1182
  }
1182
1183
  ]
1183
1184
  break
1184
- case 5:
1185
+ }
1186
+ case 5: {
1185
1187
  // Curse - attack random enemy for 50% damage, apply fear status and remove all buffs
1186
1188
 
1187
1189
  const curseTarget = getTarget(defendingTeam, rng)
@@ -1228,7 +1230,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1228
1230
  }
1229
1231
 
1230
1232
  break
1231
- case 6:
1233
+ }
1234
+ case 6: {
1232
1235
  // Blessing - Heal all non-healer allies and remove all debuffs
1233
1236
 
1234
1237
  // Get all alive non-healer allies on the attacking team
@@ -1292,7 +1295,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1292
1295
  }
1293
1296
 
1294
1297
  break
1295
- case 7:
1298
+ }
1299
+ case 7: {
1296
1300
  // Thunder - Attack all enemies for 50% damage and apply stun status
1297
1301
 
1298
1302
  const thunderTargets = getAlive(defendingTeam)
@@ -1318,7 +1322,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1318
1322
  }
1319
1323
 
1320
1324
  break
1321
- case 8:
1325
+ }
1326
+ case 8: {
1322
1327
  // Devestating Smash - Attack random enemy for 200% damage
1323
1328
 
1324
1329
  const smashTarget = getTarget(defendingTeam, rng)
@@ -1362,6 +1367,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1362
1367
  }
1363
1368
 
1364
1369
  break
1370
+ }
1365
1371
  }
1366
1372
 
1367
1373
  return {
@@ -86,29 +86,6 @@ const MULTS = {
86
86
  CLAN_MOMENTUM_DAMAGE: 3.1
87
87
  }
88
88
 
89
- const passiveIcons = {
90
- 'sharp_blades': 'https://game-icons.net/1x1/lorc/plain-dagger.html',
91
- 'cloud_of_zen': 'https://game-icons.net/1x1/lorc/meditation.html',
92
- 'frenzy': 'https://game-icons.net/1x1/lorc/totem-head.html',
93
- 'fortify': 'https://game-icons.net/1x1/lorc/crenulated-shield.html',
94
- 'spread_the_fear': 'https://game-icons.net/1x1/lorc/evil-book.html',
95
- 'cleansing_aura': 'https://game-icons.net/1x1/lorc/aura.html',
96
- 'channel_the_coven': 'https://game-icons.net/1x1/lorc/witch-flight.html',
97
- 'clan_momentum': 'https://game-icons.net/1x1/delapouite/bully-minion.html'
98
- }
99
-
100
- const debuffIcons = {
101
- 'bleed': 'https://game-icons.net/1x1/lorc/broken-heart.html',
102
- 'stun': 'https://game-icons.net/1x1/sbed/electric.html',
103
- 'fear': 'https://game-icons.net/1x1/lorc/screaming.html'
104
- }
105
-
106
- const buffIcons = {
107
- 'taunt': 'https://game-icons.net/1x1/lorc/archery-target.html',
108
- 'power_up_1': 'https://game-icons.net/1x1/lorc/strong.html',
109
- 'power_up_2': 'https://game-icons.net/1x1/delapouite/mighty-force.html'
110
- }
111
-
112
89
  module.exports = {
113
90
  PASSIVES,
114
91
  DEBUFF_STATUSES,
@@ -128,7 +128,7 @@ const getNextToAct = (team1, team2, rng) => {
128
128
 
129
129
  const getTarget = (defendingTeam, rng) => {
130
130
  // Check for taunt gotchis
131
- const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes("taunt"))
131
+ const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes('taunt'))
132
132
 
133
133
  if (taunt.length) {
134
134
  if (taunt.length === 1) return taunt[0]
@@ -513,7 +513,7 @@ const scrambleGotchiIds = (allAliveGotchis, team1, team2) => {
513
513
  **/
514
514
  const prepareTeams = (allAliveGotchis, team1, team2) => {
515
515
  // check there's no duplicate gotchis
516
- scrambleGotchiIds(allAliveGotchis, team1, team2);
516
+ scrambleGotchiIds(allAliveGotchis, team1, team2)
517
517
 
518
518
  allAliveGotchis.forEach(x => {
519
519
  // Add statuses property to all gotchis
@@ -535,7 +535,7 @@ const prepareTeams = (allAliveGotchis, team1, team2) => {
535
535
 
536
536
  // Add leader passive to team
537
537
  addLeaderToTeam(team1)
538
- addLeaderToTeam(team2);
538
+ addLeaderToTeam(team2)
539
539
  }
540
540
 
541
541
  /**
@@ -581,20 +581,20 @@ const getLogGotchis = (allAliveGotchis) => {
581
581
  * @returns {Object} logs The battle logs
582
582
  */
583
583
  const gameLoop = (team1, team2, seed, debug) => {
584
- if (!team1) throw new Error("Team 1 not found")
585
- if (!team2) throw new Error("Team 2 not found")
586
- if (!seed) throw new Error("Seed not found")
584
+ if (!team1) throw new Error('Team 1 not found')
585
+ if (!team2) throw new Error('Team 2 not found')
586
+ if (!seed) throw new Error('Seed not found')
587
587
 
588
588
  // Validate team objects
589
589
  const team1Validation = validator.validate(team1, teamSchema)
590
590
  if (!team1Validation) {
591
591
  console.error('Team 1 validation failed: ', JSON.stringify(validator.getLastErrors(), null, 2))
592
- throw new Error(`Team 1 validation failed`)
592
+ throw new Error('Team 1 validation failed')
593
593
  }
594
594
  const team2Validation = validator.validate(team2, teamSchema)
595
595
  if (!team2Validation) {
596
596
  console.error('Team 2 validation failed: ', JSON.stringify(validator.getLastErrors(), null, 2))
597
- throw new Error(`Team 2 validation failed`)
597
+ throw new Error('Team 2 validation failed')
598
598
  }
599
599
 
600
600
  // Make deep copy of team objects to avoid modifying the original objects
@@ -616,7 +616,7 @@ const gameLoop = (team1, team2, seed, debug) => {
616
616
  ]
617
617
  },
618
618
  turns: []
619
- };
619
+ }
620
620
 
621
621
  // Used for turn by turn health and status summaries
622
622
  // Deleted if not in development or no errors
@@ -644,7 +644,7 @@ const gameLoop = (team1, team2, seed, debug) => {
644
644
  turnLogs.statusesExpired = [...turnLogs.statusesExpired, ...getExpiredStatuses(team1, team2)]
645
645
  }
646
646
 
647
- logs.turns.push({index: turnCounter, ...turnLogs})
647
+ logs.turns.push({ index: turnCounter, ...turnLogs })
648
648
 
649
649
  if (debug) {
650
650
  logs.debug.push({
@@ -854,12 +854,10 @@ const attack = (attackingGotchi, attackingTeam, defendingTeam, defendingTargets,
854
854
  }
855
855
 
856
856
  // Deal with start of turn status effects
857
- const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
857
+ const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam) => {
858
858
  const statusEffects = []
859
859
  const passiveEffects = []
860
860
 
861
- const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
862
-
863
861
  // Check for cleansing_aura
864
862
  // if (attackingGotchi.statuses.includes('cleansing_aura')) {
865
863
  // // Remove all debuffs from all allies
@@ -1103,7 +1101,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1103
1101
  const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
1104
1102
 
1105
1103
  switch (specialId) {
1106
- case 1:
1104
+ case 1: {
1107
1105
  // Spectral Strike - ignore armor and appply bleed status
1108
1106
  // get single target
1109
1107
  const ssTarget = getTarget(defendingTeam, rng)
@@ -1118,7 +1116,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1118
1116
  noResistSpeedPenalty: true
1119
1117
  })
1120
1118
  break
1121
- case 2:
1119
+ }
1120
+ case 2: {
1122
1121
  // Meditate - Boost own speed, magic, physical by 30%
1123
1122
  // If gotchi already has 2 power_up statuses, do nothing
1124
1123
  if (!addStatusToGotchi(attackingGotchi, 'power_up_2')) {
@@ -1152,7 +1151,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1152
1151
  }
1153
1152
 
1154
1153
  break
1155
- case 3:
1154
+ }
1155
+ case 3: {
1156
1156
  // Cleave - attack all enemies in a row (that have the most gotchis) for 75% damage
1157
1157
  // Find row with most gotchis
1158
1158
  const cleaveRow = getAlive(defendingTeam, 'front').length > getAlive(defendingTeam, 'back').length ? 'front' : 'back'
@@ -1164,7 +1164,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1164
1164
  noPassiveStatuses: true
1165
1165
  })
1166
1166
  break
1167
- case 4:
1167
+ }
1168
+ case 4: {
1168
1169
  // Taunt - add taunt status to self
1169
1170
 
1170
1171
  // Check if gotchi already has taunt status
@@ -1186,7 +1187,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1186
1187
  }
1187
1188
  ]
1188
1189
  break
1189
- case 5:
1190
+ }
1191
+ case 5: {
1190
1192
  // Curse - attack random enemy for 50% damage, apply fear status and remove all buffs
1191
1193
 
1192
1194
  const curseTarget = getTarget(defendingTeam, rng)
@@ -1251,7 +1253,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1251
1253
  }
1252
1254
 
1253
1255
  break
1254
- case 6:
1256
+ }
1257
+ case 6: {
1255
1258
  // Blessing - Heal all non-healer allies and remove all debuffs
1256
1259
 
1257
1260
  // Get all alive non-healer allies on the attacking team
@@ -1320,7 +1323,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1320
1323
  }
1321
1324
 
1322
1325
  break
1323
- case 7:
1326
+ }
1327
+ case 7: {
1324
1328
  // Thunder - Attack all enemies for 50% damage and apply stun status
1325
1329
 
1326
1330
  const thunderTargets = getAlive(defendingTeam)
@@ -1347,7 +1351,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1347
1351
  }
1348
1352
 
1349
1353
  break
1350
- case 8:
1354
+ }
1355
+ case 8: {
1351
1356
  // Devestating Smash - Attack random enemy for 200% damage
1352
1357
 
1353
1358
  const smashTarget = getTarget(defendingTeam, rng)
@@ -1391,6 +1396,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
1391
1396
  }
1392
1397
 
1393
1398
  break
1399
+ }
1394
1400
  }
1395
1401
 
1396
1402
  return {
@@ -105,29 +105,6 @@ const MULTS = {
105
105
  DEVESTATING_SMASH_X2_DAMAGE: 1.5,
106
106
  }
107
107
 
108
- const passiveIcons = {
109
- 'sharp_blades': 'https://game-icons.net/1x1/lorc/plain-dagger.html',
110
- 'cloud_of_zen': 'https://game-icons.net/1x1/lorc/meditation.html',
111
- 'frenzy': 'https://game-icons.net/1x1/lorc/totem-head.html',
112
- 'fortify': 'https://game-icons.net/1x1/lorc/crenulated-shield.html',
113
- 'spread_the_fear': 'https://game-icons.net/1x1/lorc/evil-book.html',
114
- 'cleansing_aura': 'https://game-icons.net/1x1/lorc/aura.html',
115
- 'channel_the_coven': 'https://game-icons.net/1x1/lorc/witch-flight.html',
116
- 'clan_momentum': 'https://game-icons.net/1x1/delapouite/bully-minion.html'
117
- }
118
-
119
- const debuffIcons = {
120
- 'bleed': 'https://game-icons.net/1x1/lorc/broken-heart.html',
121
- 'stun': 'https://game-icons.net/1x1/sbed/electric.html',
122
- 'fear': 'https://game-icons.net/1x1/lorc/screaming.html'
123
- }
124
-
125
- const buffIcons = {
126
- 'taunt': 'https://game-icons.net/1x1/lorc/archery-target.html',
127
- 'power_up_1': 'https://game-icons.net/1x1/lorc/strong.html',
128
- 'power_up_2': 'https://game-icons.net/1x1/delapouite/mighty-force.html'
129
- }
130
-
131
108
  module.exports = {
132
109
  PASSIVES,
133
110
  DEBUFF_STATUSES,
@@ -119,7 +119,7 @@ const getNextToAct = (team1, team2, rng) => {
119
119
 
120
120
  const getTarget = (defendingTeam, rng) => {
121
121
  // Check for taunt gotchis
122
- const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes("taunt"))
122
+ const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes('taunt'))
123
123
 
124
124
  if (taunt.length) {
125
125
  if (taunt.length === 1) return taunt[0]
@@ -509,7 +509,7 @@ const scrambleGotchiIds = (allAliveGotchis, team1, team2) => {
509
509
  **/
510
510
  const prepareTeams = (allAliveGotchis, team1, team2) => {
511
511
  // check there's no duplicate gotchis
512
- scrambleGotchiIds(allAliveGotchis, team1, team2);
512
+ scrambleGotchiIds(allAliveGotchis, team1, team2)
513
513
 
514
514
  // Apply stat items
515
515
  applyStatItems(allAliveGotchis)
@@ -35,20 +35,20 @@ const {
35
35
  * @returns {Object} logs The battle logs
36
36
  */
37
37
  const gameLoop = (team1, team2, seed, debug) => {
38
- if (!team1) throw new Error("Team 1 not found")
39
- if (!team2) throw new Error("Team 2 not found")
40
- if (!seed) throw new Error("Seed not found")
38
+ if (!team1) throw new Error('Team 1 not found')
39
+ if (!team2) throw new Error('Team 2 not found')
40
+ if (!seed) throw new Error('Seed not found')
41
41
 
42
42
  // Validate team objects
43
43
  const team1Validation = validator.validate(team1, teamSchema)
44
44
  if (!team1Validation) {
45
45
  console.error('Team 1 validation failed: ', JSON.stringify(validator.getLastErrors(), null, 2))
46
- throw new Error(`Team 1 validation failed`)
46
+ throw new Error('Team 1 validation failed')
47
47
  }
48
48
  const team2Validation = validator.validate(team2, teamSchema)
49
49
  if (!team2Validation) {
50
50
  console.error('Team 2 validation failed: ', JSON.stringify(validator.getLastErrors(), null, 2))
51
- throw new Error(`Team 2 validation failed`)
51
+ throw new Error('Team 2 validation failed')
52
52
  }
53
53
 
54
54
  // Make deep copy of team objects to avoid modifying the original objects
@@ -70,7 +70,7 @@ const gameLoop = (team1, team2, seed, debug) => {
70
70
  ]
71
71
  },
72
72
  turns: []
73
- };
73
+ }
74
74
 
75
75
  // Used for turn by turn health and status summaries
76
76
  // Deleted if not in development or no errors
@@ -98,7 +98,7 @@ const gameLoop = (team1, team2, seed, debug) => {
98
98
  turnLogs.statusesExpired = [...turnLogs.statusesExpired, ...getExpiredStatuses(team1, team2)]
99
99
  }
100
100
 
101
- logs.turns.push({index: turnCounter, ...turnLogs})
101
+ logs.turns.push({ index: turnCounter, ...turnLogs })
102
102
 
103
103
  if (debug) {
104
104
  logs.debug.push({
@@ -306,12 +306,10 @@ const attack = (attackingGotchi, attackingTeam, defendingTeam, defendingTargets,
306
306
  }
307
307
 
308
308
  // Deal with start of turn status effects
309
- const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
309
+ const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam) => {
310
310
  const statusEffects = []
311
311
  const passiveEffects = []
312
312
 
313
- const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
314
-
315
313
  // Check for global status effects
316
314
  const allAliveGotchis = [...getAlive(attackingTeam), ...getAlive(defendingTeam)]
317
315
 
@@ -513,7 +511,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
513
511
  const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
514
512
 
515
513
  switch (specialId) {
516
- case 1:
514
+ case 1: {
517
515
  // Spectral Strike - ignore armor and appply bleed status
518
516
  // get single target
519
517
  const ssTarget = getTarget(defendingTeam, rng)
@@ -528,7 +526,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
528
526
  noResistSpeedPenalty: true
529
527
  })
530
528
  break
531
- case 2:
529
+ }
530
+ case 2: {
532
531
  // Meditate - Boost own speed, magic, physical by 30%
533
532
  // If gotchi already has 2 power_up statuses, do nothing
534
533
  if (!addStatusToGotchi(attackingGotchi, 'power_up_2')) {
@@ -562,7 +561,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
562
561
  }
563
562
 
564
563
  break
565
- case 3:
564
+ }
565
+ case 3: {
566
566
  // Cleave - attack all enemies in a row (that have the most gotchis) for 75% damage
567
567
  // Find row with most gotchis
568
568
  const cleaveRow = getAlive(defendingTeam, 'front').length > getAlive(defendingTeam, 'back').length ? 'front' : 'back'
@@ -574,7 +574,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
574
574
  noPassiveStatuses: true
575
575
  })
576
576
  break
577
- case 4:
577
+ }
578
+ case 4: {
578
579
  // Taunt - add taunt status to self
579
580
 
580
581
  // Check if gotchi already has taunt status
@@ -596,7 +597,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
596
597
  }
597
598
  ]
598
599
  break
599
- case 5:
600
+ }
601
+ case 5: {
600
602
  // Curse - attack random enemy for 50% damage, apply fear status and remove all buffs
601
603
 
602
604
  const curseTarget = getTarget(defendingTeam, rng)
@@ -661,7 +663,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
661
663
  }
662
664
 
663
665
  break
664
- case 6:
666
+ }
667
+ case 6: {
665
668
  // Blessing - Heal all non-healer allies and remove all debuffs
666
669
 
667
670
  // Get all alive non-healer allies on the attacking team
@@ -731,7 +734,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
731
734
  }
732
735
 
733
736
  break
734
- case 7:
737
+ }
738
+ case 7: {
735
739
  // Thunder - Attack all enemies for 50% damage and apply stun status
736
740
 
737
741
  const thunderTargets = getAlive(defendingTeam)
@@ -752,7 +756,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
752
756
  })
753
757
 
754
758
  break
755
- case 8:
759
+ }
760
+ case 8: {
756
761
  // Devestating Smash - Attack random enemy for 200% damage
757
762
 
758
763
  const smashTarget = getTarget(defendingTeam, rng)
@@ -787,6 +792,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
787
792
  }
788
793
 
789
794
  break
795
+ }
790
796
  }
791
797
 
792
798
  return {
@@ -98,29 +98,6 @@ const MULTS = {
98
98
  DEVESTATING_SMASH_X2_DAMAGE: 1.9,
99
99
  }
100
100
 
101
- const passiveIcons = {
102
- 'sharp_blades': 'https://game-icons.net/1x1/lorc/plain-dagger.html',
103
- 'cloud_of_zen': 'https://game-icons.net/1x1/lorc/meditation.html',
104
- 'frenzy': 'https://game-icons.net/1x1/lorc/totem-head.html',
105
- 'fortify': 'https://game-icons.net/1x1/lorc/crenulated-shield.html',
106
- 'spread_the_fear': 'https://game-icons.net/1x1/lorc/evil-book.html',
107
- 'cleansing_aura': 'https://game-icons.net/1x1/lorc/aura.html',
108
- 'channel_the_coven': 'https://game-icons.net/1x1/lorc/witch-flight.html',
109
- 'clan_momentum': 'https://game-icons.net/1x1/delapouite/bully-minion.html'
110
- }
111
-
112
- const debuffIcons = {
113
- 'bleed': 'https://game-icons.net/1x1/lorc/broken-heart.html',
114
- 'stun': 'https://game-icons.net/1x1/sbed/electric.html',
115
- 'fear': 'https://game-icons.net/1x1/lorc/screaming.html'
116
- }
117
-
118
- const buffIcons = {
119
- 'taunt': 'https://game-icons.net/1x1/lorc/archery-target.html',
120
- 'cloud_of_zen': 'https://game-icons.net/1x1/lorc/strong.html',
121
- 'power_up_2': 'https://game-icons.net/1x1/delapouite/mighty-force.html'
122
- }
123
-
124
101
  module.exports = {
125
102
  PASSIVES,
126
103
  DEBUFF_STATUSES,
@@ -119,7 +119,7 @@ const getNextToAct = (team1, team2, rng) => {
119
119
 
120
120
  const getTarget = (defendingTeam, rng) => {
121
121
  // Check for taunt gotchis
122
- const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes("taunt"))
122
+ const taunt = [...getAlive(defendingTeam, 'front'), ...getAlive(defendingTeam, 'back')].filter(gotchi => gotchi.statuses && gotchi.statuses.includes('taunt'))
123
123
 
124
124
  if (taunt.length) {
125
125
  if (taunt.length === 1) return taunt[0]
@@ -526,7 +526,7 @@ const scrambleGotchiIds = (allAliveGotchis, team1, team2) => {
526
526
  **/
527
527
  const prepareTeams = (allAliveGotchis, team1, team2) => {
528
528
  // check there's no duplicate gotchis
529
- scrambleGotchiIds(allAliveGotchis, team1, team2);
529
+ scrambleGotchiIds(allAliveGotchis, team1, team2)
530
530
 
531
531
  // Apply stat items
532
532
  applyStatItems(allAliveGotchis)