150 lines
4.6 KiB
TypeScript
150 lines
4.6 KiB
TypeScript
import { VNScene } from "./vnscene.ts";
|
|
import { getPlayerProgress } from "./playerprogress.ts";
|
|
import { getSkills } from "./skills.ts";
|
|
import { Ending, SCORING_CATEGORIES, ScoringCategory } from "./datatypes.ts";
|
|
import {
|
|
sceneBat,
|
|
sceneCharm,
|
|
sceneLore,
|
|
sceneParty,
|
|
sceneStare,
|
|
sceneStealth,
|
|
} from "./endings.ts";
|
|
import { generateWishes, getWishes, isWishCompleted } from "./wishes.ts";
|
|
import { generateSuccessors } from "./successors.ts";
|
|
|
|
class Scorer {
|
|
constructor() {}
|
|
|
|
pickEnding(): Ending {
|
|
let learnedSkills = getPlayerProgress().getLearnedSkills();
|
|
let scores: Record<string, number> = {};
|
|
|
|
let itemsPurloined = getPlayerProgress().getItemsPurloined();
|
|
let vampiricSkills = 0;
|
|
let mortalServants = itemsPurloined / 10;
|
|
|
|
for (const skill of learnedSkills.values()) {
|
|
let data = getSkills().get(skill);
|
|
for (let [category, number] of Object.entries(data.governing.scoring)) {
|
|
scores[category] = (scores[category] ?? 0) + number;
|
|
}
|
|
mortalServants += data.governing.mortalServantValue;
|
|
vampiricSkills += 1;
|
|
}
|
|
|
|
mortalServants = Math.max(Math.floor(mortalServants), 0);
|
|
|
|
// NOTE: This approach isn't efficient but it's easy to understand
|
|
// and it allows me to arbitrate ties however I want
|
|
let runningScores: Record<string, number> = { ...scores };
|
|
const isMax = (cat: ScoringCategory, min: number) => {
|
|
let score = runningScores[cat] ?? 0;
|
|
runningScores[cat] = 0; // each category, once checked, can't disqualify any other category
|
|
|
|
if (score < min) {
|
|
return false;
|
|
}
|
|
for (let cat of SCORING_CATEGORIES.values()) {
|
|
if (runningScores[cat] > score) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
let scene: VNScene;
|
|
let rank: string;
|
|
let domicile: string;
|
|
let reignSentence: string;
|
|
let penance: boolean = false;
|
|
let successorVerb: string = "Appoint a Successor";
|
|
|
|
// Let the player
|
|
let wish = getPlayerProgress().getWish();
|
|
if (wish != null) {
|
|
let data = getWishes().get(wish);
|
|
if (isWishCompleted(wish)) {
|
|
scene = data.onVictory;
|
|
rank = data.profile.name;
|
|
domicile = data.profile.domicile;
|
|
reignSentence = data.profile.reignSentence;
|
|
} else {
|
|
scene = data.onFailure;
|
|
rank = data.profile.failureName;
|
|
domicile = data.profile.failureDomicile;
|
|
reignSentence = data.profile.failureReignSentence;
|
|
penance = true;
|
|
successorVerb = data.profile.failureSuccessorVerb;
|
|
}
|
|
}
|
|
// TODO: Award different ranks depending on second-to-top skill
|
|
// TODO: Award different domiciles based on overall score
|
|
// TODO: Force the rank to match the wish if one existed
|
|
else if (isMax("stare", 3)) {
|
|
scene = sceneStare;
|
|
rank = "Hypno-Chiropteran";
|
|
domicile = "Village of Brainwashed Mortals";
|
|
reignSentence = "You rule with a fair but unflinching gaze.";
|
|
} else if (isMax("lore", 3)) {
|
|
scene = sceneLore;
|
|
rank = "Loremaster";
|
|
domicile = "Vineyard";
|
|
reignSentence = "You're well on the path to ultimate knowledge.";
|
|
} else if (isMax("charm", 2)) {
|
|
scene = sceneCharm;
|
|
rank = "Seducer";
|
|
domicile = "Guest House";
|
|
reignSentence = "You get to sink your fangs into anyone you want.";
|
|
} else if (isMax("party", 1)) {
|
|
scene = sceneParty;
|
|
rank = "Party Animal";
|
|
domicile = "Nightclub";
|
|
reignSentence = "Everyone thinks you're too cool to disobey.";
|
|
} else if (isMax("stealth", 0)) {
|
|
scene = sceneStealth;
|
|
rank = "Invisible";
|
|
domicile = "Townhouse";
|
|
reignSentence = "People don't see you but they do most of what you want.";
|
|
}
|
|
// if (isMax("bat")) {
|
|
else {
|
|
scene = sceneBat;
|
|
rank = "Bat";
|
|
domicile = "Cave";
|
|
reignSentence =
|
|
"Your skreeking verdicts are irresistible to your subjects.";
|
|
}
|
|
|
|
// TODO: Analytics tracker
|
|
let analytics = {
|
|
itemsPurloined,
|
|
vampiricSkills,
|
|
mortalServants,
|
|
};
|
|
let successorOptions = generateSuccessors(0, penance); // TODO: generate nImprovements from mortalServants and the player's bsae improvements
|
|
let wishOptions = generateWishes(penance);
|
|
|
|
let progenerateVerb = penance ? "Repent" : "Progenerate";
|
|
|
|
return {
|
|
scene,
|
|
personal: {
|
|
rank,
|
|
domicile,
|
|
reignSentence,
|
|
successorVerb,
|
|
progenerateVerb,
|
|
},
|
|
analytics,
|
|
successorOptions,
|
|
wishOptions,
|
|
};
|
|
}
|
|
}
|
|
|
|
let active = new Scorer();
|
|
export function getScorer(): Scorer {
|
|
return active;
|
|
}
|