Save system: ceremonial PR #42
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 471 B After Width: | Height: | Size: 479 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 171 B After Width: | Height: | Size: 168 B | 
| @@ -1,12 +1,6 @@ | ||||
| import { DrawPile } from "./drawpile.ts"; | ||||
| import { AlignX, AlignY, Point, Rect, Size } from "./engine/datatypes.ts"; | ||||
| import { | ||||
|   BG_INSET, | ||||
|   FG_BOLD, | ||||
|   FG_TEXT, | ||||
|   FG_TEXT_DISABLED, | ||||
|   FG_TEXT_ENDORSED, | ||||
| } from "./colors.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
| import { D } from "./engine/public.ts"; | ||||
|  | ||||
| export function addButton( | ||||
| @@ -31,18 +25,18 @@ export function addButton( | ||||
|   drawpile.addClickable( | ||||
|     0, | ||||
|     (hover) => { | ||||
|       let [bg, fg, fgLabel] = [BG_INSET, FG_TEXT, FG_BOLD]; | ||||
|       let [bg, fg, fgLabel] = [C.BG_UI, C.FG_TEXT, C.FG_BOLD]; | ||||
|       if (!enabled) { | ||||
|         fgLabel = FG_TEXT_DISABLED; | ||||
|         fgLabel = C.FG_TEXT_DISABLED; | ||||
|       } | ||||
|  | ||||
|       if (enabled && options?.endorse) { | ||||
|         fg = FG_TEXT_ENDORSED; | ||||
|         fgLabel = FG_TEXT_ENDORSED; | ||||
|         fg = C.FG_TEXT_ENDORSED; | ||||
|         fgLabel = C.FG_TEXT_ENDORSED; | ||||
|       } | ||||
|  | ||||
|       if (hover) { | ||||
|         [bg, fg, fgLabel] = [FG_BOLD, BG_INSET, BG_INSET]; | ||||
|         [bg, fg, fgLabel] = [C.FG_BOLD, C.BG_UI, C.BG_UI]; | ||||
|       } | ||||
|       D.fillRect( | ||||
|         topLeftPadded.offset(new Point(-1, -1)), | ||||
|   | ||||
| @@ -3,10 +3,10 @@ import { CheckData, CheckDataOption, ChoiceOption } from "./newmap.ts"; | ||||
| import { getPartLocation, withCamera } from "./layout.ts"; | ||||
| import { AlignX, AlignY, Point, Rect, Size } from "./engine/datatypes.ts"; | ||||
| import { D } from "./engine/public.ts"; | ||||
| import { BG_INSET, FG_BOLD } from "./colors.ts"; | ||||
| import { addButton } from "./button.ts"; | ||||
| import { getSkills } from "./skills.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| export class CheckModal { | ||||
|   #drawpile: DrawPile; | ||||
| @@ -54,17 +54,22 @@ export class CheckModal { | ||||
|  | ||||
|     let size = this.#size; | ||||
|     this.#drawpile.add(0, () => { | ||||
|       D.fillRect(new Point(-4, -4), size.add(new Size(8, 8)), BG_INSET); | ||||
|       D.fillRect(new Point(-4, -4), size.add(new Size(8, 8)), C.BG_UI); | ||||
|     }); | ||||
|  | ||||
|     let success = this.#success; | ||||
|     if (success) { | ||||
|       this.#drawpile.add(0, () => { | ||||
|         D.drawText(success, new Point(size.w / 2, (size.h - 64) / 2), FG_BOLD, { | ||||
|         D.drawText( | ||||
|           success, | ||||
|           new Point(size.w / 2, (size.h - 64) / 2), | ||||
|           C.FG_BOLD, | ||||
|           { | ||||
|             forceWidth: size.w, | ||||
|             alignX: AlignX.Center, | ||||
|             alignY: AlignY.Middle, | ||||
|         }); | ||||
|           }, | ||||
|         ); | ||||
|       }); | ||||
|       addButton( | ||||
|         this.#drawpile, | ||||
| @@ -80,11 +85,16 @@ export class CheckModal { | ||||
|  | ||||
|     let labelText = check.label; | ||||
|     this.#drawpile.add(0, () => { | ||||
|       D.drawText(labelText, new Point(size.w / 2, (size.h - 64) / 2), FG_BOLD, { | ||||
|       D.drawText( | ||||
|         labelText, | ||||
|         new Point(size.w / 2, (size.h - 64) / 2), | ||||
|         C.FG_BOLD, | ||||
|         { | ||||
|           forceWidth: size.w, | ||||
|           alignX: AlignX.Center, | ||||
|           alignY: AlignY.Middle, | ||||
|       }); | ||||
|         }, | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     let options = check.options; | ||||
|   | ||||
							
								
								
									
										214
									
								
								src/colors.ts
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								src/colors.ts
									
									
									
									
									
								
							| @@ -1,46 +1,206 @@ | ||||
| import { Color } from "./engine/datatypes.ts"; | ||||
| import { Stat } from "./datatypes.ts"; | ||||
| import { maybeGetHuntMode } from "./huntmode.ts"; | ||||
| import { getEndgameModal } from "./endgamemodal.ts"; | ||||
| import { getVNModal } from "./vnmodal.ts"; | ||||
|  | ||||
| export const BG_OUTER = Color.parseHexCode("#143464"); | ||||
| export const BG_WALL_OR_UNREVEALED = Color.parseHexCode("#143464"); | ||||
| export const BG_INSET = Color.parseHexCode("#242234"); | ||||
| export const FG_TEXT = Color.parseHexCode("#c0c0c0"); | ||||
| export const FG_TEXT_DISABLED = Color.parseHexCode("#808080"); | ||||
| export const FG_TOO_EXPENSIVE = Color.parseHexCode("#ff8080"); | ||||
| export const FG_TEXT_ENDORSED = Color.parseHexCode("#80ff80"); | ||||
| export const FG_BOLD = Color.parseHexCode("#ffffff"); | ||||
| export const BG_CEILING = Color.parseHexCode("#143464"); | ||||
| export const FG_MOULDING = FG_TEXT; | ||||
| export type Microtheme = { | ||||
|   SKY0: Color; // outer, less dark | ||||
|   FLOOR0: Color; // floor, even less dark | ||||
|  | ||||
| // stat colors | ||||
| export const SWATCH_EXP: [Color, Color] = [ | ||||
|   WALL0: Color; // darkest (ex. the underside of something) | ||||
|   WALL1: Color; // darkest (ex. the underside of something) | ||||
|  | ||||
|   BG0: Color; // UI background -- should be highly readable and similar to SKY or FLOOR | ||||
|   FG1: Color; // dark (ex. disabled text) | ||||
|   FG2: Color; // normal  (ex. normal text) | ||||
|   FG3: Color; // brightest (ex. bold text) | ||||
| }; | ||||
|  | ||||
| /* | ||||
| const MICROTHEME_OLD: MicroTheme = { | ||||
|   BG0: Color.parseHexCode("#242234"), | ||||
|   BG1: Color.parseHexCode("#143464"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| } | ||||
|  */ | ||||
|  | ||||
| export const MICROTHEME_DEFAULT: Microtheme = { | ||||
|   // outdoors | ||||
|   SKY0: Color.parseHexCode("#242234"), | ||||
|   FLOOR0: Color.parseHexCode("#141013"), | ||||
|   WALL0: Color.parseHexCode("#5d758d"), | ||||
|   WALL1: Color.parseHexCode("#8b93af"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export const MICROTHEME_BLACK: Microtheme = { | ||||
|   // manor | ||||
|   SKY0: Color.parseHexCode("#141013"), | ||||
|   FLOOR0: Color.parseHexCode("#3b1725"), | ||||
|   WALL0: Color.parseHexCode("#221c1a"), | ||||
|   WALL1: Color.parseHexCode("#322b28"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export const MICROTHEME_PURPLE_TAN: Microtheme = { | ||||
|   // library | ||||
|   SKY0: Color.parseHexCode("#403353"), | ||||
|   FLOOR0: Color.parseHexCode("#242234"), | ||||
|   WALL0: Color.parseHexCode("#5a4e44"), | ||||
|   WALL1: Color.parseHexCode("#c7b08b"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export const MICROTHEME_GREEN: Microtheme = { | ||||
|   // zoo | ||||
|   SKY0: Color.parseHexCode("#24523b"), | ||||
|   FLOOR0: Color.parseHexCode("#122020"), | ||||
|   WALL0: Color.parseHexCode("#328464"), | ||||
|   WALL1: Color.parseHexCode("#5daf8d"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export const MICROTHEME_TEAL: Microtheme = { | ||||
|   // optometrist | ||||
|   SKY0: Color.parseHexCode("#143464"), | ||||
|   FLOOR0: Color.parseHexCode("#122020"), | ||||
|   WALL0: Color.parseHexCode("#477d85"), | ||||
|   WALL1: Color.parseHexCode("#588dbe"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export const MICROTHEME_PINK: Microtheme = { | ||||
|   // coffee shop | ||||
|   SKY0: Color.parseHexCode("#793a80"), | ||||
|   FLOOR0: Color.parseHexCode("#221c1a"), | ||||
|   WALL0: Color.parseHexCode("#e86a73"), | ||||
|   WALL1: Color.parseHexCode("#f5a097"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export const MICROTHEME_NEON: Microtheme = { | ||||
|   // club | ||||
|   SKY0: Color.parseHexCode("#141013"), | ||||
|   FLOOR0: Color.parseHexCode("#221c1a"), | ||||
|   WALL0: Color.parseHexCode("#9cdb43"), | ||||
|   WALL1: Color.parseHexCode("#d6f264"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export const MICROTHEME_RED: Microtheme = { | ||||
|   // blood bank | ||||
|   SKY0: Color.parseHexCode("#73172d"), | ||||
|   FLOOR0: Color.parseHexCode("#141013"), | ||||
|   WALL0: Color.parseHexCode("#df3e23"), | ||||
|   WALL1: Color.parseHexCode("#f9a31b"), | ||||
|   BG0: Color.parseHexCode("#000000"), | ||||
|   FG1: Color.parseHexCode("#8b93af"), | ||||
|   FG2: Color.parseHexCode("#b3b9d1"), | ||||
|   FG3: Color.parseHexCode("#ffffff"), | ||||
| }; | ||||
|  | ||||
| export class ColorSystem { | ||||
|   get BG_UI() { | ||||
|     return this.#microtheme.BG0; | ||||
|   } | ||||
|   get BG_FLOOR() { | ||||
|     return this.#microtheme.FLOOR0; | ||||
|   } | ||||
|   get FG_TEXT() { | ||||
|     return this.#microtheme.FG2; | ||||
|   } | ||||
|   get FG_TEXT_DISABLED() { | ||||
|     return this.#microtheme.FG1; | ||||
|   } | ||||
|   readonly FG_TOO_EXPENSIVE = Color.parseHexCode("#f5a097"); | ||||
|   readonly FG_TEXT_ENDORSED = Color.parseHexCode("#d6f264"); | ||||
|   get FG_BOLD() { | ||||
|     return this.#microtheme.FG3; | ||||
|   } | ||||
|   get BG_OUTER() { | ||||
|     return this.#microtheme.SKY0; | ||||
|   } | ||||
|   get BG_WALL_OR_UNREVEALED() { | ||||
|     return this.#microtheme.SKY0; | ||||
|   } | ||||
|   get BG_CEILING() { | ||||
|     return this.#microtheme.SKY0; | ||||
|   } | ||||
|  | ||||
|   get BG_INNERWALL() { | ||||
|     return this.#microtheme.WALL0; | ||||
|   } | ||||
|   get BG_OUTERWALL() { | ||||
|     return this.#microtheme.WALL1; | ||||
|   } | ||||
|  | ||||
|   get #microtheme(): Microtheme { | ||||
|     if (getEndgameModal().isShown || getVNModal().isShown) { | ||||
|       return MICROTHEME_RED; | ||||
|     } | ||||
|     let option = maybeGetHuntMode()?.getActiveMicrotheme(); | ||||
|     if (option) { | ||||
|       return option; | ||||
|     } | ||||
|     return MICROTHEME_DEFAULT; | ||||
|   } | ||||
|  | ||||
|   // stat colors | ||||
|   readonly SWATCH_EXP: [Color, Color] = [ | ||||
|     Color.parseHexCode("#b9bffb"), | ||||
|     Color.parseHexCode("#e3e6ff"), | ||||
| ]; | ||||
|   ]; | ||||
|  | ||||
| export const SWATCH_AGI: [Color, Color] = [ | ||||
|   readonly SWATCH_AGI: [Color, Color] = [ | ||||
|     Color.parseHexCode("#df3e23"), | ||||
|     Color.parseHexCode("#fa6a0a"), | ||||
| ]; | ||||
|   ]; | ||||
|  | ||||
| export const SWATCH_INT: [Color, Color] = [ | ||||
|   readonly SWATCH_INT: [Color, Color] = [ | ||||
|     Color.parseHexCode("#285cc4"), | ||||
|     Color.parseHexCode("#249fde"), | ||||
| ]; | ||||
|   ]; | ||||
|  | ||||
| export const SWATCH_CHA: [Color, Color] = [ | ||||
|   readonly SWATCH_CHA: [Color, Color] = [ | ||||
|     Color.parseHexCode("#793a80"), | ||||
|     Color.parseHexCode("#bc4a9b"), | ||||
| ]; | ||||
|   ]; | ||||
|  | ||||
| export const SWATCH_PSI: [Color, Color] = [ | ||||
|   readonly SWATCH_PSI: [Color, Color] = [ | ||||
|     Color.parseHexCode("#9cdb43"), | ||||
|     Color.parseHexCode("#d6f264"), | ||||
| ]; | ||||
|   ]; | ||||
|  | ||||
| export const SWATCH_STAT: Record<Stat, [Color, Color]> = { | ||||
|   AGI: SWATCH_AGI, | ||||
|   INT: SWATCH_INT, | ||||
|   CHA: SWATCH_CHA, | ||||
|   PSI: SWATCH_PSI, | ||||
| }; | ||||
|   readonly SWATCH_STAT: Record<Stat, [Color, Color]> = { | ||||
|     AGI: this.SWATCH_AGI, | ||||
|     INT: this.SWATCH_INT, | ||||
|     CHA: this.SWATCH_CHA, | ||||
|     PSI: this.SWATCH_PSI, | ||||
|   }; | ||||
| } | ||||
|  | ||||
| export let C = new ColorSystem(); | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import { withCamera } from "./layout.ts"; | ||||
| import { D } from "./engine/public.ts"; | ||||
| import { BG_INSET, FG_BOLD, FG_TEXT } from "./colors.ts"; | ||||
| import { AlignX, AlignY, Point, Rect, Size } from "./engine/datatypes.ts"; | ||||
| import { DrawPile } from "./drawpile.ts"; | ||||
| import { addButton } from "./button.ts"; | ||||
| @@ -8,6 +7,7 @@ import { ALL_STATS, Ending } from "./datatypes.ts"; | ||||
| import { getStateManager } from "./statemanager.ts"; | ||||
| import { getWishes } from "./wishes.ts"; | ||||
| import { sndEnding } from "./sounds.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| const WIDTH = 384; | ||||
| const HEIGHT = 384; | ||||
| @@ -89,22 +89,22 @@ export class EndgameModal { | ||||
|         D.drawText( | ||||
|           "It is time to announce the sentence of fate.", | ||||
|           new Point(0, 0), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|         ); | ||||
|         D.drawText( | ||||
|           "You are no longer a fledgling. Your new rank:", | ||||
|           new Point(0, 32), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|         ); | ||||
|         D.drawText(rank, new Point(WIDTH / 2, 64), FG_BOLD, { | ||||
|         D.drawText(rank, new Point(WIDTH / 2, 64), C.FG_BOLD, { | ||||
|           alignX: AlignX.Center, | ||||
|         }); | ||||
|         D.drawText( | ||||
|           "You have achieved a DOMICILE STATUS of:", | ||||
|           new Point(0, 96), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|         ); | ||||
|         D.drawText(domicile, new Point(WIDTH / 2, 128), FG_BOLD, { | ||||
|         D.drawText(domicile, new Point(WIDTH / 2, 128), C.FG_BOLD, { | ||||
|           alignX: AlignX.Center, | ||||
|         }); | ||||
|         let whereLabel = | ||||
| @@ -113,8 +113,8 @@ export class EndgameModal { | ||||
|             : mortalServants >= 1 | ||||
|               ? "where you live with a couple of friends." | ||||
|               : "where you live without friends."; | ||||
|         D.drawText(whereLabel, new Point(0, 160), FG_TEXT); | ||||
|         D.drawText("You have achieved:", new Point(0, 192), FG_TEXT); | ||||
|         D.drawText(whereLabel, new Point(0, 160), C.FG_TEXT); | ||||
|         D.drawText("You have achieved:", new Point(0, 192), C.FG_TEXT); | ||||
|         let itemsPurloinedText = | ||||
|           itemsPurloined == 1 ? "item purloined" : "items purloined"; | ||||
|         let vampiricSkillsText = | ||||
| @@ -131,13 +131,13 @@ export class EndgameModal { | ||||
|         D.drawText( | ||||
|           `${itemsPurloined} ${itemsPurloinedText}\n${vampiricSkills} ${vampiricSkillsText}\n${mortalServants} ${mortalServantsText}`, | ||||
|           new Point(WIDTH / 2, 224), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|           { alignX: AlignX.Center }, | ||||
|         ); | ||||
|         D.drawText( | ||||
|           `${itemsPurloined} ${itemsPurloinedSpcr}\n${vampiricSkills} ${vampiricSkillsSpcr}\n${mortalServants} ${mortalServantsSpcr}`, | ||||
|           new Point(WIDTH / 2, 224), | ||||
|           FG_BOLD, | ||||
|           C.FG_BOLD, | ||||
|           { alignX: AlignX.Center }, | ||||
|         ); | ||||
|         let msg = "That's pretty dreadful."; | ||||
| @@ -147,14 +147,14 @@ export class EndgameModal { | ||||
|         if (mortalServants >= 30) { | ||||
|           msg = "That feels like a lot!"; | ||||
|         } | ||||
|         D.drawText(msg, new Point(0, 288), FG_TEXT); | ||||
|         D.drawText(msg, new Point(0, 288), C.FG_TEXT); | ||||
|         let reignSentence = | ||||
|           this.#ending?.personal?.reignSentence ?? | ||||
|           "Your reign is in an unknown state."; | ||||
|         D.drawText( | ||||
|           `${reignSentence} It is now time to`, | ||||
|           new Point(0, 320), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|           { forceWidth: WIDTH }, | ||||
|         ); | ||||
|       }); | ||||
| @@ -169,7 +169,7 @@ export class EndgameModal { | ||||
|       ); | ||||
|     } else if (this.#page == 1) { | ||||
|       this.#drawpile.add(0, () => { | ||||
|         D.drawText("Choose your successor:", new Point(0, 0), FG_TEXT); | ||||
|         D.drawText("Choose your successor:", new Point(0, 0), C.FG_TEXT); | ||||
|       }); | ||||
|  | ||||
|       this.#addCandidate(0, new Point(0, 16)); | ||||
| @@ -184,7 +184,7 @@ export class EndgameModal { | ||||
|         D.drawText( | ||||
|           `Plan their destiny:${optionalNote}`, | ||||
|           new Point(0, 224), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|         ); | ||||
|       }); | ||||
|  | ||||
| @@ -293,9 +293,9 @@ export class EndgameModal { | ||||
|     this.#drawpile.addClickable( | ||||
|       0, | ||||
|       (hover) => { | ||||
|         let [bg, fg, fgBold] = [BG_INSET, FG_TEXT, FG_BOLD]; | ||||
|         let [bg, fg, fgBold] = [C.BG_UI, C.FG_TEXT, C.FG_BOLD]; | ||||
|         if (hover || selected) { | ||||
|           [bg, fg, fgBold] = [FG_BOLD, BG_INSET, BG_INSET]; | ||||
|           [bg, fg, fgBold] = [C.FG_BOLD, C.BG_UI, C.BG_UI]; | ||||
|         } | ||||
|         D.fillRect(at.offset(new Point(0, 4)), new Size(w, h - 8), bg); | ||||
|         D.drawRect(at.offset(new Point(0, 4)), new Size(w, h - 8), fg); | ||||
| @@ -383,9 +383,9 @@ export class EndgameModal { | ||||
|     this.#drawpile.addClickable( | ||||
|       0, | ||||
|       (hover) => { | ||||
|         let [bg, fg, fgBold] = [BG_INSET, FG_TEXT, FG_BOLD]; | ||||
|         let [bg, fg, fgBold] = [C.BG_UI, C.FG_TEXT, C.FG_BOLD]; | ||||
|         if (hover || selected) { | ||||
|           [bg, fg, fgBold] = [FG_BOLD, BG_INSET, BG_INSET]; | ||||
|           [bg, fg, fgBold] = [C.FG_BOLD, C.BG_UI, C.BG_UI]; | ||||
|         } | ||||
|         D.fillRect(at.offset(new Point(2, 4)), new Size(w - 4, h - 8), bg); | ||||
|         D.drawRect(at.offset(new Point(2, 4)), new Size(w - 4, h - 8), fg); | ||||
| @@ -403,7 +403,7 @@ export class EndgameModal { | ||||
|         D.drawText( | ||||
|           wishData.profile.note, | ||||
|           at.offset(new Point(w / 2, h)), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|           { | ||||
|             alignX: AlignX.Center, | ||||
|           }, | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import { BG_OUTER } from "./colors.ts"; | ||||
| import { D, I } from "./engine/public.ts"; | ||||
| import { IGame, Point, Size } from "./engine/datatypes.ts"; | ||||
| import { getHotbar, Hotbar } from "./hotbar.ts"; | ||||
| @@ -7,6 +6,7 @@ import { getVNModal, VNModal } from "./vnmodal.ts"; | ||||
| import { Gameplay, getGameplay } from "./gameplay.ts"; | ||||
| import { getEndgameModal } from "./endgamemodal.ts"; | ||||
| import { CheckModal, getCheckModal } from "./checkmodal.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| export class Game implements IGame { | ||||
|   #mainThing: Gameplay | VNModal | null; | ||||
| @@ -28,7 +28,7 @@ export class Game implements IGame { | ||||
|     // draw screen background | ||||
|     let oldCamera = D.camera; | ||||
|     D.camera = new Point(0, 0); | ||||
|     D.fillRect(new Point(0, 0), D.size, BG_OUTER); | ||||
|     D.fillRect(new Point(0, 0), D.size, C.BG_OUTER); | ||||
|     D.camera = oldCamera; | ||||
|  | ||||
|     this.drawGameplay(); | ||||
|   | ||||
							
								
								
									
										36
									
								
								src/hud.ts
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								src/hud.ts
									
									
									
									
									
								
							| @@ -1,17 +1,11 @@ | ||||
| import { D } from "./engine/public.ts"; | ||||
| import { Point, Size } from "./engine/datatypes.ts"; | ||||
| import { | ||||
|   BG_OUTER, | ||||
|   FG_BOLD, | ||||
|   FG_TEXT, | ||||
|   FG_TEXT_ENDORSED, | ||||
|   FG_TOO_EXPENSIVE, | ||||
| } from "./colors.ts"; | ||||
| import { ALL_STATS } from "./datatypes.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| import { getHuntMode } from "./huntmode.ts"; | ||||
| import { getStateManager } from "./statemanager.ts"; | ||||
| import { withCamera } from "./layout.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| export class Hud { | ||||
|   get size(): Size { | ||||
| @@ -33,45 +27,45 @@ export class Hud { | ||||
|   #update() {} | ||||
|  | ||||
|   #draw() { | ||||
|     D.fillRect(new Point(-4, -4), this.size.add(new Size(8, 8)), BG_OUTER); | ||||
|     D.drawText(getPlayerProgress().name, new Point(0, 0), FG_BOLD); | ||||
|     D.fillRect(new Point(-4, -4), this.size.add(new Size(8, 8)), C.BG_OUTER); | ||||
|     D.drawText(getPlayerProgress().name, new Point(0, 0), C.FG_BOLD); | ||||
|  | ||||
|     let levelText = `Level ${getHuntMode().getDepth()}`; | ||||
|     let zoneLabel = getHuntMode().getZoneLabel(); | ||||
|     if (zoneLabel != null) { | ||||
|       levelText += ": " + zoneLabel; | ||||
|     } | ||||
|     D.drawText(levelText, new Point(0, 16), FG_TEXT); | ||||
|     D.drawText(levelText, new Point(0, 16), C.FG_TEXT); | ||||
|     D.drawText( | ||||
|       `Turn ${getStateManager().getTurn()}/${getStateManager().getMaxTurns()}`, | ||||
|       new Point(0, 32), | ||||
|       FG_TEXT, | ||||
|       C.FG_TEXT, | ||||
|     ); | ||||
|  | ||||
|     let y = 64; | ||||
|     let prog = getPlayerProgress(); | ||||
|     for (let s of ALL_STATS.values()) { | ||||
|       D.drawText(`${s}`, new Point(0, y), FG_BOLD); | ||||
|       D.drawText(`${prog.getStat(s)}`, new Point(32, y), FG_TEXT); | ||||
|       D.drawText(`${s}`, new Point(0, y), C.FG_BOLD); | ||||
|       D.drawText(`${prog.getStat(s)}`, new Point(32, y), C.FG_TEXT); | ||||
|       let talent = prog.getTalent(s); | ||||
|       if (talent > 0) { | ||||
|         D.drawText(`(+${talent})`, new Point(56, y), FG_TEXT); | ||||
|         D.drawText(`(+${talent})`, new Point(56, y), C.FG_TEXT); | ||||
|       } | ||||
|       if (talent < 0) { | ||||
|         D.drawText(`(${talent})`, new Point(56, y), FG_TEXT); | ||||
|         D.drawText(`(${talent})`, new Point(56, y), C.FG_TEXT); | ||||
|       } | ||||
|       y += 16; | ||||
|     } | ||||
|     D.drawText("EXP", new Point(0, 144), FG_BOLD); | ||||
|     D.drawText(`${prog.getExperience()}`, new Point(32, 144), FG_TEXT); | ||||
|     D.drawText("BLD", new Point(0, 160), FG_BOLD); | ||||
|     D.drawText("EXP", new Point(0, 144), C.FG_BOLD); | ||||
|     D.drawText(`${prog.getExperience()}`, new Point(32, 144), C.FG_TEXT); | ||||
|     D.drawText("BLD", new Point(0, 160), C.FG_BOLD); | ||||
|     let bloodAmount = prog.getBlood(); | ||||
|     let bloodColor = FG_TEXT; | ||||
|     let bloodColor = C.FG_TEXT; | ||||
|     if (bloodAmount >= 2000) { | ||||
|       bloodColor = FG_TEXT_ENDORSED; | ||||
|       bloodColor = C.FG_TEXT_ENDORSED; | ||||
|     } | ||||
|     if (bloodAmount < 100) { | ||||
|       bloodColor = FG_TOO_EXPENSIVE; | ||||
|       bloodColor = C.FG_TOO_EXPENSIVE; | ||||
|     } | ||||
|     D.drawText(`${prog.getBlood()}cc`, new Point(32, 160), bloodColor); | ||||
|   } | ||||
|   | ||||
| @@ -1,12 +1,6 @@ | ||||
| import { Circle, Point, Size } from "./engine/datatypes.ts"; | ||||
| import { DrawPile } from "./drawpile.ts"; | ||||
| import { D, I } from "./engine/public.ts"; | ||||
| import { | ||||
|   BG_INSET, | ||||
|   FG_TEXT, | ||||
|   FG_TEXT_ENDORSED, | ||||
|   FG_TOO_EXPENSIVE, | ||||
| } from "./colors.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| import { Architecture, LoadedNewMap } from "./newmap.ts"; | ||||
| import { FLOOR_CELL_SIZE, GridArt } from "./gridart.ts"; | ||||
| @@ -17,6 +11,7 @@ import { Block3D, Floor3D, World3D } from "./world3d.ts"; | ||||
| import { Floater } from "./floater.ts"; | ||||
| import { displace } from "./physics.ts"; | ||||
| import { getThralls } from "./thralls.ts"; | ||||
| import { C, Microtheme } from "./colors.ts"; | ||||
|  | ||||
| export class HuntMode { | ||||
|   map: LoadedNewMap; | ||||
| @@ -92,6 +87,10 @@ export class HuntMode { | ||||
|     return this.map.get(this.gridifiedPlayer).zoneLabel; | ||||
|   } | ||||
|  | ||||
|   getActiveMicrotheme(): Microtheme | null { | ||||
|     return this.map.get(this.gridifiedPlayer).microtheme; | ||||
|   } | ||||
|  | ||||
|   // draw | ||||
|   update() { | ||||
|     withCamera("Gameplay", () => { | ||||
| @@ -300,11 +299,11 @@ export class HuntMode { | ||||
|           highlighted = false; | ||||
|         } | ||||
|  | ||||
|         let color = BG_INSET; | ||||
|         let color = C.BG_FLOOR; | ||||
|         if (highlighted) { | ||||
|           color = FG_TEXT; | ||||
|           color = C.FG_TEXT; | ||||
|           if (tooExpensive) { | ||||
|             color = FG_TOO_EXPENSIVE; | ||||
|             color = C.FG_TOO_EXPENSIVE; | ||||
|           } | ||||
|         } | ||||
|  | ||||
| @@ -426,7 +425,7 @@ export class HuntMode { | ||||
|       D.fillRect( | ||||
|         cellOffset.offset(new Point(-4, -4)), | ||||
|         new Size(8, 8), | ||||
|         FG_TEXT_ENDORSED, | ||||
|         C.FG_TEXT_ENDORSED, | ||||
|       ); | ||||
|     }); | ||||
|   } | ||||
| @@ -466,3 +465,7 @@ export function getHuntMode() { | ||||
|   } | ||||
|   return active; | ||||
| } | ||||
|  | ||||
| export function maybeGetHuntMode(): HuntMode | null { | ||||
|   return active; | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import { | ||||
|   ThrallRecruitedPickup, | ||||
| } from "./pickups.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| import { MICROTHEME_BLACK } from "./colors.ts"; | ||||
|  | ||||
| const BASIC_PLAN = Grid.createGridFromMultilineString(` | ||||
| ##################### | ||||
| @@ -53,6 +54,7 @@ export function generateManor(): LoadedNewMap { | ||||
|       }; | ||||
|  | ||||
|       cell.zoneLabel = "Manor"; | ||||
|       cell.microtheme = MICROTHEME_BLACK; | ||||
|       switch (BASIC_PLAN.get(xy)) { | ||||
|         case "#": | ||||
|           break; | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import { | ||||
| } from "./pickups.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| import { ItemStage } from "./thralls.ts"; | ||||
| import { Microtheme } from "./colors.ts"; | ||||
|  | ||||
| const WIDTH = 19; | ||||
| const HEIGHT = 19; | ||||
| @@ -68,16 +69,22 @@ class Knife { | ||||
|     this.#region += 1; | ||||
|   } | ||||
|  | ||||
|   carve(point: Point, label?: string) { | ||||
|   carve(point: Point, theme?: Microtheme | null, label?: string) { | ||||
|     this.#regions.set(point, this.#region); | ||||
|     this.map.get(point).architecture = Architecture.Floor; | ||||
|     this.map.get(point).microtheme = theme ?? null; | ||||
|     this.map.get(point).zoneLabel = label ?? null; | ||||
|   } | ||||
|  | ||||
|   carveRoom(room: Rect, protect?: boolean, label?: string) { | ||||
|   carveRoom( | ||||
|     room: Rect, | ||||
|     protect?: boolean, | ||||
|     theme?: Microtheme | null, | ||||
|     label?: string, | ||||
|   ) { | ||||
|     for (let y = room.top.y; y < room.top.y + room.size.h; y++) { | ||||
|       for (let x = room.top.x; x < room.top.x + room.size.w; x++) { | ||||
|         this.carve(new Point(x, y), label); | ||||
|         this.carve(new Point(x, y), theme, label); | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @@ -335,9 +342,24 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { | ||||
|   let ab = mergeRects(a, b); | ||||
|  | ||||
|   knife.startRegion(); | ||||
|   knife.carveRoom(ab, false, vaultTemplate.roomLabels.hall); | ||||
|   knife.carveRoom(c, true, vaultTemplate.roomLabels.backroom); | ||||
|   knife.carveRoom(d, true, vaultTemplate.roomLabels.closet); | ||||
|   knife.carveRoom( | ||||
|     ab, | ||||
|     false, | ||||
|     vaultTemplate.microtheme(), | ||||
|     vaultTemplate.roomLabels.hall, | ||||
|   ); | ||||
|   knife.carveRoom( | ||||
|     c, | ||||
|     true, | ||||
|     vaultTemplate.microtheme(), | ||||
|     vaultTemplate.roomLabels.backroom, | ||||
|   ); | ||||
|   knife.carveRoom( | ||||
|     d, | ||||
|     true, | ||||
|     vaultTemplate.microtheme(), | ||||
|     vaultTemplate.roomLabels.closet, | ||||
|   ); | ||||
|  | ||||
|   // now place standard pickups | ||||
|   for (let dy = 0; dy < ab.size.h; dy++) { | ||||
| @@ -391,7 +413,11 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { | ||||
|       if (check != null) { | ||||
|         knife.map.get(connector).pickup = new LockPickup(check); | ||||
|       } | ||||
|       knife.carve(connector, vaultTemplate.roomLabels.backroom); | ||||
|       knife.carve( | ||||
|         connector, | ||||
|         vaultTemplate.microtheme(), | ||||
|         vaultTemplate.roomLabels.backroom, | ||||
|       ); | ||||
|     } | ||||
|     if (mergeRects(c, d).contains(connector)) { | ||||
|       // TODO: Put check 2 here | ||||
| @@ -399,7 +425,11 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { | ||||
|       if (check != null) { | ||||
|         knife.map.get(connector).pickup = new LockPickup(check); | ||||
|       } | ||||
|       knife.carve(connector, vaultTemplate.roomLabels.closet); | ||||
|       knife.carve( | ||||
|         connector, | ||||
|         vaultTemplate.microtheme(), | ||||
|         vaultTemplate.roomLabels.closet, | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -445,7 +475,7 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { | ||||
| } | ||||
|  | ||||
| function carveStaircase(knife: Knife, room: Rect, ix: number) { | ||||
|   carveRoom(knife, room, "Stairwell"); | ||||
|   carveRoom(knife, room, null, "Stairwell"); | ||||
|  | ||||
|   let x = Math.floor(room.top.x + room.size.w / 2); | ||||
|   let y = Math.floor(room.top.y + room.size.h / 2); | ||||
| @@ -460,9 +490,14 @@ function carveStaircase(knife: Knife, room: Rect, ix: number) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function carveRoom(knife: Knife, room: Rect, label?: string) { | ||||
| function carveRoom( | ||||
|   knife: Knife, | ||||
|   room: Rect, | ||||
|   theme?: Microtheme | null, | ||||
|   label?: string, | ||||
| ) { | ||||
|   knife.startRegion(); | ||||
|   knife.carveRoom(room, false, label); | ||||
|   knife.carveRoom(room, false, theme, label); | ||||
|  | ||||
|   for (let dy = 0; dy < Math.ceil(room.size.h / 2); dy++) { | ||||
|     for (let dx = 0; dx < Math.ceil(room.size.w / 2); dx++) { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { Grid, Point, Size } from "./engine/datatypes.ts"; | ||||
| import { Pickup } from "./pickups.ts"; | ||||
| import { Skill } from "./datatypes.ts"; | ||||
| import { Microtheme } from "./colors.ts"; | ||||
|  | ||||
| export enum Architecture { | ||||
|   Wall, | ||||
| @@ -36,6 +37,7 @@ export class LoadedNewMap { | ||||
|   #provinces: Grid<string | null>; // TODO: Does this just duplicate zoneLabels | ||||
|   #revealed: Grid<boolean>; | ||||
|   #zoneLabels: Grid<string | null>; | ||||
|   #microthemes: Grid<Microtheme | null>; | ||||
|  | ||||
|   constructor(id: string, size: Size) { | ||||
|     this.#id = id; | ||||
| @@ -47,6 +49,7 @@ export class LoadedNewMap { | ||||
|     this.#provinces = new Grid<string | null>(size, () => null); | ||||
|     this.#revealed = new Grid<boolean>(size, () => false); | ||||
|     this.#zoneLabels = new Grid<string | null>(size, () => null); | ||||
|     this.#microthemes = new Grid<Microtheme | null>(size, () => null); | ||||
|   } | ||||
|  | ||||
|   set entrance(point: Point) { | ||||
| @@ -116,6 +119,14 @@ export class LoadedNewMap { | ||||
|     return this.#zoneLabels.get(point); | ||||
|   } | ||||
|  | ||||
|   setMicrotheme(point: Point, value: Microtheme | null) { | ||||
|     this.#microthemes.set(point, value); | ||||
|   } | ||||
|  | ||||
|   getMicrotheme(point: Point): Microtheme | null { | ||||
|     return this.#microthemes.get(point); | ||||
|   } | ||||
|  | ||||
|   isConnected(): boolean { | ||||
|     const size = this.#size; | ||||
|     let reached = new Grid<boolean>(size, () => false); | ||||
| @@ -216,6 +227,13 @@ export class CellView { | ||||
|     return this.#map.getZoneLabel(this.#point); | ||||
|   } | ||||
|  | ||||
|   set microtheme(value: Microtheme | null) { | ||||
|     this.#map.setMicrotheme(this.#point, value); | ||||
|   } | ||||
|   get microtheme(): Microtheme | null { | ||||
|     return this.#map.getMicrotheme(this.#point); | ||||
|   } | ||||
|  | ||||
|   copyFrom(cell: CellView) { | ||||
|     this.architecture = cell.architecture; | ||||
|     this.pickup = cell.pickup; | ||||
|   | ||||
| @@ -15,7 +15,6 @@ import { GridArt } from "./gridart.ts"; | ||||
| import { getCheckModal } from "./checkmodal.ts"; | ||||
| import { Point, Size } from "./engine/datatypes.ts"; | ||||
| import { choose } from "./utils.ts"; | ||||
| import { FG_BOLD, FG_TEXT, SWATCH_EXP, SWATCH_STAT } from "./colors.ts"; | ||||
| import { Block3D } from "./world3d.ts"; | ||||
| import { DrawPile } from "./drawpile.ts"; | ||||
| import { Floater } from "./floater.ts"; | ||||
| @@ -27,6 +26,7 @@ import { | ||||
|   sndRewardFor, | ||||
|   sndRewardHuge, | ||||
| } from "./sounds.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| export type Pickup = | ||||
|   | LockPickup | ||||
| @@ -211,9 +211,9 @@ export class StatPickupCallbacks { | ||||
|  | ||||
|   getBlock(progress: number) { | ||||
|     return new Block3D( | ||||
|       progress > 0.6 ? FG_BOLD : SWATCH_STAT[this.#stat][1], | ||||
|       progress > 0.6 ? FG_TEXT : SWATCH_STAT[this.#stat][0], | ||||
|       progress > 0.6 ? FG_BOLD : SWATCH_STAT[this.#stat][1], | ||||
|       progress > 0.6 ? C.FG_BOLD : C.SWATCH_STAT[this.#stat][1], | ||||
|       progress > 0.6 ? C.FG_TEXT : C.SWATCH_STAT[this.#stat][0], | ||||
|       progress > 0.6 ? C.FG_BOLD : C.SWATCH_STAT[this.#stat][1], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @@ -258,9 +258,9 @@ export class ExperiencePickupCallbacks { | ||||
|  | ||||
|   getBlock(progress: number) { | ||||
|     return new Block3D( | ||||
|       progress > 0.6 ? FG_BOLD : SWATCH_EXP[1], | ||||
|       progress > 0.6 ? FG_TEXT : SWATCH_EXP[0], | ||||
|       progress > 0.6 ? FG_BOLD : SWATCH_EXP[1], | ||||
|       progress > 0.6 ? C.FG_BOLD : C.SWATCH_EXP[1], | ||||
|       progress > 0.6 ? C.FG_TEXT : C.SWATCH_EXP[0], | ||||
|       progress > 0.6 ? C.FG_BOLD : C.SWATCH_EXP[1], | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @@ -608,7 +608,7 @@ export class ThrallCollectionPlatePickup { | ||||
|         D.drawRect( | ||||
|           gridArt.project(0).offset(new Point(-18, -18)), | ||||
|           new Size(36, 36), | ||||
|           FG_TEXT, | ||||
|           C.FG_TEXT, | ||||
|         ); | ||||
|       } else { | ||||
|         D.drawSprite(data.sprite, gridArt.project(2), 3, { | ||||
|   | ||||
| @@ -2,16 +2,11 @@ import { getPartLocation, withCamera } from "./layout.ts"; | ||||
| import { AlignX, Point, Rect, Size } from "./engine/datatypes.ts"; | ||||
| import { DrawPile } from "./drawpile.ts"; | ||||
| import { D } from "./engine/public.ts"; | ||||
| import { | ||||
|   BG_INSET, | ||||
|   FG_BOLD, | ||||
|   FG_TEXT_DISABLED, | ||||
|   FG_TEXT_ENDORSED, | ||||
| } from "./colors.ts"; | ||||
| import { addButton } from "./button.ts"; | ||||
| import { getSkills } from "./skills.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| import { Skill, SkillData } from "./datatypes.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| export class SkillsModal { | ||||
|   #drawpile: DrawPile; | ||||
| @@ -50,7 +45,7 @@ export class SkillsModal { | ||||
|     this.#drawpile.clear(); | ||||
|     let size = this.#size; | ||||
|     this.#drawpile.add(0, () => { | ||||
|       D.fillRect(new Point(-4, -4), size.add(new Size(8, 8)), BG_INSET); | ||||
|       D.fillRect(new Point(-4, -4), size.add(new Size(8, 8)), C.BG_UI); | ||||
|     }); | ||||
|  | ||||
|     // draw skills | ||||
| @@ -71,24 +66,24 @@ export class SkillsModal { | ||||
|         0, | ||||
|         (hover) => { | ||||
|           // two column layout | ||||
|           let [bg, fg] = [BG_INSET, FG_BOLD]; | ||||
|           let [bg, fg] = [C.BG_UI, C.FG_BOLD]; | ||||
|  | ||||
|           let overpriced = | ||||
|             getSkills().computeCost(skill) > | ||||
|             getPlayerProgress().getExperience(); | ||||
|           let atMinimum = getSkills().isAtMinimum(skill); | ||||
|           if (overpriced) { | ||||
|             fg = FG_TEXT_DISABLED; | ||||
|             fg = C.FG_TEXT_DISABLED; | ||||
|           } else if (atMinimum) { | ||||
|             fg = FG_TEXT_ENDORSED; | ||||
|             fg = C.FG_TEXT_ENDORSED; | ||||
|           } | ||||
|  | ||||
|           if (selected || hover) { | ||||
|             [bg, fg] = [FG_BOLD, BG_INSET]; | ||||
|             [bg, fg] = [C.FG_BOLD, C.BG_UI]; | ||||
|             if (overpriced) { | ||||
|               // still use the same BG, for contrast | ||||
|             } else if (atMinimum) { | ||||
|               bg = FG_TEXT_ENDORSED; | ||||
|               bg = C.FG_TEXT_ENDORSED; | ||||
|             } | ||||
|           } | ||||
|           D.fillRect(skillRect.top, skillRect.size, bg); | ||||
| @@ -117,8 +112,8 @@ export class SkillsModal { | ||||
|       let remainingWidth = size.w - 160; | ||||
|  | ||||
|       this.#drawpile.add(0, () => { | ||||
|         D.fillRect(new Point(160, 0), new Size(remainingWidth, 96), FG_BOLD); | ||||
|         D.drawText(createFullDescription(data), new Point(164, 0), BG_INSET, { | ||||
|         D.fillRect(new Point(160, 0), new Size(remainingWidth, 96), C.FG_BOLD); | ||||
|         D.drawText(createFullDescription(data), new Point(164, 0), C.BG_UI, { | ||||
|           forceWidth: remainingWidth - 8, | ||||
|         }); | ||||
|       }); | ||||
|   | ||||
| @@ -268,7 +268,7 @@ export let thrallBat = table.add({ | ||||
|     options: [ | ||||
|       { | ||||
|         skill: () => party1, // Rave | ||||
|         locked: "Act crazy to get her attention", | ||||
|         locked: "Act weird to get her attention", | ||||
|         failure: '"I -- you -- you know we\'re not being filmed, right?"', | ||||
|         unlockable: "Flash your eyes like a TV camera", | ||||
|         success: | ||||
|   | ||||
| @@ -29,8 +29,18 @@ import { | ||||
|   thrallStare, | ||||
|   thrallStealth, | ||||
| } from "./thralls.ts"; | ||||
| import { | ||||
|   Microtheme, | ||||
|   MICROTHEME_GREEN, | ||||
|   MICROTHEME_NEON, | ||||
|   MICROTHEME_PINK, | ||||
|   MICROTHEME_PURPLE_TAN, | ||||
|   MICROTHEME_RED, | ||||
|   MICROTHEME_TEAL, | ||||
| } from "./colors.ts"; | ||||
|  | ||||
| export type VaultTemplate = { | ||||
|   microtheme: () => Microtheme | null; | ||||
|   stats: { primary: Stat; secondary: Stat }; | ||||
|   roomLabels: { | ||||
|     hall: string; | ||||
| @@ -45,6 +55,7 @@ export type VaultTemplate = { | ||||
| export const standardVaultTemplates: VaultTemplate[] = [ | ||||
|   { | ||||
|     // zoo | ||||
|     microtheme: () => MICROTHEME_GREEN, | ||||
|     stats: { primary: "AGI", secondary: "PSI" }, | ||||
|     roomLabels: { | ||||
|       hall: "Zoo", | ||||
| @@ -97,6 +108,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ | ||||
|   }, | ||||
|   { | ||||
|     // blood bank | ||||
|     microtheme: () => MICROTHEME_RED, | ||||
|     stats: { primary: "AGI", secondary: "INT" }, | ||||
|     roomLabels: { | ||||
|       hall: "Blood Bank", | ||||
| @@ -148,6 +160,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ | ||||
|   }, | ||||
|   { | ||||
|     // coffee shop | ||||
|     microtheme: () => MICROTHEME_PINK, | ||||
|     stats: { primary: "PSI", secondary: "CHA" }, | ||||
|     roomLabels: { | ||||
|       hall: "Coffee Shop", | ||||
| @@ -200,6 +213,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ | ||||
|   }, | ||||
|   { | ||||
|     // optometrist | ||||
|     microtheme: () => MICROTHEME_TEAL, | ||||
|     stats: { primary: "PSI", secondary: "PSI" }, | ||||
|     roomLabels: { | ||||
|       hall: "Optometrist", | ||||
| @@ -252,6 +266,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ | ||||
|   }, | ||||
|   { | ||||
|     // club, | ||||
|     microtheme: () => MICROTHEME_NEON, | ||||
|     stats: { primary: "CHA", secondary: "PSI" }, | ||||
|     roomLabels: { | ||||
|       hall: "Nightclub", | ||||
| @@ -304,6 +319,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ | ||||
|   }, | ||||
|   { | ||||
|     // library | ||||
|     microtheme: () => MICROTHEME_PURPLE_TAN, | ||||
|     stats: { primary: "INT", secondary: "CHA" }, | ||||
|     roomLabels: { | ||||
|       hall: "Library", | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import { D, I } from "./engine/public.ts"; | ||||
| import { AlignX, AlignY, Point } from "./engine/datatypes.ts"; | ||||
| import { FG_BOLD } from "./colors.ts"; | ||||
| import { withCamera } from "./layout.ts"; | ||||
| import { VNScene, VNSceneMessage, VNScenePart } from "./vnscene.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| const WIDTH = 384; | ||||
| const HEIGHT = 384; | ||||
| @@ -119,11 +119,16 @@ class SceneMessageCathexis { | ||||
|   } | ||||
|  | ||||
|   draw() { | ||||
|     D.drawText(this.#message.text, new Point(WIDTH / 2, HEIGHT / 2), FG_BOLD, { | ||||
|     D.drawText( | ||||
|       this.#message.text, | ||||
|       new Point(WIDTH / 2, HEIGHT / 2), | ||||
|       C.FG_BOLD, | ||||
|       { | ||||
|         alignX: AlignX.Center, | ||||
|         alignY: AlignY.Middle, | ||||
|         forceWidth: WIDTH, | ||||
|     }); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,7 @@ | ||||
| import { Color, Grid, Point, Rect, Size } from "./engine/datatypes.ts"; | ||||
| import { DrawPile } from "./drawpile.ts"; | ||||
| import { GridArt } from "./gridart.ts"; | ||||
| import { | ||||
|   BG_CEILING, | ||||
|   BG_WALL_OR_UNREVEALED, | ||||
|   FG_BOLD, | ||||
|   FG_TEXT, | ||||
| } from "./colors.ts"; | ||||
| import { C } from "./colors.ts"; | ||||
|  | ||||
| export class World3D { | ||||
|   #grid: Grid<Element3D>; | ||||
| @@ -27,7 +22,7 @@ export class World3D { | ||||
|  | ||||
|     if (here == null) { | ||||
|       drawpile.add(OFFSET_TOP, () => { | ||||
|         gridArt.drawCeiling(BG_CEILING); | ||||
|         gridArt.drawCeiling(C.BG_CEILING); | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
| @@ -135,6 +130,6 @@ export class Block3D { | ||||
|   } | ||||
|  | ||||
|   static standardWall(): Block3D { | ||||
|     return new Block3D(FG_BOLD, FG_TEXT, BG_WALL_OR_UNREVEALED); | ||||
|     return new Block3D(C.BG_OUTERWALL, C.BG_INNERWALL, C.BG_WALL_OR_UNREVEALED); | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user