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