2024-02-24 01:38:00 -08:00
|
|
|
/*
|
2024-02-24 18:00:53 -08:00
|
|
|
Define various sequences to play out in this file.
|
|
|
|
For example, we can define an initialization sequence that
|
2024-02-24 01:38:00 -08:00
|
|
|
plays out some series of notifications, and call it whenever we need it,
|
2024-02-24 18:00:53 -08:00
|
|
|
or a sequence to change the screen color and play some audio queues
|
|
|
|
after a crash
|
|
|
|
|
|
|
|
These sequences should be self contained and not rely on any external state
|
|
|
|
so that they can be invoked from anywhere. In the event that you need some
|
|
|
|
persistent variable (eg. a variable that saves whether or not a sequence has
|
|
|
|
already been played or a counter variable), add an entry to and use sequenceStore
|
2024-02-24 18:56:49 -08:00
|
|
|
|
|
|
|
Sequences should be either event-driven or periodic. In the case of periodic
|
|
|
|
sequences, invoke them in the periodicSequence function
|
2024-02-24 01:38:00 -08:00
|
|
|
*/
|
|
|
|
|
2024-02-24 20:21:36 -08:00
|
|
|
import { Notifications } from "../Notifications/notifications";
|
|
|
|
import { sequenceStore } from "../stores/sequenceStore";
|
|
|
|
import { settingsStore } from "../stores/settingsStore";
|
|
|
|
import { get } from "svelte/store";
|
|
|
|
import getVoicePath from "../utils/getVoicePath";
|
|
|
|
import { tick } from "svelte";
|
2024-02-24 01:38:00 -08:00
|
|
|
|
2024-02-24 17:40:47 -08:00
|
|
|
// await a "tick" (a svelte update frame) at the start of every sequence so that
|
|
|
|
// state is synced and no weird side effects occur
|
|
|
|
|
|
|
|
export const initializationSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
|
|
|
Notifications.info("Jankboard initialized!", {
|
2024-02-24 01:38:00 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("jankboard-initialized", "en"),
|
|
|
|
});
|
2024-02-24 01:38:00 -08:00
|
|
|
setTimeout(() => {
|
2024-02-24 20:21:36 -08:00
|
|
|
if (get(settingsStore).goWoke) return;
|
|
|
|
Notifications.success("LittenOS is online", {
|
2024-02-24 01:38:00 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("littenos-is-online", "en"),
|
|
|
|
});
|
2024-02-24 01:38:00 -08:00
|
|
|
setTimeout(() => {
|
2024-02-24 20:21:36 -08:00
|
|
|
Notifications.warn("Breaching Monte Vista codebase", {
|
2024-02-24 01:38:00 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("breaching-monte-vista", "en"),
|
|
|
|
});
|
2024-02-24 17:40:47 -08:00
|
|
|
setTimeout(() => {
|
2024-02-24 20:21:36 -08:00
|
|
|
Notifications.playAudio(
|
|
|
|
getVoicePath("hello-virtual-assistant", "en"),
|
|
|
|
() => {
|
|
|
|
sequenceStore.update("initializationComplete", true);
|
|
|
|
periodicSequence();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}, 3000);
|
|
|
|
}, 3000);
|
|
|
|
}, 3000);
|
|
|
|
};
|
|
|
|
|
|
|
|
let counter = 1;
|
2024-02-24 18:56:49 -08:00
|
|
|
/**
|
|
|
|
* Special sequence that plays invokes itself periodically, started automatically
|
|
|
|
* at the end of the initializationSequence
|
|
|
|
*
|
|
|
|
* @param seconds - the interval in seconds
|
|
|
|
* @param callback - the function to call
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
const periodicSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
2024-02-24 18:56:49 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns either true or false based on the provided probability
|
|
|
|
*
|
|
|
|
* @param probability - The probability value between 0 and 1
|
|
|
|
* @return The result of the probability test
|
|
|
|
*/
|
|
|
|
const chance = (probability: number) => {
|
|
|
|
if (probability < 0 || probability > 1) {
|
2024-02-24 20:21:36 -08:00
|
|
|
throw new Error("Probability must be between 0 and 1");
|
2024-02-24 18:56:49 -08:00
|
|
|
}
|
|
|
|
|
2024-02-24 20:21:36 -08:00
|
|
|
return Math.random() < probability;
|
|
|
|
};
|
2024-02-24 18:56:49 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Calls a callback function at regular intervals.
|
|
|
|
*
|
|
|
|
* @param seconds - the interval in seconds
|
|
|
|
* @param callback - the function to call
|
|
|
|
*/
|
|
|
|
const every = (seconds: number, callback: () => void) => {
|
2024-02-24 20:21:36 -08:00
|
|
|
if (counter % seconds === 0) callback();
|
|
|
|
};
|
2024-02-24 18:56:49 -08:00
|
|
|
|
|
|
|
// add your periodic sequences here
|
2024-02-24 20:21:36 -08:00
|
|
|
every(15, () => {
|
|
|
|
if (chance(0.2)) breaching1323Sequence();
|
|
|
|
else if (chance(0.2)) breaching254Sequence();
|
|
|
|
else if (chance(0.05)) bullyingRohanSequence();
|
|
|
|
else if (chance(0.1)) bypassCoprocessorRestrictionsSequence();
|
|
|
|
});
|
2024-02-24 18:56:49 -08:00
|
|
|
|
|
|
|
// Dont touch
|
2024-02-24 20:21:36 -08:00
|
|
|
counter++;
|
|
|
|
setTimeout(periodicSequence, 1000);
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
export const criticalFailureIminentSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
|
|
|
Notifications.error("Critical robot failure imminent", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("critical-robot-failure", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
|
|
|
export const collisionDetectedSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
|
|
|
Notifications.error("Collision detected", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("collision-detected", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
|
|
|
export const collisionImminentSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
|
|
|
Notifications.error("Collision imminent", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("collision-imminent", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
|
|
|
export const cruiseControlEngagedSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
if (get(settingsStore).disableAnnoyances) return;
|
|
|
|
await tick();
|
|
|
|
Notifications.success("Cruise control engaged", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("cruise-control-engaged", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
|
|
|
export const retardSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
if (get(settingsStore).goWoke) return;
|
|
|
|
await tick();
|
|
|
|
Notifications.warn("Retard", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("retard", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 19:03:32 -08:00
|
|
|
const breaching254Sequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
if (get(settingsStore).disableAnnoyances) return;
|
|
|
|
await tick();
|
|
|
|
Notifications.warn("Breaching 254 mainframe", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("breaching-254-mainframe", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 19:03:32 -08:00
|
|
|
const breaching1323Sequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
if (get(settingsStore).disableAnnoyances) return;
|
|
|
|
await tick();
|
|
|
|
Notifications.warn("Breaching 1323 mainframe", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("breaching-1323-mainframe", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 19:03:32 -08:00
|
|
|
const bullyingRohanSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
if (get(settingsStore).disableAnnoyances) return;
|
|
|
|
await tick();
|
|
|
|
Notifications.info("Bullying Rohan", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("bullying-rohan", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
|
|
|
export const userErrorDetectedSequence = async () => {
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
|
|
|
Notifications.error("User error detected", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("user-error-detected", "en"),
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
|
|
|
export const infotainmentBootupSequence = async () => {
|
|
|
|
if (
|
|
|
|
get(sequenceStore).infotainmentStartedFirstTime ||
|
|
|
|
get(settingsStore).disableAnnoyances
|
|
|
|
)
|
2024-02-24 20:21:36 -08:00
|
|
|
return;
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 20:21:36 -08:00
|
|
|
const sequence = () => {
|
|
|
|
Notifications.info("Infotainment system buffering", {
|
2024-02-24 17:40:47 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("infotainment-system-buffering", "en"),
|
|
|
|
});
|
|
|
|
setTimeout(() => {
|
|
|
|
Notifications.success("Infotainment system online", {
|
|
|
|
withAudio: true,
|
|
|
|
src: getVoicePath("infotainment-system-online", "en"),
|
|
|
|
onComplete: () => {
|
|
|
|
sequenceStore.update("infotainmentStartedFirstTime", true);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}, 3000);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!get(sequenceStore).initializationComplete) {
|
|
|
|
const unsubscribe = sequenceStore.subscribe((data) => {
|
|
|
|
if (data.initializationComplete) {
|
|
|
|
sequence();
|
|
|
|
unsubscribe();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
sequence();
|
|
|
|
}
|
|
|
|
};
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 19:36:19 -08:00
|
|
|
/**
|
|
|
|
* Waits for the infotainment system to boot up before executing the given sequence.
|
|
|
|
* Designed to be used by apps who want to play a bootup sequence but not overlap with the default one.
|
|
|
|
* If it's already booted, the sequence will be executed immediately.
|
|
|
|
*
|
|
|
|
* @param sequence - The sequence to execute after infotainment bootup, or immediately it already booted.
|
|
|
|
*/
|
2024-02-24 20:21:36 -08:00
|
|
|
const waitForInfotainmentBootup = (sequence: () => void) => {
|
2024-02-24 19:36:19 -08:00
|
|
|
if (!get(sequenceStore).infotainmentStartedFirstTime) {
|
2024-02-24 20:21:36 -08:00
|
|
|
const unsubscribe = sequenceStore.subscribe((data) => {
|
|
|
|
if (data.infotainmentStartedFirstTime) {
|
|
|
|
sequence();
|
|
|
|
unsubscribe();
|
|
|
|
}
|
|
|
|
});
|
2024-02-24 19:36:19 -08:00
|
|
|
} else {
|
2024-02-24 20:21:36 -08:00
|
|
|
sequence();
|
2024-02-24 19:36:19 -08:00
|
|
|
}
|
2024-02-24 20:21:36 -08:00
|
|
|
};
|
2024-02-24 19:36:19 -08:00
|
|
|
|
2024-02-24 17:40:47 -08:00
|
|
|
export const musicPlayerBootupSequence = async () => {
|
|
|
|
if (
|
|
|
|
get(sequenceStore).musicStartedFirstTime ||
|
|
|
|
get(settingsStore).disableAnnoyances
|
|
|
|
)
|
2024-02-24 20:21:36 -08:00
|
|
|
return;
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 20:21:36 -08:00
|
|
|
sequenceStore.update("musicStartedFirstTime", true);
|
2024-02-24 17:40:47 -08:00
|
|
|
|
2024-02-24 19:36:19 -08:00
|
|
|
waitForInfotainmentBootup(() => {
|
2024-02-24 20:21:36 -08:00
|
|
|
Notifications.info("Downloading copyrighted music...", {
|
2024-02-24 19:36:19 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("downloading-copyrighted-music", "en"),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2024-02-24 19:36:19 -08:00
|
|
|
|
|
|
|
export const gbaEmulatorBootupSequence = async () => {
|
|
|
|
if (
|
|
|
|
get(sequenceStore).gbaEmulatorStartedFirstTime ||
|
|
|
|
get(settingsStore).disableAnnoyances
|
|
|
|
)
|
2024-02-24 20:21:36 -08:00
|
|
|
return;
|
2024-02-24 19:36:19 -08:00
|
|
|
|
2024-02-24 20:21:36 -08:00
|
|
|
await tick();
|
|
|
|
sequenceStore.update("gbaEmulatorStartedFirstTime", true);
|
2024-02-24 19:36:19 -08:00
|
|
|
|
|
|
|
waitForInfotainmentBootup(() => {
|
2024-02-24 20:21:36 -08:00
|
|
|
Notifications.info("Loading pirated Nintendo ROMs", {
|
2024-02-24 19:36:19 -08:00
|
|
|
withAudio: true,
|
2024-02-24 20:21:36 -08:00
|
|
|
src: getVoicePath("loading-pirated-nintendo", "en"),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
export const doomBootupSequence = async () => {
|
|
|
|
if (
|
|
|
|
get(sequenceStore).doomStartedFirstTime ||
|
|
|
|
get(settingsStore).disableAnnoyances
|
|
|
|
)
|
|
|
|
return;
|
|
|
|
|
|
|
|
await tick();
|
|
|
|
sequenceStore.update("doomStartedFirstTime", true);
|
|
|
|
|
|
|
|
waitForInfotainmentBootup(() => {
|
|
|
|
Notifications.success("Doom Engaged", {
|
|
|
|
withAudio: true,
|
|
|
|
src: getVoicePath("doom-engaged", "en"),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const bypassCoprocessorRestrictionsSequence = async () => {
|
|
|
|
if (get(settingsStore).disableAnnoyances) return;
|
|
|
|
await tick();
|
|
|
|
Notifications.warn("Bypassing coprocessor restrictions", {
|
|
|
|
withAudio: true,
|
|
|
|
src: getVoicePath("bypassing-coprocessor-restrictions", "en"),
|
|
|
|
});
|
|
|
|
};
|