Files
healer-man/src/avatar/attackPresentation.ts
T
2026-08-14 15:56:39 -04:00

38 lines
1.3 KiB
TypeScript

export const ATTACK_PRESENTATION_DURATION_SECONDS = 0.52;
const WINDUP_END_SECONDS = 0.12;
const STRIKE_END_SECONDS = 0.25;
function smoothstep(progress: number): number {
const clamped = Math.max(0, Math.min(1, progress));
return clamped * clamped * (3 - 2 * clamped);
}
/**
* A one-shot presentation curve driven by an actual combat hit revision.
* Negative values are the windup, positive values are the strike, and zero is
* the locomotion pose. Keeping this pure lets the render rig layer the motion
* over Stand/Run without putting animation timing into combat simulation.
*/
export function attackSwingAt(elapsedSeconds: number): number {
if (!Number.isFinite(elapsedSeconds) || elapsedSeconds <= 0) return 0;
if (elapsedSeconds >= ATTACK_PRESENTATION_DURATION_SECONDS) return 0;
if (elapsedSeconds < WINDUP_END_SECONDS) {
return -0.58 * smoothstep(elapsedSeconds / WINDUP_END_SECONDS);
}
if (elapsedSeconds < STRIKE_END_SECONDS) {
const progress = smoothstep(
(elapsedSeconds - WINDUP_END_SECONDS) / (STRIKE_END_SECONDS - WINDUP_END_SECONDS),
);
return -0.58 + (1.05 + 0.58) * progress;
}
const progress = smoothstep(
(elapsedSeconds - STRIKE_END_SECONDS)
/ (ATTACK_PRESENTATION_DURATION_SECONDS - STRIKE_END_SECONDS),
);
return 1.05 * (1 - progress);
}