From 09ba8663e6e27e7ab9159dc2f30bdf2faf12741e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 17 Feb 2024 09:57:52 -0600 Subject: [PATCH] feat: stat parity --- .vscode/settings.json | 1 + .../components/Miscellaneous.tsx | 22 ++--- .../[id]/components/Characteristics/index.tsx | 96 ++++++++++--------- src/core/blitzkrieg/degressiveStat.ts | 3 + src/core/blitzkrieg/progressiveStat.ts | 3 + src/stores/tankopedia.ts | 4 +- 6 files changed, 72 insertions(+), 57 deletions(-) create mode 100644 src/core/blitzkrieg/degressiveStat.ts create mode 100644 src/core/blitzkrieg/progressiveStat.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 860908502..bebb6611c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -33,6 +33,7 @@ "deburr", "decalmask", "defence", + "degressive", "diacriticless", "donotremove", "drei", diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/components/Miscellaneous.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/components/Miscellaneous.tsx index 34cc6cbeb..b2d107132 100644 --- a/src/app/tools/tankopedia/[id]/components/Characteristics/components/Miscellaneous.tsx +++ b/src/app/tools/tankopedia/[id]/components/Characteristics/components/Miscellaneous.tsx @@ -14,25 +14,25 @@ export function Miscellaneous() { const cooldownBooster = useTankopediaTemporary( (state) => state.cooldownBooster, ); - const crew = useTankopediaTemporary((state) => state.crew); + const crewMastery = useTankopediaTemporary((state) => state.crewMastery); const crewInput = useRef(null); - const [crewDraft, setCrewDraft] = useState(crew); + const [crewMasteryDraft, setCrewMasteryDraft] = useState(crewMastery); const debouncedApplyDraft = useMemo( () => debounce((value) => { mutateTankopediaTemporary((draft) => { - draft.crew = value; + draft.crewMastery = value; }); }, 500), [], ); useEffect(() => { - setCrewDraft(crew); + setCrewMasteryDraft(crewMastery); if (!crewInput.current) return; - crewInput.current.value = `${Math.round(crew * 100)}`; - }, [crew]); + crewInput.current.value = `${Math.round(crewMastery * 100)}`; + }, [crewMastery]); return ( @@ -91,18 +91,18 @@ export function Miscellaneous() { Crew { const newValue = Number(crewInput.current!.value) / 100; if (isNaN(newValue)) { - crewInput.current!.value = `${Math.round(crew * 100)}`; + crewInput.current!.value = `${Math.round(crewMastery * 100)}`; return; } mutateTankopediaTemporary((draft) => { - draft.crew = clamp(newValue / 100, 0.5, 1); + draft.crewMastery = clamp(newValue / 100, 0.5, 1); }); }} onKeyUp={(event) => { @@ -117,10 +117,10 @@ export function Miscellaneous() { { - setCrewDraft(value / 100); + setCrewMasteryDraft(value / 100); debouncedApplyDraft(value / 100); }} /> diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx index ab378fed1..a1cf8a3f6 100644 --- a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx @@ -6,8 +6,10 @@ import { lerp } from 'three/src/math/MathUtils'; import { isExplosive } from '../../../../../../core/blitz/isExplosive'; import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration'; import { coefficient } from '../../../../../../core/blitzkrieg/coefficient'; +import { degressiveStat } from '../../../../../../core/blitzkrieg/degressiveStat'; import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions'; import { normalizeBoundingBox } from '../../../../../../core/blitzkrieg/normalizeBoundingBox'; +import { progressiveStat } from '../../../../../../core/blitzkrieg/progressiveStat'; import { resolveDpm } from '../../../../../../core/blitzkrieg/resolveDpm'; import { sum } from '../../../../../../core/blitzkrieg/sum'; import { @@ -29,7 +31,15 @@ export function Characteristics() { const { tank, turret, gun, engine, track, shell } = useDuel( (state) => state.protagonist!, ); - const crew = useTankopediaTemporary((state) => state.crew); + const provisions = useProvisions(); + const crewMastery = useTankopediaTemporary((state) => state.crewMastery); + const provisionCrewBonus = provisions.reduce( + (total, provision) => + provision.crew ? total + provision.crew / 100 : total, + 0, + ); + const commanderMastery = crewMastery + provisionCrewBonus; + const crewMemberMastery = commanderMastery * 1.1; const stockEngine = tank.engines[0]; const stockTrack = tank.tracks[0]; const stockTurret = tank.turrets[0]; @@ -53,7 +63,6 @@ export function Characteristics() { stockTurret.weight + stockGun.weight; const [penetrationDistance, setPenetrationDistance] = useState(250); - const provisions = useProvisions(); const camouflage = useTankopediaTemporary((state) => state.camouflage); const hasRammer = useEquipment(100); const hasCalibratedShells = useEquipment(103); @@ -89,10 +98,10 @@ export function Characteristics() { [hasEnhancedSandbagArmor, 0.06], [hasImprovedAssembly, 0.06], ); - const reloadCoefficient = coefficient( - [hasRammer, -0.07], - [hasAdrenaline && gun.type === 'regular', -0.2], - ); + const reloadCoefficient = + (coefficient([hasRammer, -0.07]) * + coefficient([true, degressiveStat(crewMemberMastery)])) / + coefficient([hasAdrenaline && gun.type === 'regular', 0.2]); const penetrationCoefficient = coefficient([ hasCalibratedShells, isExplosive(shell.type) ? 0.1 : 0.05, @@ -110,15 +119,18 @@ export function Characteristics() { hasSupercharger, -0.5, ]); - const aimTimeCoefficient = coefficient( - [hasEnhancedGunLayingDrive, -0.1], - [hasReticleCalibration, -0.4], - [hasVerticalStabilizer, -0.15], - ); - const dispersionCoefficient = coefficient( - [hasRefinedGun, -0.1], - [hasReticleCalibration, -0.4], - ); + const aimTimeCoefficient = + coefficient( + [hasEnhancedGunLayingDrive, -0.1], + [hasReticleCalibration, -0.4], + ) * coefficient([true, degressiveStat(crewMemberMastery)]); + const dispersionStillCoefficient = + coefficient([hasRefinedGun, -0.1], [hasReticleCalibration, -0.4]) * + coefficient([true, degressiveStat(crewMemberMastery)]); + const dispersionMovingCoefficient = coefficient([ + hasVerticalStabilizer, + -0.15, + ]); const enginePowerCoefficient = coefficient( [ hasEngineAccelerator && (tank.type === 'light' || tank.type === 'medium'), @@ -136,19 +148,20 @@ export function Characteristics() { [hasGearOil, 0.03], [hasImprovedGearOil, 0.06], ); - const turretTraverseCoefficient = coefficient( - [hasStandardFuel, 0.03], - [hasImprovedFuel, 0.1], - ); - const hullTraverseCoefficient = coefficient( - [hasImprovedControl, 0.1], - [hasImprovedEnginePowerBoost, 0.05], - ); + const turretTraverseCoefficient = + coefficient([hasStandardFuel, 0.03], [hasImprovedFuel, 0.1]) * + coefficient([true, progressiveStat(crewMemberMastery)]); + const hullTraverseCoefficient = + coefficient( + [hasImprovedControl, 0.1], + [hasImprovedEnginePowerBoost, 0.05], + ) * coefficient([true, progressiveStat(crewMemberMastery)]); const resistanceCoefficient = coefficient([hasImprovedSuspension, -0.25]); - const viewRangeCoefficient = coefficient([ - hasImprovedOptics, - tank.type === 'tankDestroyer' ? 0.05 : tank.type === 'heavy' ? 0.07 : 0.1, - ]); + const viewRangeCoefficient = + coefficient([ + hasImprovedOptics, + tank.type === 'tankDestroyer' ? 0.05 : tank.type === 'heavy' ? 0.07 : 0.1, + ]) * coefficient([true, progressiveStat(commanderMastery)]); const fireChanceCoefficient = coefficient([hasProtectiveKit, -0.2]); const speedForwardsSum = sum( @@ -199,11 +212,6 @@ export function Characteristics() { ], ); - const provisionCrewBonus = provisions.reduce( - (total, provision) => - provision.crew ? total + provision.crew / 100 : total, - 0, - ); const resolvedEnginePower = engine.power * enginePowerCoefficient; const dpm = resolveDpm( gun, @@ -363,7 +371,7 @@ export function Characteristics() { {shell.damage.module * damageCoefficient} - + {shell.speed * shellVelocityCoefficient} - {gun.dispersion.base * dispersionCoefficient} + {gun.dispersion.base * dispersionStillCoefficient} - {track.dispersion.move * dispersionCoefficient} + {track.dispersion.move * dispersionMovingCoefficient} - {track.dispersion.traverse * dispersionCoefficient} + {track.dispersion.traverse * dispersionMovingCoefficient} - {gun.dispersion.traverse * dispersionCoefficient} + {gun.dispersion.traverse * dispersionMovingCoefficient} - {gun.dispersion.shot * dispersionCoefficient} + {gun.dispersion.shot * dispersionMovingCoefficient} - {gun.dispersion.damaged * dispersionCoefficient} + {gun.dispersion.damaged * dispersionMovingCoefficient} @@ -549,7 +557,7 @@ export function Characteristics() { {Math.round(engine.fireChance * fireChanceCoefficient * 100)} - + {turret.viewRange * viewRangeCoefficient} @@ -590,9 +598,9 @@ export function Characteristics() { unit="%" decimals={0} > - {(crew + provisionCrewBonus) * - (member.type === 'commander' ? 1 : 1.1) * - 100} + {(member.type === 'commander' + ? commanderMastery + : crewMemberMastery) * 100} {member.substitute && ( ()( [0, 0, 0], [0, 0, 0], ], - crew: 0.75, + crewMastery: 0.75, mode: 'model', consumables: [], provisions: [],