volleyballsimtypes 0.0.495 → 0.0.497

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.
@@ -13,123 +13,123 @@
13
13
  },
14
14
  "measuredFrom": "prod read-only 2026-07-24: 434 Wishlist rows, 162 with roles; role listing shares"
15
15
  },
16
- "sourceHash": "ec4620ca048d05741b9c42ce6f24a4e7bd04f047c5a420bb93f5a5e711d7adeb",
16
+ "sourceHash": "162d3c45b2932f91e599ed9fa652caa4a0206f8b823340892418778c9247d1a3",
17
17
  "floors": [
18
18
  {
19
19
  "rarity": "COMMON",
20
20
  "role": "SETTER",
21
- "samples": 104658,
21
+ "samples": 104493,
22
22
  "roleBranchShare": 0,
23
- "all": 540.2,
23
+ "all": 540,
24
24
  "focus": {
25
25
  "ATTACK": 172.3,
26
- "SET": 136.7,
26
+ "SET": 166.6,
27
27
  "RECEIVE": 172.6,
28
28
  "SERVE": 93.9,
29
29
  "BLOCK": 175.8,
30
- "STAMINA": 28.6
30
+ "STAMINA": 28.7
31
31
  }
32
32
  },
33
33
  {
34
34
  "rarity": "COMMON",
35
35
  "role": "OUTSIDE_HITTER",
36
- "samples": 1886,
36
+ "samples": 1875,
37
37
  "roleBranchShare": 0,
38
- "all": 545.7,
38
+ "all": 547.1,
39
39
  "focus": {
40
- "ATTACK": 183.8,
41
- "SET": 100,
42
- "RECEIVE": 183.7,
43
- "SERVE": 102.4,
44
- "BLOCK": 181.6,
40
+ "ATTACK": 185.2,
41
+ "SET": 132,
42
+ "RECEIVE": 184.3,
43
+ "SERVE": 102.7,
44
+ "BLOCK": 182.1,
45
45
  "STAMINA": 32.7
46
46
  }
47
47
  },
48
48
  {
49
49
  "rarity": "COMMON",
50
50
  "role": "MIDDLE_BLOCKER",
51
- "samples": 99825,
51
+ "samples": 100149,
52
52
  "roleBranchShare": 0,
53
- "all": 541,
53
+ "all": 540.8,
54
54
  "focus": {
55
- "ATTACK": 177.9,
56
- "SET": 113,
55
+ "ATTACK": 178.1,
56
+ "SET": 143,
57
57
  "RECEIVE": 174.5,
58
58
  "SERVE": 86.9,
59
- "BLOCK": 198.3,
59
+ "BLOCK": 198.1,
60
60
  "STAMINA": 30.4
61
61
  }
62
62
  },
63
63
  {
64
64
  "rarity": "COMMON",
65
65
  "role": "OPPOSITE_HITTER",
66
- "samples": 85837,
66
+ "samples": 85147,
67
67
  "roleBranchShare": 0,
68
68
  "all": 537,
69
69
  "focus": {
70
- "ATTACK": 200.9,
71
- "SET": 112,
70
+ "ATTACK": 200.7,
71
+ "SET": 141.7,
72
72
  "RECEIVE": 172.9,
73
- "SERVE": 92.6,
74
- "BLOCK": 170.4,
73
+ "SERVE": 92.3,
74
+ "BLOCK": 170.6,
75
75
  "STAMINA": 28.5
76
76
  }
77
77
  },
78
78
  {
79
79
  "rarity": "COMMON",
80
80
  "role": "LIBERO",
81
- "samples": 107794,
81
+ "samples": 108336,
82
82
  "roleBranchShare": 0,
83
- "all": 541.4,
83
+ "all": 541.3,
84
84
  "focus": {
85
- "ATTACK": 173.1,
86
- "SET": 117.3,
87
- "RECEIVE": 197.8,
88
- "SERVE": 86.9,
89
- "BLOCK": 174.4,
90
- "STAMINA": 32.1
85
+ "ATTACK": 173,
86
+ "SET": 147.3,
87
+ "RECEIVE": 197.6,
88
+ "SERVE": 87,
89
+ "BLOCK": 174.5,
90
+ "STAMINA": 32
91
91
  }
92
92
  },
93
93
  {
94
94
  "rarity": "RARE",
95
95
  "role": "SETTER",
96
- "samples": 92252,
97
- "roleBranchShare": 0.0888,
98
- "all": 865.3,
96
+ "samples": 92057,
97
+ "roleBranchShare": 0.0889,
98
+ "all": 884.7,
99
99
  "focus": {
100
- "ATTACK": 269,
101
- "SET": 239.4,
102
- "RECEIVE": 299.7,
103
- "SERVE": 176.2,
104
- "BLOCK": 299.9,
105
- "STAMINA": 40.2
100
+ "ATTACK": 288.5,
101
+ "SET": 296.8,
102
+ "RECEIVE": 299.8,
103
+ "SERVE": 176.1,
104
+ "BLOCK": 299.8,
105
+ "STAMINA": 40.1
106
106
  }
107
107
  },
108
108
  {
109
109
  "rarity": "RARE",
110
110
  "role": "OUTSIDE_HITTER",
111
- "samples": 18916,
112
- "roleBranchShare": 0.8573,
113
- "all": 691.4,
111
+ "samples": 18711,
112
+ "roleBranchShare": 0.8516,
113
+ "all": 692.4,
114
114
  "focus": {
115
- "ATTACK": 237.8,
116
- "SET": 114.5,
117
- "RECEIVE": 210.9,
118
- "SERVE": 119.5,
119
- "BLOCK": 207.7,
120
- "STAMINA": 42.7
115
+ "ATTACK": 238.7,
116
+ "SET": 144.1,
117
+ "RECEIVE": 211.3,
118
+ "SERVE": 119.9,
119
+ "BLOCK": 208.5,
120
+ "STAMINA": 42.5
121
121
  }
122
122
  },
123
123
  {
124
124
  "rarity": "RARE",
125
125
  "role": "MIDDLE_BLOCKER",
126
- "samples": 92272,
127
- "roleBranchShare": 0.1525,
128
- "all": 899.1,
126
+ "samples": 91948,
127
+ "roleBranchShare": 0.152,
128
+ "all": 904.7,
129
129
  "focus": {
130
- "ATTACK": 306.8,
131
- "SET": 201.7,
132
- "RECEIVE": 303.5,
130
+ "ATTACK": 312.4,
131
+ "SET": 254.2,
132
+ "RECEIVE": 303.6,
133
133
  "SERVE": 149.3,
134
134
  "BLOCK": 339.8,
135
135
  "STAMINA": 42.6
@@ -138,104 +138,104 @@
138
138
  {
139
139
  "rarity": "RARE",
140
140
  "role": "OPPOSITE_HITTER",
141
- "samples": 100116,
142
- "roleBranchShare": 0.1141,
143
- "all": 895.9,
141
+ "samples": 100430,
142
+ "roleBranchShare": 0.1131,
143
+ "all": 897.4,
144
144
  "focus": {
145
- "ATTACK": 352.3,
146
- "SET": 208.1,
147
- "RECEIVE": 293.3,
148
- "SERVE": 173.1,
149
- "BLOCK": 273.9,
150
- "STAMINA": 40.3
145
+ "ATTACK": 353.7,
146
+ "SET": 265.6,
147
+ "RECEIVE": 293.2,
148
+ "SERVE": 173.2,
149
+ "BLOCK": 273.8,
150
+ "STAMINA": 40.4
151
151
  }
152
152
  },
153
153
  {
154
154
  "rarity": "RARE",
155
155
  "role": "LIBERO",
156
- "samples": 96444,
157
- "roleBranchShare": 0.1067,
158
- "all": 886.5,
156
+ "samples": 96854,
157
+ "roleBranchShare": 0.1072,
158
+ "all": 899.9,
159
159
  "focus": {
160
- "ATTACK": 272,
161
- "SET": 225.8,
162
- "RECEIVE": 349.9,
163
- "SERVE": 154.5,
164
- "BLOCK": 301.7,
160
+ "ATTACK": 285.7,
161
+ "SET": 279.1,
162
+ "RECEIVE": 349.8,
163
+ "SERVE": 154.4,
164
+ "BLOCK": 301.6,
165
165
  "STAMINA": 44.8
166
166
  }
167
167
  },
168
168
  {
169
169
  "rarity": "LEGENDARY",
170
170
  "role": "SETTER",
171
- "samples": 68986,
172
- "roleBranchShare": 0.119,
173
- "all": 1077.5,
171
+ "samples": 69381,
172
+ "roleBranchShare": 0.1187,
173
+ "all": 1090.8,
174
174
  "focus": {
175
- "ATTACK": 368.2,
176
- "SET": 285.7,
177
- "RECEIVE": 362.8,
178
- "SERVE": 186.9,
179
- "BLOCK": 355.3,
175
+ "ATTACK": 381.4,
176
+ "SET": 355.9,
177
+ "RECEIVE": 363,
178
+ "SERVE": 187.1,
179
+ "BLOCK": 355.4,
180
180
  "STAMINA": 48.7
181
181
  }
182
182
  },
183
183
  {
184
184
  "rarity": "LEGENDARY",
185
185
  "role": "OUTSIDE_HITTER",
186
- "samples": 16108,
187
- "roleBranchShare": 0.9988,
188
- "all": 845.7,
186
+ "samples": 16102,
187
+ "roleBranchShare": 0.9987,
188
+ "all": 845.2,
189
189
  "focus": {
190
- "ATTACK": 290.2,
191
- "SET": 140.7,
192
- "RECEIVE": 250.7,
193
- "SERVE": 145.4,
194
- "BLOCK": 250.5,
190
+ "ATTACK": 290.4,
191
+ "SET": 175.5,
192
+ "RECEIVE": 250.4,
193
+ "SERVE": 145.1,
194
+ "BLOCK": 250.2,
195
195
  "STAMINA": 49.5
196
196
  }
197
197
  },
198
198
  {
199
199
  "rarity": "LEGENDARY",
200
200
  "role": "MIDDLE_BLOCKER",
201
- "samples": 116110,
202
- "roleBranchShare": 0.1202,
203
- "all": 1090,
201
+ "samples": 116362,
202
+ "roleBranchShare": 0.1214,
203
+ "all": 1092.9,
204
204
  "focus": {
205
- "ATTACK": 361.5,
206
- "SET": 242.2,
207
- "RECEIVE": 379.6,
208
- "SERVE": 155.6,
209
- "BLOCK": 414.7,
205
+ "ATTACK": 364.9,
206
+ "SET": 303.7,
207
+ "RECEIVE": 379.4,
208
+ "SERVE": 155.5,
209
+ "BLOCK": 414.4,
210
210
  "STAMINA": 49.7
211
211
  }
212
212
  },
213
213
  {
214
214
  "rarity": "LEGENDARY",
215
215
  "role": "OPPOSITE_HITTER",
216
- "samples": 83884,
217
- "roleBranchShare": 0.1336,
218
- "all": 1098.1,
216
+ "samples": 83611,
217
+ "roleBranchShare": 0.1347,
218
+ "all": 1097.5,
219
219
  "focus": {
220
- "ATTACK": 428.8,
221
- "SET": 255.3,
222
- "RECEIVE": 350.8,
220
+ "ATTACK": 428.7,
221
+ "SET": 324.7,
222
+ "RECEIVE": 350.5,
223
223
  "SERVE": 182.8,
224
- "BLOCK": 347.6,
224
+ "BLOCK": 347.3,
225
225
  "STAMINA": 49
226
226
  }
227
227
  },
228
228
  {
229
229
  "rarity": "LEGENDARY",
230
230
  "role": "LIBERO",
231
- "samples": 114912,
232
- "roleBranchShare": 0.089,
233
- "all": 1098.7,
231
+ "samples": 114544,
232
+ "roleBranchShare": 0.0892,
233
+ "all": 1103.1,
234
234
  "focus": {
235
- "ATTACK": 358.7,
236
- "SET": 260.7,
235
+ "ATTACK": 363.1,
236
+ "SET": 323.3,
237
237
  "RECEIVE": 421.5,
238
- "SERVE": 157.8,
238
+ "SERVE": 157.7,
239
239
  "BLOCK": 381.3,
240
240
  "STAMINA": 50.2
241
241
  }
@@ -243,57 +243,57 @@
243
243
  {
244
244
  "rarity": "MYTHIC",
245
245
  "role": "SETTER",
246
- "samples": 99645,
247
- "roleBranchShare": 0.0824,
248
- "all": 1246.4,
246
+ "samples": 99611,
247
+ "roleBranchShare": 0.0828,
248
+ "all": 1263.9,
249
249
  "focus": {
250
- "ATTACK": 410.6,
251
- "SET": 324.7,
252
- "RECEIVE": 413.3,
253
- "SERVE": 236.4,
254
- "BLOCK": 404,
255
- "STAMINA": 66.7
250
+ "ATTACK": 427.9,
251
+ "SET": 404.8,
252
+ "RECEIVE": 413.4,
253
+ "SERVE": 236.3,
254
+ "BLOCK": 404.2,
255
+ "STAMINA": 66.6
256
256
  }
257
257
  },
258
258
  {
259
259
  "rarity": "MYTHIC",
260
260
  "role": "OUTSIDE_HITTER",
261
- "samples": 15991,
262
- "roleBranchShare": 1,
263
- "all": 962.4,
261
+ "samples": 16110,
262
+ "roleBranchShare": 0.9999,
263
+ "all": 962.8,
264
264
  "focus": {
265
- "ATTACK": 326.1,
266
- "SET": 157,
267
- "RECEIVE": 281.9,
268
- "SERVE": 162.7,
269
- "BLOCK": 282.2,
270
- "STAMINA": 66.9
265
+ "ATTACK": 327,
266
+ "SET": 197.6,
267
+ "RECEIVE": 281.4,
268
+ "SERVE": 163.5,
269
+ "BLOCK": 281,
270
+ "STAMINA": 67
271
271
  }
272
272
  },
273
273
  {
274
274
  "rarity": "MYTHIC",
275
275
  "role": "MIDDLE_BLOCKER",
276
- "samples": 92022,
277
- "roleBranchShare": 0.1535,
278
- "all": 1251.8,
276
+ "samples": 92045,
277
+ "roleBranchShare": 0.152,
278
+ "all": 1257.1,
279
279
  "focus": {
280
- "ATTACK": 393.6,
281
- "SET": 266.9,
282
- "RECEIVE": 421.4,
283
- "SERVE": 210.1,
284
- "BLOCK": 472.7,
285
- "STAMINA": 67.2
280
+ "ATTACK": 398.4,
281
+ "SET": 333.1,
282
+ "RECEIVE": 421.8,
283
+ "SERVE": 210.4,
284
+ "BLOCK": 472.9,
285
+ "STAMINA": 67.1
286
286
  }
287
287
  },
288
288
  {
289
289
  "rarity": "MYTHIC",
290
290
  "role": "OPPOSITE_HITTER",
291
- "samples": 99024,
292
- "roleBranchShare": 0.1126,
293
- "all": 1272.8,
291
+ "samples": 99007,
292
+ "roleBranchShare": 0.1123,
293
+ "all": 1272.7,
294
294
  "focus": {
295
295
  "ATTACK": 485.3,
296
- "SET": 288.2,
296
+ "SET": 367.3,
297
297
  "RECEIVE": 396.8,
298
298
  "SERVE": 234.5,
299
299
  "BLOCK": 389.7,
@@ -303,90 +303,90 @@
303
303
  {
304
304
  "rarity": "MYTHIC",
305
305
  "role": "LIBERO",
306
- "samples": 93318,
307
- "roleBranchShare": 0.1088,
308
- "all": 1267.3,
306
+ "samples": 93227,
307
+ "roleBranchShare": 0.1095,
308
+ "all": 1272.3,
309
309
  "focus": {
310
- "ATTACK": 391.6,
311
- "SET": 290.9,
312
- "RECEIVE": 482.1,
313
- "SERVE": 215.1,
314
- "BLOCK": 426.2,
315
- "STAMINA": 67.5
310
+ "ATTACK": 397,
311
+ "SET": 358.3,
312
+ "RECEIVE": 482,
313
+ "SERVE": 215,
314
+ "BLOCK": 425.9,
315
+ "STAMINA": 67.6
316
316
  }
317
317
  },
318
318
  {
319
319
  "rarity": "SPECIAL",
320
320
  "role": "SETTER",
321
- "samples": 102997,
322
- "roleBranchShare": 0.0804,
323
- "all": 1457.3,
321
+ "samples": 102669,
322
+ "roleBranchShare": 0.0806,
323
+ "all": 1468.8,
324
324
  "focus": {
325
- "ATTACK": 485.2,
326
- "SET": 360.5,
327
- "RECEIVE": 481.4,
325
+ "ATTACK": 496.8,
326
+ "SET": 448.2,
327
+ "RECEIVE": 481.3,
328
328
  "SERVE": 265.7,
329
- "BLOCK": 475.5,
329
+ "BLOCK": 475.4,
330
330
  "STAMINA": 79
331
331
  }
332
332
  },
333
333
  {
334
334
  "rarity": "SPECIAL",
335
335
  "role": "OUTSIDE_HITTER",
336
- "samples": 16546,
337
- "roleBranchShare": 0.9652,
338
- "all": 1100.6,
336
+ "samples": 16703,
337
+ "roleBranchShare": 0.9649,
338
+ "all": 1100.5,
339
339
  "focus": {
340
- "ATTACK": 371.9,
341
- "SET": 183.9,
342
- "RECEIVE": 323.6,
343
- "SERVE": 187.1,
344
- "BLOCK": 323.7,
345
- "STAMINA": 79.6
340
+ "ATTACK": 371.8,
341
+ "SET": 229.6,
342
+ "RECEIVE": 323.3,
343
+ "SERVE": 187,
344
+ "BLOCK": 323.1,
345
+ "STAMINA": 79.5
346
346
  }
347
347
  },
348
348
  {
349
349
  "rarity": "SPECIAL",
350
350
  "role": "MIDDLE_BLOCKER",
351
- "samples": 87715,
352
- "roleBranchShare": 0.1592,
353
- "all": 1440.2,
351
+ "samples": 87563,
352
+ "roleBranchShare": 0.1597,
353
+ "all": 1442.9,
354
354
  "focus": {
355
- "ATTACK": 463.7,
356
- "SET": 309.9,
357
- "RECEIVE": 482.8,
355
+ "ATTACK": 466.6,
356
+ "SET": 386.9,
357
+ "RECEIVE": 482.7,
358
358
  "SERVE": 234.3,
359
- "BLOCK": 522.8,
360
- "STAMINA": 79.5
359
+ "BLOCK": 522.3,
360
+ "STAMINA": 79.7
361
361
  }
362
362
  },
363
363
  {
364
364
  "rarity": "SPECIAL",
365
365
  "role": "OPPOSITE_HITTER",
366
- "samples": 102830,
366
+ "samples": 103053,
367
367
  "roleBranchShare": 0.1096,
368
- "all": 1469.1,
368
+ "all": 1469.5,
369
369
  "focus": {
370
- "ATTACK": 536.1,
371
- "SET": 331.8,
372
- "RECEIVE": 467.1,
370
+ "ATTACK": 536.2,
371
+ "SET": 418.7,
372
+ "RECEIVE": 467.2,
373
373
  "SERVE": 262.7,
374
- "BLOCK": 463.9,
374
+ "BLOCK": 464.2,
375
375
  "STAMINA": 79.2
376
376
  }
377
377
  },
378
378
  {
379
379
  "rarity": "SPECIAL",
380
380
  "role": "LIBERO",
381
- "samples": 89912,
382
- "roleBranchShare": 0.1147,
383
- "all": 1462.7,
381
+ "samples": 90012,
382
+ "roleBranchShare": 0.1131,
383
+ "all": 1466.8,
384
384
  "focus": {
385
- "ATTACK": 464.9,
386
- "SET": 332.7,
387
- "RECEIVE": 531.3,
388
- "SERVE": 240.9,
389
- "BLOCK": 490.4,
385
+ "ATTACK": 468.6,
386
+ "SET": 411.6,
387
+ "RECEIVE": 531.6,
388
+ "SERVE": 241,
389
+ "BLOCK": 490.6,
390
390
  "STAMINA": 80.3
391
391
  }
392
392
  }
@@ -13,19 +13,26 @@ const improvement_1 = require("../service/player/improvement");
13
13
  //
14
14
  // The drift guard is a HASH OF THE PARSED VALUES the floors depend on, not of any source text: hashing source
15
15
  // would fail on a comment edit and force a regeneration that rewrites every number with fresh sampling noise.
16
- // It therefore catches a retuned role weight, stat cap or rarity range, and does NOT catch a pure logic change
17
- // inside player-generator.ts. That case is covered by re-running the generator deliberately.
16
+ // It therefore catches a retuned role weight, stat cap, rarity range or COMPOSITE MULTIPLIER, and does NOT catch
17
+ // a pure logic change inside player-generator.ts. That case is covered by re-running the generator deliberately.
18
+ //
19
+ // The multipliers are in the hash because they DEFINE the focus pools (focusPoolColumns is literally
20
+ // Object.keys(getMultipliers(focus))), so adding a stat to a composite changes both the band divisor and which
21
+ // stats the focus can raise. Observed 2026-07-24: without them, adding `quick` to SET left every test passing on
22
+ // a stale file, because the "below ceiling" assertion reads pool size live and a bigger pool only raises the
23
+ // ceiling the old floor was already under.
18
24
  const RARITIES = [rarity_1.RarityEnum.COMMON, rarity_1.RarityEnum.RARE, rarity_1.RarityEnum.LEGENDARY, rarity_1.RarityEnum.MYTHIC, rarity_1.RarityEnum.SPECIAL];
19
25
  const ROLES = [role_1.RoleEnum.SETTER, role_1.RoleEnum.OUTSIDE_HITTER, role_1.RoleEnum.MIDDLE_BLOCKER, role_1.RoleEnum.OPPOSITE_HITTER, role_1.RoleEnum.LIBERO];
20
26
  const FOCI = [stats_1.StatsEnum.ATTACK, stats_1.StatsEnum.SET, stats_1.StatsEnum.RECEIVE, stats_1.StatsEnum.SERVE, stats_1.StatsEnum.BLOCK, stats_1.StatsEnum.STAMINA];
21
27
  const REGENERATE = 'improvement-floors.json is stale. Run: yarn build && yarn floors';
22
28
  (0, globals_1.describe)('improvement-floors.json', () => {
23
- (0, globals_1.it)('was generated from the current roles, caps and rarity ranges', () => {
29
+ (0, globals_1.it)('was generated from the current roles, caps, rarity ranges and composite multipliers', () => {
24
30
  const canonical = JSON.stringify({
25
31
  roles: index_1.rolesJSON,
26
32
  statCaps: index_1.statCapsJSON,
27
33
  rarityRanges: rarity_1.RarityRanges,
28
- staminaRanges: rarity_1.StaminaRanges
34
+ staminaRanges: rarity_1.StaminaRanges,
35
+ multipliers: FOCI.map(focus => [focus, (0, stats_1.getMultipliers)(focus)])
29
36
  });
30
37
  const expected = (0, crypto_1.createHash)('sha256').update(canonical).digest('hex');
31
38
  (0, globals_1.expect)(`${index_1.improvementFloorsJSON.sourceHash} ${REGENERATE}`).toBe(`${expected} ${REGENERATE}`);
@@ -35,14 +35,22 @@ import { youthMultiplier } from './decline';
35
35
  // Threshold runs from CURVE_BASE at both floors to CURVE_BASE + CURVE_SCALAR at both ceilings; CURVE_EXPONENT
36
36
  // keeps players fast through most of the band and slows them sharply only near the top.
37
37
  //
38
- // BASE and SCALAR were retuned from 180/800 to 130/400 when the second band was added, to hold career-long
39
- // development at its previous level. Pricing every focus-pool upgrade instead of only the ~26% that touched
40
- // the core 6 makes the average player climb their curve far faster, and at the old 180/800 that cut career
41
- // stat gains by ~32% across every rarity (measured: ~253 lifetime ups down to ~176). That would have been a
42
- // large balance change nobody asked for on top of the fix. At 130/400 lifetime ups land at ~247, within a few
43
- // percent of the old curve, so the only behaviour that actually changes is WHICH stats drive the price.
44
- const CURVE_BASE = 130;
45
- const CURVE_SCALAR = 400;
38
+ // BASE and SCALAR are deliberately UNCHANGED from the pre-focus-band curve. They were briefly retuned to
39
+ // 130/400 to hold career-long development flat, but that was the wrong objective: measured against the actual
40
+ // design goals (2026-07-24) a flatter curve is worse on both. Lower scalar means stats are EASIER to max and
41
+ // there is LESS pressure to rotate the training focus, which is the opposite of what the rework is for.
42
+ //
43
+ // base/scalar stats within 5 of cap rotator vs fixed live threshold vs old
44
+ // 180/800 3.6 1.28x 1.00
45
+ // 130/400 4.9 1.19x 0.72
46
+ // 180/275 5.2 1.15x 1.00
47
+ //
48
+ // 180/800 also leaves today's live players paying exactly what they paid before (median ratio 1.00), so the
49
+ // only thing this rework changes is WHICH stats drive the price, not how fast anyone develops on day one.
50
+ // Career totals do fall (~253 lifetime stat points to ~175) and that is intended: maxing a focus is supposed
51
+ // to be hard, and staying on one focus forever is supposed to stall.
52
+ const CURVE_BASE = 180;
53
+ const CURVE_SCALAR = 800;
46
54
  const CURVE_EXPONENT = 2;
47
55
  export const FOCUS_WEIGHT = 0.5;
48
56
  const statCaps = statCapsJSON;