forked from phenom/healer-man
158 lines
4.4 KiB
TypeScript
158 lines
4.4 KiB
TypeScript
import { playMasterAudioCue } from "./combatAudio";
|
|
|
|
export type ManastormPortalCueSignal = "portal-coming-up" | "portal-ready";
|
|
|
|
export interface ManastormPortalAudioCue {
|
|
readonly id: string;
|
|
readonly signal: ManastormPortalCueSignal;
|
|
readonly variant: "generic" | "single";
|
|
readonly alternate: boolean;
|
|
readonly fileName: string;
|
|
readonly url: string;
|
|
}
|
|
|
|
export interface ManastormClientCueRequest {
|
|
readonly cueId: ManastormPortalCueId;
|
|
readonly revision: number;
|
|
}
|
|
|
|
export interface ManastormAudioHandle {
|
|
currentTime: number;
|
|
preload: string;
|
|
volume: number;
|
|
pause: () => void;
|
|
play: () => Promise<void> | void;
|
|
}
|
|
|
|
export type ManastormAudioFactory = (url: string) => ManastormAudioHandle;
|
|
|
|
export const MANASTORM_PORTAL_AUDIO_ROOT =
|
|
"/assets/game/combat-effects/audio/manastorm";
|
|
|
|
function packagedPortalAudioUrl(fileName: string): string {
|
|
return `${MANASTORM_PORTAL_AUDIO_ROOT}/${fileName}`;
|
|
}
|
|
|
|
export const MANASTORM_PORTAL_AUDIO_CUES = [
|
|
{
|
|
id: "generic-portal-coming-up",
|
|
signal: "portal-coming-up",
|
|
variant: "generic",
|
|
alternate: false,
|
|
fileName: "Manastorm_BossKill_GenericPortalComingUp.wav",
|
|
url: packagedPortalAudioUrl("Manastorm_BossKill_GenericPortalComingUp.wav"),
|
|
},
|
|
{
|
|
id: "single-portal-coming-up",
|
|
signal: "portal-coming-up",
|
|
variant: "single",
|
|
alternate: false,
|
|
fileName: "Manastorm_BossKill_1PortalComingUp.wav",
|
|
url: packagedPortalAudioUrl("Manastorm_BossKill_1PortalComingUp.wav"),
|
|
},
|
|
{
|
|
id: "single-portal-coming-up-alt",
|
|
signal: "portal-coming-up",
|
|
variant: "single",
|
|
alternate: true,
|
|
fileName: "Manastorm_BossKill_1PortalComingUp_2.wav",
|
|
url: packagedPortalAudioUrl("Manastorm_BossKill_1PortalComingUp_2.wav"),
|
|
},
|
|
{
|
|
id: "generic-portals-ready",
|
|
signal: "portal-ready",
|
|
variant: "generic",
|
|
alternate: false,
|
|
fileName: "Manastorm_BossKill_GenericPortalsReady.wav",
|
|
url: packagedPortalAudioUrl("Manastorm_BossKill_GenericPortalsReady.wav"),
|
|
},
|
|
{
|
|
id: "generic-portals-ready-alt",
|
|
signal: "portal-ready",
|
|
variant: "generic",
|
|
alternate: true,
|
|
fileName: "Manastorm_BossKill_GenericPortalsReady_2.wav",
|
|
url: packagedPortalAudioUrl("Manastorm_BossKill_GenericPortalsReady_2.wav"),
|
|
},
|
|
] as const satisfies readonly ManastormPortalAudioCue[];
|
|
|
|
export type ManastormPortalCueId = typeof MANASTORM_PORTAL_AUDIO_CUES[number]["id"];
|
|
|
|
export const MANASTORM_DEFAULT_PORTAL_READY_CUE_ID: ManastormPortalCueId =
|
|
"generic-portals-ready";
|
|
|
|
const cueById = new Map<ManastormPortalCueId, ManastormPortalAudioCue>(
|
|
MANASTORM_PORTAL_AUDIO_CUES.map((cue) => [cue.id, cue]),
|
|
);
|
|
|
|
let activeAudio: ManastormAudioHandle | null = null;
|
|
|
|
export function manastormPortalAudioCue(
|
|
cueId: ManastormPortalCueId,
|
|
): ManastormPortalAudioCue {
|
|
const cue = cueById.get(cueId);
|
|
if (!cue) throw new Error(`Unknown Manastorm client cue ${cueId}.`);
|
|
return cue;
|
|
}
|
|
|
|
export function isManastormPortalCueId(value: string): value is ManastormPortalCueId {
|
|
return cueById.has(value as ManastormPortalCueId);
|
|
}
|
|
|
|
export function manastormCueForStatusTransition(
|
|
previousStatus: string,
|
|
nextStatus: string,
|
|
): ManastormPortalCueId | null {
|
|
return previousStatus !== "portal-ready" && nextStatus === "portal-ready"
|
|
? MANASTORM_DEFAULT_PORTAL_READY_CUE_ID
|
|
: null;
|
|
}
|
|
|
|
function browserAudioFactory(url: string): ManastormAudioHandle {
|
|
let stopPlayback: (() => void) | null = null;
|
|
let stopped = false;
|
|
const handle: ManastormAudioHandle = {
|
|
currentTime: 0,
|
|
preload: "auto",
|
|
volume: 1,
|
|
pause: () => {
|
|
stopped = true;
|
|
stopPlayback?.();
|
|
stopPlayback = null;
|
|
},
|
|
play: async () => {
|
|
stopped = false;
|
|
const stop = await playMasterAudioCue(url, handle.volume);
|
|
if (!stop) throw new Error("Web Audio is unavailable.");
|
|
if (stopped) stop();
|
|
else stopPlayback = stop;
|
|
},
|
|
};
|
|
return handle;
|
|
}
|
|
|
|
export async function playManastormClientCue(
|
|
cueId: ManastormPortalCueId,
|
|
audioFactory: ManastormAudioFactory = browserAudioFactory,
|
|
): Promise<boolean> {
|
|
const cue = manastormPortalAudioCue(cueId);
|
|
try {
|
|
activeAudio?.pause();
|
|
const audio = audioFactory(cue.url);
|
|
audio.preload = "auto";
|
|
audio.volume = 0.72;
|
|
audio.currentTime = 0;
|
|
activeAudio = audio;
|
|
await audio.play();
|
|
return true;
|
|
} catch {
|
|
activeAudio = null;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function stopManastormClientCue(): void {
|
|
activeAudio?.pause();
|
|
activeAudio = null;
|
|
}
|