Various minor fixes to successor system and mixing

This commit is contained in:
2025-02-23 12:09:47 -08:00
parent 9024d67114
commit d031a6acbe
18 changed files with 94 additions and 25 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

After

Width:  |  Height:  |  Size: 651 B

-1
View File
@@ -7,7 +7,6 @@ import { BG_INSET, FG_BOLD } from "./colors.ts";
import { addButton } from "./button.ts"; import { addButton } from "./button.ts";
import { getSkills } from "./skills.ts"; import { getSkills } from "./skills.ts";
import { getPlayerProgress } from "./playerprogress.ts"; import { getPlayerProgress } from "./playerprogress.ts";
import { sndRecruit } from "./sounds.ts";
export class CheckModal { export class CheckModal {
#drawpile: DrawPile; #drawpile: DrawPile;
+2
View File
@@ -1,4 +1,5 @@
import { VNScene } from "./vnscene.ts"; import { VNScene } from "./vnscene.ts";
import { Thrall } from "./thralls.ts";
export type Stat = "AGI" | "INT" | "CHA" | "PSI"; export type Stat = "AGI" | "INT" | "CHA" | "PSI";
export const ALL_STATS: Array<Stat> = ["AGI", "INT", "CHA", "PSI"]; export const ALL_STATS: Array<Stat> = ["AGI", "INT", "CHA", "PSI"];
@@ -104,6 +105,7 @@ export type EndingAnalytics = {
export type SuccessorOption = { export type SuccessorOption = {
name: string; name: string;
title: string; title: string;
template: Thrall;
note: string | null; // ex "already a vampire" note: string | null; // ex "already a vampire"
stats: Record<Stat, number>; stats: Record<Stat, number>;
talents: Record<Stat, number>; talents: Record<Stat, number>;
+10
View File
@@ -7,6 +7,7 @@ import { addButton } from "./button.ts";
import { ALL_STATS, Ending } from "./datatypes.ts"; import { ALL_STATS, Ending } from "./datatypes.ts";
import { getStateManager } from "./statemanager.ts"; import { getStateManager } from "./statemanager.ts";
import { getWishes } from "./wishes.ts"; import { getWishes } from "./wishes.ts";
import { sndEnding } from "./sounds.ts";
const WIDTH = 384; const WIDTH = 384;
const HEIGHT = 384; const HEIGHT = 384;
@@ -19,6 +20,8 @@ export class EndgameModal {
#selectedWish: number | null; #selectedWish: number | null;
#ending: Ending | null; #ending: Ending | null;
#playedSound: boolean;
constructor() { constructor() {
this.#drawpile = new DrawPile(); this.#drawpile = new DrawPile();
this.#page = 0; this.#page = 0;
@@ -27,6 +30,8 @@ export class EndgameModal {
this.#selectedWish = null; this.#selectedWish = null;
this.#ending = null; this.#ending = null;
this.#playedSound = false;
// this.show(getScorer().pickEnding()); // this.show(getScorer().pickEnding());
} }
@@ -66,6 +71,11 @@ export class EndgameModal {
#update() { #update() {
this.#fixCompulsory(); this.#fixCompulsory();
if (!this.#playedSound) {
sndEnding.play({ bgm: true });
this.#playedSound = true;
}
this.#drawpile.clear(); this.#drawpile.clear();
if (this.#page == 0) { if (this.#page == 0) {
let analytics = this.#ending?.analytics; let analytics = this.#ending?.analytics;
+2 -3
View File
@@ -120,9 +120,8 @@ export class Floater {
} }
get bbox(): Circle { get bbox(): Circle {
let w = 0.25; let sz = 0.25;
let h = 0.25; return new Circle(this.xy, sz / 2);
return new Circle(this.xy, w / 2);
} }
drawParticle(projected: Point, isShadow: boolean): any { drawParticle(projected: Point, isShadow: boolean): any {
this.#callbacks.drawParticle( this.#callbacks.drawParticle(
-3
View File
@@ -6,9 +6,6 @@ import { addButton } from "./button.ts";
import { getPlayerProgress } from "./playerprogress.ts"; import { getPlayerProgress } from "./playerprogress.ts";
import { getStateManager } from "./statemanager.ts"; import { getStateManager } from "./statemanager.ts";
import { getCheckModal } from "./checkmodal.ts"; import { getCheckModal } from "./checkmodal.ts";
import { sndRecruit, sndSleep } from "./sounds.ts";
//import { LadderPickup } from "./pickups.ts";
// import { generateMap } from "./mapgen.ts";
type Button = { type Button = {
label: string; label: string;
+6 -8
View File
@@ -1,7 +1,6 @@
import { Circle, Point, Rect, Size } from "./engine/datatypes.ts"; import { Circle, Point, Size } from "./engine/datatypes.ts";
import { DrawPile } from "./drawpile.ts"; import { DrawPile } from "./drawpile.ts";
import { D, I } from "./engine/public.ts"; import { D, I } from "./engine/public.ts";
import { sprThrallLore } from "./sprites.ts";
import { import {
BG_INSET, BG_INSET,
FG_TEXT, FG_TEXT,
@@ -14,11 +13,10 @@ import { FLOOR_CELL_SIZE, GridArt } from "./gridart.ts";
import { shadowcast } from "./shadowcast.ts"; import { shadowcast } from "./shadowcast.ts";
import { withCamera } from "./layout.ts"; import { withCamera } from "./layout.ts";
import { getCheckModal } from "./checkmodal.ts"; import { getCheckModal } from "./checkmodal.ts";
import { CARDINAL_DIRECTIONS } from "./mapgen.ts";
import { Block3D, Floor3D, World3D } from "./world3d.ts"; import { Block3D, Floor3D, World3D } from "./world3d.ts";
import { Floater } from "./floater.ts"; import { Floater } from "./floater.ts";
import { displace } from "./physics.ts"; import { displace } from "./physics.ts";
import { sndRecruit } from "./sounds.ts"; import { getThralls } from "./thralls.ts";
export class HuntMode { export class HuntMode {
map: LoadedNewMap; map: LoadedNewMap;
@@ -197,12 +195,11 @@ export class HuntMode {
this.faceLeft = false; this.faceLeft = false;
} }
let szX = 0.5; let sz = getThralls().get(getPlayerProgress().template).hitboxSize;
let szY = 0.5;
this.velocity = new Point(dx, dy); this.velocity = new Point(dx, dy);
let bbox = new Circle(this.floatingPlayer, szX / 2); let bbox = new Circle(this.floatingPlayer, sz / 2);
let { displacement, dxy } = displace(bbox, this.velocity, (b: Circle) => let { displacement, dxy } = displace(bbox, this.velocity, (b: Circle) =>
this.getContact(b), this.getContact(b),
); );
@@ -373,8 +370,9 @@ export class HuntMode {
}); });
}); });
*/ */
let sprite = getThralls().get(getPlayerProgress().template).sprite;
this.drawpile.add(1024, () => { this.drawpile.add(1024, () => {
D.drawSprite(sprThrallLore, new Point(192, 192), 1, { D.drawSprite(sprite, new Point(192, 192), 1, {
xScale: this.faceLeft ? -2 : 2, xScale: this.faceLeft ? -2 : 2,
yScale: 2, yScale: 2,
}); });
+2 -2
View File
@@ -42,14 +42,14 @@ const names = [
"Thisby", "Thisby",
"Calloway", "Calloway",
"Fenna", "Fenna",
"Lupin", // "Lupin",
"Finlo", "Finlo",
"Tycho", "Tycho",
"Talmadge", "Talmadge",
// others // others
"Jeff", "Jeff",
"Jon", "Jon",
"Garrett", // "Garrett",
"Russell", "Russell",
"Tyson", "Tyson",
"Gervase", "Gervase",
+1 -1
View File
@@ -1,4 +1,4 @@
import { Circle, lerp, Point, Rect } from "./engine/datatypes.ts"; import { Circle, lerp, Point } from "./engine/datatypes.ts";
export function displace( export function displace(
bbox: Circle, bbox: Circle,
+6
View File
@@ -4,6 +4,7 @@ import { getThralls, ItemStage, LifeStage, Thrall } from "./thralls.ts";
export class PlayerProgress { export class PlayerProgress {
#name: string; #name: string;
#thrallTemplate: number;
#stats: Record<Stat, number>; #stats: Record<Stat, number>;
#talents: Record<Stat, number>; #talents: Record<Stat, number>;
#isInPenance: boolean; #isInPenance: boolean;
@@ -20,6 +21,7 @@ export class PlayerProgress {
constructor(asSuccessor: SuccessorOption, withWish: Wish | null) { constructor(asSuccessor: SuccessorOption, withWish: Wish | null) {
this.#name = asSuccessor.name; this.#name = asSuccessor.name;
this.#thrallTemplate = asSuccessor.template.id;
this.#stats = { ...asSuccessor.stats }; this.#stats = { ...asSuccessor.stats };
this.#talents = { ...asSuccessor.talents }; this.#talents = { ...asSuccessor.talents };
this.#isInPenance = asSuccessor.inPenance; this.#isInPenance = asSuccessor.inPenance;
@@ -47,6 +49,10 @@ export class PlayerProgress {
return this.#name; return this.#name;
} }
get template(): Thrall {
return { id: this.#thrallTemplate };
}
get isInPenance(): boolean { get isInPenance(): boolean {
return this.#isInPenance; return this.#isInPenance;
} }
+15 -1
View File
@@ -1,8 +1,12 @@
class SoundShared { class SoundShared {
readonly context: AudioContext; readonly context: AudioContext;
bgmSource: AudioBufferSourceNode | null;
bgmGain: GainNode | null;
constructor() { constructor() {
this.context = new AudioContext(); this.context = new AudioContext();
this.bgmSource = null;
this.bgmGain = null;
} }
} }
const shared = new SoundShared(); const shared = new SoundShared();
@@ -25,7 +29,7 @@ export class Sound {
return await this.#audioBufferPromise; return await this.#audioBufferPromise;
} }
play(options?: { volume: number }) { play(options?: { volume?: number; bgm?: boolean }) {
this.#getAudioBuffer().then((adata) => { this.#getAudioBuffer().then((adata) => {
let source = shared.context.createBufferSource(); let source = shared.context.createBufferSource();
source.buffer = adata; source.buffer = adata;
@@ -34,6 +38,16 @@ export class Sound {
source.connect(gain); source.connect(gain);
gain.connect(shared.context.destination); gain.connect(shared.context.destination);
source.start(); source.start();
if (options?.bgm) {
shared.bgmSource?.stop(shared.context.currentTime + 1);
shared.bgmGain?.gain?.linearRampToValueAtTime(
0.0,
shared.context.currentTime + 1,
);
shared.bgmSource = source;
shared.bgmGain = gain;
}
}); });
} }
} }
+4
View File
@@ -1,22 +1,26 @@
import audBite from "./art/sounds/bite.mp3"; import audBite from "./art/sounds/bite.mp3";
import audDeath from "./art/sounds/death.mp3"; import audDeath from "./art/sounds/death.mp3";
import audDig from "./art/sounds/dig.mp3"; import audDig from "./art/sounds/dig.mp3";
import audEnding from "./art/sounds/ending.mp3";
import audRecruit from "./art/sounds/recruit.mp3"; import audRecruit from "./art/sounds/recruit.mp3";
import audRewardBig from "./art/sounds/reward_big.mp3"; import audRewardBig from "./art/sounds/reward_big.mp3";
import audRewardHuge from "./art/sounds/reward_huge.mp3"; import audRewardHuge from "./art/sounds/reward_huge.mp3";
import audRewardMedium from "./art/sounds/reward_medium.mp3"; import audRewardMedium from "./art/sounds/reward_medium.mp3";
import audRewardSmall from "./art/sounds/reward_small.mp3"; import audRewardSmall from "./art/sounds/reward_small.mp3";
import audSilence from "./art/sounds/silence.mp3";
import audSleep from "./art/sounds/sleep.mp3"; import audSleep from "./art/sounds/sleep.mp3";
import { Sound } from "./sound.ts"; import { Sound } from "./sound.ts";
export let sndBite = new Sound(audBite); export let sndBite = new Sound(audBite);
export let sndDeath = new Sound(audDeath); export let sndDeath = new Sound(audDeath);
export let sndDig = new Sound(audDig); export let sndDig = new Sound(audDig);
export let sndEnding = new Sound(audEnding);
export let sndRecruit = new Sound(audRecruit); export let sndRecruit = new Sound(audRecruit);
export let sndRewardBig = new Sound(audRewardBig); export let sndRewardBig = new Sound(audRewardBig);
export let sndRewardHuge = new Sound(audRewardHuge); export let sndRewardHuge = new Sound(audRewardHuge);
export let sndRewardMedium = new Sound(audRewardMedium); export let sndRewardMedium = new Sound(audRewardMedium);
export let sndRewardSmall = new Sound(audRewardSmall); export let sndRewardSmall = new Sound(audRewardSmall);
export let sndSilence = new Sound(audSilence);
export let sndSleep = new Sound(audSleep); export let sndSleep = new Sound(audSleep);
export function sndRewardFor(amount: number) { export function sndRewardFor(amount: number) {
+9 -5
View File
@@ -5,8 +5,11 @@ import { getScorer } from "./scorer.ts";
import { getEndgameModal } from "./endgamemodal.ts"; import { getEndgameModal } from "./endgamemodal.ts";
import { SuccessorOption, Wish } from "./datatypes.ts"; import { SuccessorOption, Wish } from "./datatypes.ts";
import { generateManor } from "./manormap.ts"; import { generateManor } from "./manormap.ts";
import { sndSleep } from "./sounds.ts"; import { sndSilence, sndSleep } from "./sounds.ts";
import { openingScene } from "./openingscene.ts"; import { openingScene } from "./openingscene.ts";
import { generateName } from "./namegen.ts";
import { photogenicThralls } from "./thralls.ts";
import { choose } from "./utils.ts";
const N_TURNS: number = 9; const N_TURNS: number = 9;
@@ -29,7 +32,8 @@ export class StateManager {
callback: () => { callback: () => {
this.startGame( this.startGame(
{ {
name: "Pyrex", name: generateName(),
template: choose(photogenicThralls),
title: "", title: "",
note: null, note: null,
stats: { AGI: 10, INT: 10, CHA: 10, PSI: 10 }, stats: { AGI: 10, INT: 10, CHA: 10, PSI: 10 },
@@ -49,7 +53,7 @@ export class StateManager {
this.#turn = 1; this.#turn = 1;
initPlayerProgress(asSuccessor, withWish); initPlayerProgress(asSuccessor, withWish);
initHuntMode(new HuntMode(1, generateManor())); initHuntMode(new HuntMode(1, generateManor()));
sndSleep.play(); sndSleep.play({ bgm: true });
} }
advance() { advance() {
@@ -58,9 +62,9 @@ export class StateManager {
getPlayerProgress().applyEndOfTurn(); getPlayerProgress().applyEndOfTurn();
getPlayerProgress().refill(); getPlayerProgress().refill();
initHuntMode(new HuntMode(getHuntMode().depth, generateManor())); initHuntMode(new HuntMode(getHuntMode().depth, generateManor()));
sndSleep.play(); sndSleep.play({ bgm: true });
} else { } else {
// TODO: Play a specific scene sndSilence.play({ bgm: true });
let ending = getScorer().pickEnding(); let ending = getScorer().pickEnding();
getVNModal().play(ending.scene); getVNModal().play(ending.scene);
getEndgameModal().show(ending); getEndgameModal().show(ending);
+14 -1
View File
@@ -2,6 +2,7 @@ import { ALL_STATS, Skill, Stat, SuccessorOption } from "./datatypes.ts";
import { generateName, generateTitle } from "./namegen.ts"; import { generateName, generateTitle } from "./namegen.ts";
import { choose } from "./utils.ts"; import { choose } from "./utils.ts";
import { getPlayerProgress } from "./playerprogress.ts"; import { getPlayerProgress } from "./playerprogress.ts";
import { photogenicThralls } from "./thralls.ts";
export function generateSuccessors( export function generateSuccessors(
nImprovements: number, nImprovements: number,
@@ -35,6 +36,7 @@ export function generateSuccessorFromPlayer(): SuccessorOption {
let progress = getPlayerProgress(); let progress = getPlayerProgress();
let successor = { let successor = {
name: progress.name, name: progress.name,
template: progress.template,
title: "Penitent", title: "Penitent",
note: "Failed at Master's bidding", note: "Failed at Master's bidding",
stats: { ...progress.getStats() }, stats: { ...progress.getStats() },
@@ -52,6 +54,7 @@ export function generateSuccessorFromPlayer(): SuccessorOption {
export function generateSuccessor(nImprovements: number): SuccessorOption { export function generateSuccessor(nImprovements: number): SuccessorOption {
let name = generateName(); let name = generateName();
let template = choose(photogenicThralls);
let title = generateTitle(); let title = generateTitle();
let note = null; let note = null;
let stats: Record<Stat, number> = { let stats: Record<Stat, number> = {
@@ -85,5 +88,15 @@ export function generateSuccessor(nImprovements: number): SuccessorOption {
let skills: Skill[] = []; let skills: Skill[] = [];
let inPenance = false; let inPenance = false;
let isCompulsory = false; let isCompulsory = false;
return { name, title, note, stats, talents, skills, inPenance, isCompulsory }; return {
name,
template,
title,
note,
stats,
talents,
skills,
inPenance,
isCompulsory,
};
} }
+23
View File
@@ -56,6 +56,7 @@ class ThrallsTable {
export type ThrallData = { export type ThrallData = {
label: string; label: string;
sprite: Sprite; sprite: Sprite;
hitboxSize: number;
posterCheck: CheckData; posterCheck: CheckData;
initialCheck: CheckData; initialCheck: CheckData;
itemHint: string; itemHint: string;
@@ -99,6 +100,7 @@ export function getThralls() {
export let thrallParty = table.add({ export let thrallParty = table.add({
label: "Garrett", label: "Garrett",
sprite: sprThrallParty, sprite: sprThrallParty,
hitboxSize: 0.7,
posterCheck: { posterCheck: {
label: label:
"This room would be perfect for someone with an ostensibly managed gambling addiction.", "This room would be perfect for someone with an ostensibly managed gambling addiction.",
@@ -172,6 +174,7 @@ export let thrallParty = table.add({
export let thrallLore = table.add({ export let thrallLore = table.add({
label: "Lupin", label: "Lupin",
sprite: sprThrallLore, sprite: sprThrallLore,
hitboxSize: 0.65,
posterCheck: { posterCheck: {
label: label:
"This room would be perfect for someone with a love of nature and screaming.", "This room would be perfect for someone with a love of nature and screaming.",
@@ -244,6 +247,7 @@ export let thrallLore = table.add({
export let thrallBat = table.add({ export let thrallBat = table.add({
label: "Monica", label: "Monica",
sprite: sprThrallBat, sprite: sprThrallBat,
hitboxSize: 0.4,
posterCheck: { posterCheck: {
label: "This room would be perfect for some kind of television chef.", label: "This room would be perfect for some kind of television chef.",
options: [], options: [],
@@ -318,6 +322,7 @@ export let thrallBat = table.add({
export let thrallCharm = table.add({ export let thrallCharm = table.add({
label: "Renfield", label: "Renfield",
sprite: sprThrallCharm, sprite: sprThrallCharm,
hitboxSize: 0.85,
posterCheck: { posterCheck: {
label: label:
"This room would be perfect for someone who likes vampires even more than you enjoy being a vampire.", "This room would be perfect for someone who likes vampires even more than you enjoy being a vampire.",
@@ -389,6 +394,7 @@ export let thrallCharm = table.add({
export let thrallStealth = table.add({ export let thrallStealth = table.add({
label: "Narthyss", label: "Narthyss",
sprite: sprThrallStealth, sprite: sprThrallStealth,
hitboxSize: 0.85,
posterCheck: { posterCheck: {
label: "This room would be perfect for someone who can breathe fire.", label: "This room would be perfect for someone who can breathe fire.",
options: [], options: [],
@@ -461,6 +467,7 @@ export let thrallStealth = table.add({
export let thrallStare = table.add({ export let thrallStare = table.add({
label: "Ridley", label: "Ridley",
sprite: sprThrallStare, sprite: sprThrallStare,
hitboxSize: 0.85,
posterCheck: { posterCheck: {
label: "This room would be perfect for a soulless robot.", label: "This room would be perfect for a soulless robot.",
options: [], options: [],
@@ -525,3 +532,19 @@ export let thrallStare = table.add({
}, },
}, },
}); });
export let photogenicThralls = [
thrallParty,
thrallParty,
thrallParty,
thrallLore,
thrallLore,
thrallLore,
thrallCharm,
thrallCharm,
thrallCharm,
thrallStealth,
thrallStealth,
thrallStealth,
thrallBat,
];