gotchi-battler-game-logic 3.0.0 → 4.0.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/.cursor/rules/cursor-rules.mdc +67 -0
- package/.cursor/rules/directory-structure.mdc +63 -0
- package/.cursor/rules/self-improvement.mdc +64 -0
- package/.cursor/rules/tech-stack.mdc +99 -0
- package/README.md +4 -0
- package/eslint.config.js +31 -0
- package/game-logic/index.js +2 -6
- package/game-logic/v1.4/constants.js +0 -23
- package/game-logic/v1.4/index.js +64 -56
- package/game-logic/v1.5/constants.js +0 -23
- package/game-logic/v1.5/index.js +27 -21
- package/game-logic/v1.6/constants.js +0 -23
- package/game-logic/v1.6/index.js +27 -21
- package/game-logic/v1.7/constants.js +0 -23
- package/game-logic/v1.7/helpers.js +2 -2
- package/game-logic/v1.7/index.js +24 -18
- package/game-logic/v1.8/constants.js +0 -23
- package/game-logic/v1.8/helpers.js +2 -2
- package/game-logic/v1.8/index.js +25 -19
- package/game-logic/v2.0/constants.js +112 -0
- package/game-logic/v2.0/helpers.js +713 -0
- package/game-logic/v2.0/index.js +782 -0
- package/game-logic/v2.0/statuses.json +439 -0
- package/package.json +11 -4
- package/schemas/crystal.js +14 -0
- package/schemas/effect.js +25 -0
- package/schemas/gotchi.js +53 -0
- package/schemas/ingameteam.js +14 -0
- package/schemas/item.js +13 -0
- package/schemas/leaderskill.js +15 -0
- package/schemas/leaderskillstatus.js +12 -0
- package/schemas/special.js +22 -0
- package/schemas/team.js +24 -0
- package/schemas/team.json +252 -114
- package/scripts/balancing/createTrainingGotchis.js +44 -44
- package/scripts/balancing/extractOnchainTraits.js +3 -3
- package/scripts/balancing/fixTrainingGotchis.js +41 -41
- package/scripts/balancing/processSims.js +5 -5
- package/scripts/balancing/sims.js +8 -15
- package/scripts/balancing/v1.7/setTeamPositions.js +2 -2
- package/scripts/balancing/v1.7.1/setTeamPositions.js +2 -2
- package/scripts/balancing/v1.7.2/setTeamPositions.js +2 -2
- package/scripts/balancing/v1.7.3/setTeamPositions.js +2 -2
- package/scripts/data/dungeon_mob_1.json +87 -0
- package/scripts/data/dungeon_mob_2.json +87 -0
- package/scripts/data/immaterialTeam1.json +374 -0
- package/scripts/data/immaterialTeam2.json +365 -0
- package/scripts/generateAllSpecialsLogs.js +93 -0
- package/scripts/generateSpecialLogs.js +94 -0
- package/scripts/runCampaignBattles.js +41 -0
- package/scripts/runLocalBattle.js +6 -3
- package/scripts/runLocalDungeon.js +52 -0
- package/scripts/runPvPBattle.js +16 -0
- package/scripts/runRealBattle.js +8 -8
- package/scripts/simRealBattle.js +8 -8
- package/scripts/validateBattle.js +12 -14
- package/scripts/validateTournament.js +9 -9
- package/tests/getModifiedStats.test.js +78 -0
- package/utils/errors.js +13 -13
- package/utils/transforms.js +2 -8
- package/scripts/output/.gitkeep +0 -0
package/game-logic/v1.8/index.js
CHANGED
|
@@ -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(
|
|
39
|
-
if (!team2) throw new Error(
|
|
40
|
-
if (!seed) throw new Error(
|
|
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(
|
|
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(
|
|
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({
|
|
@@ -304,12 +304,10 @@ const attack = (attackingGotchi, attackingTeam, defendingTeam, defendingTargets,
|
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
// Deal with start of turn status effects
|
|
307
|
-
const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam
|
|
307
|
+
const handleStatusEffects = (attackingGotchi, attackingTeam, defendingTeam) => {
|
|
308
308
|
const statusEffects = []
|
|
309
309
|
const passiveEffects = []
|
|
310
310
|
|
|
311
|
-
const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
|
|
312
|
-
|
|
313
311
|
// Check for global status effects
|
|
314
312
|
const allAliveGotchis = [...getAlive(attackingTeam), ...getAlive(defendingTeam)]
|
|
315
313
|
|
|
@@ -511,7 +509,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
511
509
|
const modifiedAttackingGotchi = getModifiedStats(attackingGotchi)
|
|
512
510
|
|
|
513
511
|
switch (specialId) {
|
|
514
|
-
case 1:
|
|
512
|
+
case 1: {
|
|
515
513
|
// Spectral Strike - ignore armor and appply bleed status
|
|
516
514
|
// get single target
|
|
517
515
|
const ssTarget = getTarget(defendingTeam, rng)
|
|
@@ -533,10 +531,11 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
533
531
|
noResistSpeedPenalty: true
|
|
534
532
|
})
|
|
535
533
|
break
|
|
536
|
-
|
|
534
|
+
}
|
|
535
|
+
case 2: {
|
|
537
536
|
// Meditate - Boost own speed, magic, physical by 30%
|
|
538
537
|
|
|
539
|
-
|
|
538
|
+
// Check if gotchi already has power_up_2 status
|
|
540
539
|
if (attackingGotchi.statuses.includes('power_up_2')) {
|
|
541
540
|
specialNotDone = true
|
|
542
541
|
break
|
|
@@ -555,7 +554,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
555
554
|
}
|
|
556
555
|
]
|
|
557
556
|
break
|
|
558
|
-
|
|
557
|
+
}
|
|
558
|
+
case 3: {
|
|
559
559
|
// Cleave - attack all enemies in a row (that have the most gotchis) for 75% damage
|
|
560
560
|
// Find row with most gotchis
|
|
561
561
|
const cleaveRow = getAlive(defendingTeam, 'front').length > getAlive(defendingTeam, 'back').length ? 'front' : 'back'
|
|
@@ -567,7 +567,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
567
567
|
noPassiveStatuses: true
|
|
568
568
|
})
|
|
569
569
|
break
|
|
570
|
-
|
|
570
|
+
}
|
|
571
|
+
case 4: {
|
|
571
572
|
// Taunt - add taunt status to self
|
|
572
573
|
|
|
573
574
|
// Check if gotchi already has taunt status
|
|
@@ -589,7 +590,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
589
590
|
}
|
|
590
591
|
]
|
|
591
592
|
break
|
|
592
|
-
|
|
593
|
+
}
|
|
594
|
+
case 5: {
|
|
593
595
|
// Curse - attack random enemy for 50% damage, apply fear status and remove all buffs
|
|
594
596
|
|
|
595
597
|
const curseTarget = getTarget(defendingTeam, rng)
|
|
@@ -666,7 +668,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
666
668
|
}
|
|
667
669
|
|
|
668
670
|
break
|
|
669
|
-
|
|
671
|
+
}
|
|
672
|
+
case 6: {
|
|
670
673
|
// Blessing - Heal all non-healer allies and remove all debuffs
|
|
671
674
|
|
|
672
675
|
// Get all alive non-healer allies on the attacking team
|
|
@@ -754,7 +757,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
754
757
|
}
|
|
755
758
|
|
|
756
759
|
break
|
|
757
|
-
|
|
760
|
+
}
|
|
761
|
+
case 7: {
|
|
758
762
|
// Thunder - Attack all enemies for 50% damage and apply stun status
|
|
759
763
|
|
|
760
764
|
const thunderTargets = getAlive(defendingTeam)
|
|
@@ -775,7 +779,8 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
775
779
|
})
|
|
776
780
|
|
|
777
781
|
break
|
|
778
|
-
|
|
782
|
+
}
|
|
783
|
+
case 8: {
|
|
779
784
|
// Devestating Smash - Attack random enemy for 200% damage
|
|
780
785
|
|
|
781
786
|
const smashTarget = getTarget(defendingTeam, rng)
|
|
@@ -810,6 +815,7 @@ const specialAttack = (attackingGotchi, attackingTeam, defendingTeam, rng) => {
|
|
|
810
815
|
}
|
|
811
816
|
|
|
812
817
|
break
|
|
818
|
+
}
|
|
813
819
|
}
|
|
814
820
|
|
|
815
821
|
return {
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const PASSIVES = ['sharp_blades', 'cloud_of_zen', 'frenzy', 'fortify', 'spread_the_fear', 'cleansing_aura', 'channel_the_coven', 'clan_momentum']
|
|
2
|
+
const DEBUFF_STATUSES = ['bleed', 'stun', 'fear']
|
|
3
|
+
const BUFF_STATUSES = ['taunt']
|
|
4
|
+
|
|
5
|
+
const BUFF_MULT_EFFECTS = {
|
|
6
|
+
cloud_of_zen: {
|
|
7
|
+
magic: 0.138,
|
|
8
|
+
physical: 0.138
|
|
9
|
+
},
|
|
10
|
+
power_up_2: {
|
|
11
|
+
magic: 0.75,
|
|
12
|
+
physical: 0.50
|
|
13
|
+
},
|
|
14
|
+
frenzy: {
|
|
15
|
+
crit: 1.14
|
|
16
|
+
},
|
|
17
|
+
fortify: {
|
|
18
|
+
armor: 1
|
|
19
|
+
},
|
|
20
|
+
taunt: {
|
|
21
|
+
armor: 1.65
|
|
22
|
+
},
|
|
23
|
+
channel_the_coven: {
|
|
24
|
+
magic: 0.18
|
|
25
|
+
},
|
|
26
|
+
clan_momentum: {
|
|
27
|
+
physical: 0.16
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const BUFF_FLAT_EFFECTS = {
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Combine all buffs
|
|
36
|
+
const BUFFS = [...PASSIVES, ...BUFF_STATUSES, ...Object.keys(BUFF_MULT_EFFECTS), ...Object.keys(BUFF_FLAT_EFFECTS)]
|
|
37
|
+
|
|
38
|
+
const DEBUFF_MULT_EFFECTS = {
|
|
39
|
+
fear: {
|
|
40
|
+
resist: 1
|
|
41
|
+
},
|
|
42
|
+
stun: {
|
|
43
|
+
speed: 0.23
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const DEBUFF_FLAT_EFFECTS = {
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Combine all debuffs
|
|
52
|
+
const DEBUFFS = [...DEBUFF_STATUSES, ...Object.keys(DEBUFF_MULT_EFFECTS), ...Object.keys(DEBUFF_FLAT_EFFECTS)]
|
|
53
|
+
|
|
54
|
+
const MULTS = {
|
|
55
|
+
// General
|
|
56
|
+
FRONT_ROW_ATK_BONUS: 1.1,
|
|
57
|
+
FRONT_ROW_DEF_NERF: 0.8,
|
|
58
|
+
EXPIRE_LEADERSKILL: 0,
|
|
59
|
+
SPEED_PENALTY: 2.5,
|
|
60
|
+
MAX_STATUSES: 3,
|
|
61
|
+
CRIT_MULTIPLIER_FAST: 2,
|
|
62
|
+
CRIT_MULTIPLIER_SLOW: 2,
|
|
63
|
+
// Ninja
|
|
64
|
+
SHARP_BLADES_BLEED_CHANCE: 0.76,
|
|
65
|
+
BLEED_DAMAGE: 10,
|
|
66
|
+
SPECTRAL_STRIKE_DAMAGE: 1.25,
|
|
67
|
+
// Enlightened
|
|
68
|
+
// Cleaver
|
|
69
|
+
CLEAVE_DAMAGE: 1.55,
|
|
70
|
+
// Tank
|
|
71
|
+
COUNTER_SPEED_MULTIPLIER: 0.5,
|
|
72
|
+
FORTIFY_COUNTER_CHANCE: 32,
|
|
73
|
+
COUNTER_DAMAGE: 1.9,
|
|
74
|
+
FORTIFY_COUNTER_DAMAGE: 1.9,
|
|
75
|
+
// Cursed
|
|
76
|
+
SPREAD_THE_FEAR_CHANCE: 0.84,
|
|
77
|
+
SPREAD_THE_FEAR_SPEED_PENALTY: 0,
|
|
78
|
+
SPREAD_THE_FEAR_CURSE_DAMAGE: 1.3,
|
|
79
|
+
CURSE_DAMAGE: 1.2,
|
|
80
|
+
CURSE_HEAL: 1,
|
|
81
|
+
CURSE_SPEED_PENALTY: 0,
|
|
82
|
+
// Healer
|
|
83
|
+
CLEANSING_AURA_REGEN: 0.2,
|
|
84
|
+
CLEANSING_AURA_NON_HEALER_REGEN: 0.1,
|
|
85
|
+
CLEANSING_AURA_HEAL: 3.4,
|
|
86
|
+
CLEANSING_AURA_HEAL_SPEED_PENALTY: 1,
|
|
87
|
+
BLESSING_HEAL: 2.7,
|
|
88
|
+
BLESSING_HEAL_SPEED_PENALTY: 1,
|
|
89
|
+
BLESSING_HEAL_CRIT_MULTIPLIER: 1.25,
|
|
90
|
+
// Mage
|
|
91
|
+
CHANNEL_THE_COVEN_STUN_CHANCE: 0.9,
|
|
92
|
+
THUNDER_STUN_CHANCE: 0.65,
|
|
93
|
+
THUNDER_DAMAGE: 1,
|
|
94
|
+
// Troll
|
|
95
|
+
CLAN_MOMENTUM_CHANCE: 0.9,
|
|
96
|
+
DEVESTATING_SMASH_X2_CHANCE: 0.65,
|
|
97
|
+
DEVESTATING_SMASH_DAMAGE: 2.5,
|
|
98
|
+
DEVESTATING_SMASH_X2_DAMAGE: 1.9,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = {
|
|
102
|
+
PASSIVES,
|
|
103
|
+
DEBUFF_STATUSES,
|
|
104
|
+
BUFF_STATUSES,
|
|
105
|
+
BUFF_MULT_EFFECTS,
|
|
106
|
+
BUFF_FLAT_EFFECTS,
|
|
107
|
+
BUFFS,
|
|
108
|
+
DEBUFF_MULT_EFFECTS,
|
|
109
|
+
DEBUFF_FLAT_EFFECTS,
|
|
110
|
+
DEBUFFS,
|
|
111
|
+
MULTS
|
|
112
|
+
}
|