fledgling/src/wishes.ts

284 lines
6.5 KiB
TypeScript

import { Skill, Wish, WishData } from "./datatypes.ts";
import { shuffle } from "./utils.ts";
import {
bat0,
bat1,
bat2,
bat3,
charm0,
charm1,
charm2,
charm3,
getSkills,
lore0,
lore1,
lore2,
party0,
party1,
party2,
party3,
sorry0,
sorry1,
sorry2,
stare0,
stare1,
stare2,
stare3,
stealth0,
stealth1,
stealth2,
stealth3,
} from "./skills.ts";
import { compile, VNSceneBasisPart } from "./vnscene.ts";
import { getPlayerProgress } from "./playerprogress.ts";
class WishesTable {
#wishes: WishData[];
constructor() {
this.#wishes = [];
}
add(data: WishData): Wish {
let id = this.#wishes.length;
this.#wishes.push(data);
return { id };
}
get(wish: Wish): WishData {
return this.#wishes[wish.id];
}
getAllRandomWishes(): Wish[] {
let wishes: Wish[] = [];
for (let i = 0; i < this.#wishes.length; i++) {
if (this.#wishes[i].isRandomlyAvailable) {
wishes.push({ id: i });
}
}
return wishes;
}
}
let table = new WishesTable();
export function getWishes(): WishesTable {
return table;
}
const whisper: VNSceneBasisPart = {
type: "message",
text: "...",
sfx: "whisper.mp3",
};
export const celebritySocialite = table.add({
profile: {
name: "Celebrity Socialite",
note: "+Charm -Lore",
domicile: "Party Mansion",
reignSentence: "A lot of people know who you are and like you.",
failureName: "Z-List Bloodstarver",
failureDomicile: "Obscure Soap Ad",
failureReignSentence: "Nobody really knows who you are.",
failureSuccessorVerb: "Apologize For Your Failure",
},
isRandomlyAvailable: true,
isCompulsory: false,
bannedSkills: () => [lore0],
discouragedSkills: () => [stealth0, stealth1, stealth2, stealth3],
encouragedSkills: () => [party0, party1, party2, party3],
requiredSkills: () => [charm0, charm1, charm2],
prologue: compile([
whisper,
"Master?",
whisper,
"I see.",
"You. I -- should I buy a guitar or something?",
whisper,
"My looks and my party skills...",
]),
onFailure: compile([
whisper,
"You're displeased...",
whisper,
"I'm not popular enough?",
"I see.",
]),
onVictory: compile([
whisper,
"I did as you commanded.",
"You're pleased?",
"... I'm free.",
]),
});
export const nightswornAlchemist = table.add({
profile: {
name: "Nightsworn Alchemist",
note: "+Lore -Party",
domicile: "Alchemical Lab",
reignSentence:
"You understand the fundamental connection between wine and blood.",
failureName: "Failure of Science",
failureDomicile: "Remedial College",
failureReignSentence: "You don't understand much of anything.",
failureSuccessorVerb: "Apologize For Your Failure",
},
isRandomlyAvailable: true,
isCompulsory: false,
bannedSkills: () => [party0],
discouragedSkills: () => [charm0, charm1, charm2, charm3],
encouragedSkills: () => [stare0, stare1, stare2, stare3],
requiredSkills: () => [lore0, lore1, lore2],
prologue: compile([
whisper,
"Master?",
whisper,
"I see.",
"You. I -- should dedicate my life to the vampiric sciences.",
whisper,
"My looks and my party skills...",
]),
onFailure: compile([
whisper,
"You're displeased...",
whisper,
"I should have learned more lore.",
]),
onVictory: compile([
whisper,
"I did as you commanded.",
"You're pleased?",
"... I'm free.",
]),
});
export const batFreak = table.add({
profile: {
name: "Bat Freak",
note: "++Bat -All",
domicile: "Master's Chiropteriary",
reignSentence: "You're an idol among bats.",
failureName: "Practically Mortal",
failureDomicile: "Right Side Up",
failureReignSentence: "Bats can tell you don't skreek correctly.",
failureSuccessorVerb: "Apologize -- SKREEK!",
},
isRandomlyAvailable: true,
isCompulsory: false,
bannedSkills: () => [charm0, stare0, party0, lore0],
discouragedSkills: () => [],
encouragedSkills: () => [stealth0, stealth1, stealth2, stealth3],
requiredSkills: () => [bat0, bat1, bat2, bat3],
prologue: compile([
whisper,
"Master?",
whisper,
"I see.",
"You -- SKKREEK -- want me to become a -- SKKREEK --",
]),
onFailure: compile([
whisper,
"You're displeased...",
whisper,
"I -- SKREEEEK -- should have spent more time becoming a bat...",
]),
onVictory: compile([whisper, "SKRSKRSKRSK.", "I'm FREEEEEEEEEE --"]),
});
export const repent = table.add({
profile: {
name: "Not Even Fit To Be Bat Food",
note: "--All",
domicile: "Master's Home",
reignSentence: "You are almost, but not quite loved.",
failureName: "Can't Even Repent Correctly",
failureDomicile: "Homeless",
failureReignSentence: "You are unloved and disrespected.",
failureSuccessorVerb: "Apologize Again",
},
isRandomlyAvailable: false,
isCompulsory: true,
bannedSkills: () => getSkills().getAvailableSkills(false),
discouragedSkills: () => [],
encouragedSkills: () => [],
requiredSkills: () => [sorry0, sorry1, sorry2],
prologue: compile([
whisper,
"I'm sorry.",
"Please...",
whisper,
"I must repent.",
]),
onFailure: compile([
whisper,
"I can't --",
"I must --",
whisper,
"Master -- please, no, I --",
]),
onVictory: compile([whisper, "Yes, I see.", "I'm free...?"]),
});
export function generateWishes(penance: boolean): Wish[] {
if (penance) {
return [repent];
}
let possibleWishes = table.getAllRandomWishes();
shuffle(possibleWishes);
let selectedWishes: Wish[] = [];
for (let i = 0; i < possibleWishes.length; i++) {
selectedWishes.push(possibleWishes[i]);
}
return selectedWishes;
}
export function getCostMultiplier(wish: Wish | null, skill: Skill): number {
if (wish == null) {
return 1.0;
}
let wishData = getWishes().get(wish);
for (let subj of wishData.requiredSkills()) {
if (subj.id == skill.id) {
return 0.75;
}
}
for (let subj of wishData.encouragedSkills()) {
if (subj.id == skill.id) {
return 0.875;
}
}
for (let subj of wishData.discouragedSkills()) {
if (subj.id == skill.id) {
return 1.25;
}
}
for (let subj of wishData.bannedSkills()) {
if (subj.id == skill.id) {
return 9999.0;
}
}
return 1.0;
}
export function isWishCompleted(wish: Wish): boolean {
let player = getPlayerProgress();
let wishData = getWishes().get(wish);
for (let subj of wishData.requiredSkills()) {
if (!player.hasLearned(subj)) {
return false;
}
}
return true;
}