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