zenno: update full charge info with new knowledge
ci/woodpecker/push/horsebot Pipeline was successful
ci/woodpecker/push/zenno Pipeline was successful

This commit is contained in:
2026-09-21 09:48:56 -04:00
parent 0ffd2c099a
commit 1cf3af5f79
3 changed files with 21 additions and 16 deletions
+3 -2
View File
@@ -771,16 +771,17 @@ export function conservePowerAccel(
distanceType: Distance, distanceType: Distance,
style: RunningStyle, style: RunningStyle,
rawPower: number, rawPower: number,
basePower: number,
powerSkillBonus?: number, powerSkillBonus?: number,
spotStruggled?: boolean, spotStruggled?: boolean,
rushed?: boolean, rushed?: boolean,
): number { ): number {
const power = rawPower + (powerSkillBonus ?? 0); const power = basePower + 0.5 * Math.max(rawPower - 1200, 0) + (powerSkillBonus ?? 0);
if (power <= 1200) { if (power <= 1200) {
return 0; return 0;
} }
const sdc = conserveStratDistCoef[style][distanceType]; const sdc = conserveStratDistCoef[style][distanceType];
const activity = rushed ? 0.8 : spotStruggled ? 0.98 : 1; const activity = (rushed ? 0.8 : 1) * (spotStruggled ? 0.98 : 1);
return Math.sqrt((power - 1200) * 130) * 0.001 * sdc * activity; return Math.sqrt((power - 1200) * 130) * 0.001 * sdc * activity;
} }
+6 -7
View File
@@ -224,10 +224,10 @@
}, },
]); ]);
const fcSeries: ComputedSeries[] = $derived([ const fcSeries: ComputedSeries[] = $derived([
{ label: 'Front Runner', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.FrontRunner, x) }, { label: 'Front Runner', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.FrontRunner, raw, x) },
{ label: 'Pace Chaser', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.PaceChaser, x) }, { label: 'Pace Chaser', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.PaceChaser, raw, x) },
{ label: 'Late Surger', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.LateSurger, x) }, { label: 'Late Surger', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.LateSurger, raw, x) },
{ label: 'End Closer', y: (x) => conservePowerAccel(distance(raceLen), RunningStyle.EndCloser, x) }, { label: 'End Closer', y: (x, raw) => conservePowerAccel(distance(raceLen), RunningStyle.EndCloser, raw, x) },
]); ]);
</script> </script>
@@ -528,9 +528,8 @@
</div> </div>
</div> </div>
<p> <p>
The exact mechanics of conserving power are unclear at this time. What has been confirmed is that rushed and <a Rushed and <a href="#spot-struggle">spot struggle</a> reduce both the duration and effectiveness of full charge, potentially to
href="#spot-struggle">spot struggle</a zero. In practice, this appears to be a concern primarily on sprints, which already have a -55% penalty to full charge duration.
> both reduce the chance for it to fire.
</p> </p>
<Sec h={3} id="lane-combo">Lane Combo</Sec> <Sec h={3} id="lane-combo">Lane Combo</Sec>
+12 -7
View File
@@ -58,10 +58,10 @@
]); ]);
const laneChange: ComputedSeries[] = [{ label: 'Lane Change Target Speed', y: (x) => race.laneChangeSpeed(x) }]; const laneChange: ComputedSeries[] = [{ label: 'Lane Change Target Speed', y: (x) => race.laneChangeSpeed(x) }];
const conservePower: Array<ComputedSeries | null> = $derived([ const conservePower: Array<ComputedSeries | null> = $derived([
{ label: 'Conserved Power', y: (_raw, x) => race.conservePowerAccel(distanceType, style, x, 0, false, false) }, { label: 'Conserved Power', y: (x, raw) => race.conservePowerAccel(distanceType, style, raw, x, 0, false, false) },
{ label: 'Rushed', y: (_raw, x) => race.conservePowerAccel(distanceType, style, x, 0, false, true) }, { label: 'Rushed', y: (x, raw) => race.conservePowerAccel(distanceType, style, raw, x, 0, false, true) },
styleIsFront styleIsFront
? { label: 'Spot Struggled', y: (_raw, x) => race.conservePowerAccel(distanceType, style, x, 0, true, false) } ? { label: 'Spot Struggled', y: (x, raw) => race.conservePowerAccel(distanceType, style, raw, x, 0, true, false) }
: null, : null,
]); ]);
const gutsSpurt: Array<ComputedSeries | null> = $derived([ const gutsSpurt: Array<ComputedSeries | null> = $derived([
@@ -329,11 +329,16 @@
Bonus acceleration at spurt start from the Charge Up/Fully Charged mechanic. Scales with base power plus passive skills, so Bonus acceleration at spurt start from the Charge Up/Fully Charged mechanic. Scales with base power plus passive skills, so
modifiers for ground conditions and career mode do not apply. modifiers for ground conditions and career mode do not apply.
</p> </p>
<p>
This mechanic does not appear to be well understood, in particular how long the acceleration bonus lasts and how the rushed
and spot struggle multipliers apply.
</p>
{@render statChart(race.Stat.Power, conservePower, 'Acceleration (m/s²)', [0, 0.35], { len: true, style: true })} {@render statChart(race.Stat.Power, conservePower, 'Acceleration (m/s²)', [0, 0.35], { len: true, style: true })}
<p>
The duration of Fully Charged does not depend directly on stats, but rather on a hidden <i>conserved power</i> value which
increases per horse throughout the race. Conserved power does not increase while <a href="#spot-struggle">spot struggling</a>,
so for front runners, the duration may scale negatively with guts. It also does not increase while running in any
<a href="#poskeep">position keep mode</a>
other than pace-down, so its duration may have a very slight negative correlation with wit.
<a href="#rushed">Rushed</a> additionally prevents accumulating conserved power, so full charge duration may scale positively with
wit amortized across races. Otherwise, power conservation rate depends on running style.
</p>
<Sec h={2} id="guts">Guts</Sec> <Sec h={2} id="guts">Guts</Sec>