Visible costing in many places
This commit is contained in:
		| @@ -1,6 +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} from "./colors.ts"; | ||||
| import {BG_INSET, FG_BOLD, FG_TEXT, FG_TEXT_DISABLED, FG_TEXT_ENDORSED} from "./colors.ts"; | ||||
| import { D } from "./engine/public.ts"; | ||||
|  | ||||
| export function addButton( | ||||
| @@ -9,6 +9,9 @@ export function addButton( | ||||
|   rect: Rect, | ||||
|   enabled: boolean, | ||||
|   cbClick: () => void, | ||||
|   options?: { | ||||
|     endorse?: boolean | ||||
|   } | ||||
| ) { | ||||
|   let padding = 2; | ||||
|   let topLeft = rect.top; | ||||
| @@ -26,6 +29,12 @@ export function addButton( | ||||
|       if (!enabled) { | ||||
|         fgLabel = FG_TEXT_DISABLED; | ||||
|       } | ||||
|  | ||||
|       if (enabled && options?.endorse) { | ||||
|         fg = FG_TEXT_ENDORSED; | ||||
|         fgLabel = FG_TEXT_ENDORSED; | ||||
|       } | ||||
|  | ||||
|       if (hover) { | ||||
|         [bg, fg, fgLabel] = [FG_BOLD, BG_INSET, BG_INSET]; | ||||
|       } | ||||
|   | ||||
| @@ -6,6 +6,7 @@ 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; | ||||
|   | ||||
| @@ -4,10 +4,14 @@ import { withCamera } from "./layout.ts"; | ||||
| import { getSkillsModal } from "./skillsmodal.ts"; | ||||
| import { addButton } from "./button.ts"; | ||||
| import { getSleepModal } from "./sleepmodal.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
| import {getSkills} from "./skills.ts"; | ||||
|  | ||||
| type Button = { | ||||
|   label: string; | ||||
|   cbClick: () => void; | ||||
|   enabled: boolean; | ||||
|   endorse: boolean; | ||||
| }; | ||||
|  | ||||
| export class Hotbar { | ||||
| @@ -33,6 +37,8 @@ export class Hotbar { | ||||
|       cbClick: () => { | ||||
|         getSkillsModal().setShown(true); | ||||
|       }, | ||||
|       enabled: getPlayerProgress().getAvailableSkills().length > 0, | ||||
|       endorse: getPlayerProgress().anyAffordableSkillsAtMinimum(), | ||||
|     }); | ||||
|     /* | ||||
|     buttons.push({ | ||||
| @@ -44,6 +50,8 @@ export class Hotbar { | ||||
|       cbClick: () => { | ||||
|         getSleepModal().setShown(true); | ||||
|       }, | ||||
|       enabled: true, | ||||
|       endorse: getPlayerProgress().getBlood() < 100, | ||||
|     }); | ||||
|     return buttons; | ||||
|   } | ||||
| @@ -65,8 +73,9 @@ export class Hotbar { | ||||
|         this.#drawpile, | ||||
|         b.label, | ||||
|         new Rect(new Point(x, 0), cellSize), | ||||
|         true, | ||||
|         b.enabled, | ||||
|         b.cbClick, | ||||
|         {endorse: b.endorse} | ||||
|       ); | ||||
|       x += cellSize.w; | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { D } from "./engine/public.ts"; | ||||
| import { Point, Size } from "./engine/datatypes.ts"; | ||||
| import {BG_OUTER, FG_BOLD, FG_TEXT, FG_TOO_EXPENSIVE} from "./colors.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"; | ||||
| @@ -42,6 +42,7 @@ export class Hud { | ||||
|     D.drawText("BLD", new Point(0, 160), FG_BOLD); | ||||
|     let bloodAmount = prog.getBlood(); | ||||
|     let bloodColor = FG_TEXT; | ||||
|     if (bloodAmount > 2000) { bloodColor = FG_TEXT_ENDORSED; } | ||||
|     if (bloodAmount < 100) { bloodColor = FG_TOO_EXPENSIVE; } | ||||
|     D.drawText(`${prog.getBlood()}cc`, new Point(32, 160), bloodColor); | ||||
|   } | ||||
|   | ||||
| @@ -274,6 +274,18 @@ export class PlayerProgress { | ||||
|     } | ||||
|     return ItemStage.Untouched; | ||||
|   } | ||||
|  | ||||
|   anyAffordableSkillsAtMinimum() { | ||||
|     let skills = this.getAvailableSkills(); | ||||
|     for (let skill of skills.values()) { | ||||
|       if (getSkills().isAtMinimum(skill)) { | ||||
|         if (getPlayerProgress().getExperience() > getSkills().computeCost(skill)) { | ||||
|           return true; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| } | ||||
|  | ||||
| let active: PlayerProgress | null = null; | ||||
|   | ||||
| @@ -68,6 +68,12 @@ class SkillsTable { | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   isAtMinimum(skill: Skill) { | ||||
|     let minimumCost = this.get(skill).governing.cost | ||||
|     let currentCost = this.computeCost(skill); | ||||
|     return currentCost <= minimumCost; | ||||
|   } | ||||
| } | ||||
|  | ||||
| function geomInterpolate( | ||||
|   | ||||
| @@ -2,7 +2,7 @@ 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 } from "./colors.ts"; | ||||
| import {BG_INSET, FG_BOLD, FG_TEXT, FG_TEXT_DISABLED, FG_TEXT_ENDORSED} from "./colors.ts"; | ||||
| import { addButton } from "./button.ts"; | ||||
| import { getSkills } from "./skills.ts"; | ||||
| import { getPlayerProgress } from "./playerprogress.ts"; | ||||
| @@ -54,7 +54,7 @@ export class SkillsModal { | ||||
|     this.#fixSkillSelection(availableSkills); | ||||
|  | ||||
|     let y = 0; | ||||
|     for (let skill of availableSkills) { | ||||
|     availableSkills.forEach((skill) => { | ||||
|       let data = getSkills().get(skill); | ||||
|       let cost = getSkills().computeCost(skill); | ||||
|       let y_ = y; | ||||
| @@ -66,9 +66,23 @@ export class SkillsModal { | ||||
|         0, | ||||
|         (hover) => { | ||||
|           // two column layout | ||||
|           let [bg, fg] = [BG_INSET, FG_TEXT]; | ||||
|           let [bg, fg] = [BG_INSET, FG_BOLD]; | ||||
|  | ||||
|           let overpriced = getSkills().computeCost(skill) > getPlayerProgress().getExperience(); | ||||
|           let atMinimum = getSkills().isAtMinimum(skill); | ||||
|           if (overpriced) { | ||||
|             fg = FG_TEXT_DISABLED; | ||||
|           } else if (atMinimum) { | ||||
|             fg = FG_TEXT_ENDORSED; | ||||
|           } | ||||
|  | ||||
|           if (selected || hover) { | ||||
|             [bg, fg] = [FG_BOLD, BG_INSET]; | ||||
|             if (overpriced) { | ||||
|               // still use the same BG, for contrast | ||||
|             } else if (atMinimum) { | ||||
|               bg = FG_TEXT_ENDORSED; | ||||
|             } | ||||
|           } | ||||
|           D.fillRect(skillRect.top, skillRect.size, bg); | ||||
|           D.drawText(data.profile.name, new Point(4, y_), fg); | ||||
| @@ -83,7 +97,7 @@ export class SkillsModal { | ||||
|         }, | ||||
|       ); | ||||
|       y += 16; | ||||
|     } | ||||
|     }); | ||||
|  | ||||
|     // add skill description | ||||
|     let selection = this.#skillSelection; | ||||
| @@ -107,21 +121,27 @@ export class SkillsModal { | ||||
|       ); | ||||
|       let canAfford = getPlayerProgress().getExperience() >= cost; | ||||
|       let caption = `Learn ${data.profile.name}`; | ||||
|       let endorse = getSkills().isAtMinimum(selection); | ||||
|       if (!canAfford) { | ||||
|         caption = `Can't Afford`; | ||||
|         endorse = false; | ||||
|       } | ||||
|  | ||||
|       addButton(this.#drawpile, caption, drawButtonRect, canAfford, () => { | ||||
|         getPlayerProgress().spendExperience(cost); | ||||
|         getPlayerProgress().learnSkill(selection); | ||||
|       }, { | ||||
|         endorse | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // add close button | ||||
|     let endorseBack = availableSkills.length == 0; | ||||
|     let closeRect = new Rect(new Point(0, 96), new Size(160, 32)); | ||||
|     addButton(this.#drawpile, "Back", closeRect, true, () => { | ||||
|       this.setShown(false); | ||||
|     }); | ||||
|     }, {endorse: endorseBack}); | ||||
|     this.#drawpile.executeOnClick(); | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user