From 3a6590a9421488d36c5db0154f313ca3960797bb Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Mon, 17 Feb 2025 14:17:50 -0800 Subject: [PATCH] Map refactor -- thralls are clickable --- src/huntmode.ts | 107 ++-------------- src/mapgen.ts | 28 +++-- src/newmap.ts | 104 +--------------- src/newmaps/bloodBank/architecture.txt | 11 -- src/newmaps/bloodBank/map.ts | 27 ---- src/newmaps/bloodBank/provinces.txt | 11 -- src/newmaps/club/architecture.txt | 11 -- src/newmaps/club/map.ts | 27 ---- src/newmaps/club/provinces.txt | 11 -- src/newmaps/coffeeShop/architecture.txt | 11 -- src/newmaps/coffeeShop/map.ts | 27 ---- src/newmaps/coffeeShop/provinces.txt | 11 -- src/newmaps/hub/map.ts | 63 ---------- src/newmaps/hub/metamap.txt | 33 ----- src/newmaps/hub/overworld.png | Bin 912 -> 0 bytes src/newmaps/library/architecture.txt | 11 -- src/newmaps/library/map.ts | 27 ---- src/newmaps/library/provinces.txt | 11 -- src/newmaps/manor/architecture.txt | 11 -- src/newmaps/manor/map.ts | 27 ---- src/newmaps/manor/provinces.txt | 11 -- src/newmaps/optometrist/architecture.txt | 11 -- src/newmaps/optometrist/map.ts | 27 ---- src/newmaps/optometrist/provinces.txt | 11 -- src/newmaps/zoo/architecture.txt | 11 -- src/newmaps/zoo/map.ts | 83 ------------- src/newmaps/zoo/provinces.txt | 11 -- src/pickups.ts | 150 +++++++++++++++++++++++ src/thralls.ts | 4 + src/vaulttemplate.ts | 8 ++ 30 files changed, 196 insertions(+), 700 deletions(-) delete mode 100644 src/newmaps/bloodBank/architecture.txt delete mode 100644 src/newmaps/bloodBank/map.ts delete mode 100644 src/newmaps/bloodBank/provinces.txt delete mode 100644 src/newmaps/club/architecture.txt delete mode 100644 src/newmaps/club/map.ts delete mode 100644 src/newmaps/club/provinces.txt delete mode 100644 src/newmaps/coffeeShop/architecture.txt delete mode 100644 src/newmaps/coffeeShop/map.ts delete mode 100644 src/newmaps/coffeeShop/provinces.txt delete mode 100644 src/newmaps/hub/map.ts delete mode 100644 src/newmaps/hub/metamap.txt delete mode 100644 src/newmaps/hub/overworld.png delete mode 100644 src/newmaps/library/architecture.txt delete mode 100644 src/newmaps/library/map.ts delete mode 100644 src/newmaps/library/provinces.txt delete mode 100644 src/newmaps/manor/architecture.txt delete mode 100644 src/newmaps/manor/map.ts delete mode 100644 src/newmaps/manor/provinces.txt delete mode 100644 src/newmaps/optometrist/architecture.txt delete mode 100644 src/newmaps/optometrist/map.ts delete mode 100644 src/newmaps/optometrist/provinces.txt delete mode 100644 src/newmaps/zoo/architecture.txt delete mode 100644 src/newmaps/zoo/map.ts delete mode 100644 src/newmaps/zoo/provinces.txt create mode 100644 src/pickups.ts diff --git a/src/huntmode.ts b/src/huntmode.ts index 103dd39..106a3bc 100644 --- a/src/huntmode.ts +++ b/src/huntmode.ts @@ -1,8 +1,7 @@ import {Point} from "./engine/datatypes.ts"; -import {ALL_STATS, Stat} from "./datatypes.ts"; import {DrawPile} from "./drawpile.ts"; import {D} from "./engine/public.ts"; -import {sprLadder, sprLock, sprRaccoonWalking, sprResourcePickup, sprStatPickup} from "./sprites.ts"; +import {sprRaccoonWalking} from "./sprites.ts"; import { BG_INSET, BG_WALL_OR_UNREVEALED, @@ -14,9 +13,7 @@ import {getPlayerProgress} from "./playerprogress.ts"; import {Architecture, LoadedNewMap} from "./newmap.ts"; import {FLOOR_CELL_SIZE, GridArt} from "./gridart.ts"; import {shadowcast} from "./shadowcast.ts"; -import {generateMap} from "./mapgen.ts"; import {getCheckModal} from "./checkmodal.ts"; -import {standardVaultTemplates} from "./vaulttemplate.ts"; export class HuntMode { @@ -47,31 +44,10 @@ export class HuntMode { let cell = this.map.get(this.player); let pickup = cell.pickup; - if (pickup != null) { - switch (pickup) { - case "AGI": - case "INT": - case "CHA": - case "PSI": - getPlayerProgress().add(pickup, 1); - getPlayerProgress().purloinItem(); - break; - case "EXP": - getPlayerProgress().addExperience(250); - getPlayerProgress().purloinItem(); - break; - case "Ladder": - getPlayerProgress().addBlood(1000); - initHuntMode(new HuntMode(this.depth + 1, generateMap())); - break; - default: - throw `not sure how to handle ${pickup}` - } - cell.pickup = null; - } + if (pickup != null) { cell.pickup = null; } } - #computeCostToMoveTo(mapPosition: Point): number | null { + #computeCostToClick(mapPosition: Point): number | null { let present = this.map.get(mapPosition); if (present.architecture != Architecture.Floor) { @@ -86,9 +62,8 @@ export class HuntMode { if (dist != 1) { return null; } let pickup = present.pickup; - if (pickup == "Ladder") { return 0; } if (pickup == null) { return 10; } - return 100; // any other pickup (EXP, stats, etc) + return pickup.computeCostToClick() } movePlayerTo(newPosition: Point) { @@ -131,7 +106,8 @@ export class HuntMode { [this.player.x, this.player.y], ([x, y]: [number, number]): boolean => { let cell = this.map.get(new Point(x, y)); - return cell.architecture == Architecture.Wall || ALL_STATS.indexOf(cell.pickup as Stat) != -1; + let pickup = cell.pickup; + return cell.architecture == Architecture.Wall || (pickup != null && pickup.isObstructive()); }, ([x, y]: [number, number]) => { let dx = x - this.player.x; @@ -180,37 +156,23 @@ export class HuntMode { return; } - let check = cellData.check; + let pickup = cellData.pickup; // draw inset zone - let cost = this.#computeCostToMoveTo(mapPosition); + let cost = this.#computeCostToClick(mapPosition); this.drawpile.addClickable( OFFSET_FLOOR, (hover: boolean) => { gridArt.drawFloor(hover ? FG_TEXT : BG_INSET) - - if (cellData.pickup == "Ladder") { - D.drawSprite(sprLadder, gridArt.project(0.0), 0, { - xScale: 2.0, - yScale: 2.0, - }) - } - - /* - // TODO: Stairs - if (cellData.content.type == "stairs") { - // draw ladder if applicable - D.drawSprite(sprLadder, cellTopLeft, 0, {xScale: 3, yScale: 3}); - } - */ + pickup?.drawFloor(gridArt); }, gridArt.floorRect, cost != null && cost <= getPlayerProgress().getBlood(), () => { - if (check != null) { - getCheckModal().show(check, () => cellData.check = null); + if (pickup?.onClick(cellData)) { return; } + if (cost != null) { getPlayerProgress().spendBlood(cost); this.movePlayerTo(mapPosition) @@ -219,18 +181,8 @@ export class HuntMode { } ); - if (check != null) { - this.drawpile.add( - OFFSET_AIR, - () => { - for (let z = 0; z < 5; z += 0.25) { - D.drawSprite(sprLock, gridArt.project(z), 0, { - xScale: 2.0, - yScale: 2.0, - }) - } - } - ) + if (pickup != null) { + this.drawpile.add(OFFSET_AIR, () => { pickup.drawInAir(gridArt); }); } const isRevealedBlock = (dx: number, dy: number) => { @@ -266,39 +218,6 @@ export class HuntMode { this.drawpile.add(OFFSET_AIR, () => { gridArt.drawWallRight(FG_BOLD); }) this.drawpile.add(OFFSET_TOP_OF_TOP, () => { gridArt.drawMouldingRight(FG_MOULDING); }) } - - - let pickup = cellData.pickup; - if (pickup != null) { - let statIndex = ALL_STATS.indexOf(pickup as Stat); - if (statIndex != -1) { - this.drawpile.add(OFFSET_AIR, () => { - D.drawSprite( - sprStatPickup, - gridArt.project(5), - statIndex, - { - xScale: 2, - yScale: 2, - } - ) - }); - } - - if (pickup == "EXP") { - this.drawpile.add(OFFSET_AIR, () => { - D.drawSprite( - sprResourcePickup, - gridArt.project(0.0).offset(new Point(0, -16)), - 0, - { - xScale: 2, - yScale: 2, - } - ); - }); - } - } } #drawPlayer(globalOffset: Point) { diff --git a/src/mapgen.ts b/src/mapgen.ts index 3025071..759fdc6 100644 --- a/src/mapgen.ts +++ b/src/mapgen.ts @@ -3,6 +3,7 @@ import {Grid, Point, Rect, Size} from "./engine/datatypes.ts"; import {choose, shuffle} from "./utils.ts"; import {standardVaultTemplates, VaultTemplate} from "./vaulttemplate.ts"; import {ALL_STATS} from "./datatypes.ts"; +import {ExperiencePickup, LadderPickup, LockPickup, StatPickup, ThrallPickup} from "./pickups.ts"; const WIDTH = 19; const HEIGHT = 19; @@ -242,21 +243,21 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { if (!(a.contains(xy) || b.contains(xy))) { stat = vaultTemplate.stats.secondary; } - knife.map.get(xy).pickup = stat; + knife.map.get(xy).pickup = new StatPickup(stat); } } for (let dy = 0; dy < c.size.h; dy++) { for (let dx = 0; dx < c.size.w; dx++) { let xy = c.top.offset(new Point(dx, dy)); - knife.map.get(xy).pickup = vaultTemplate.stats.primary; + knife.map.get(xy).pickup = new StatPickup(vaultTemplate.stats.primary); } } for (let dy = 0; dy < d.size.h; dy++) { for (let dx = 0; dx < d.size.w; dx++) { let xy = d.top.offset(new Point(dx, dy)); - knife.map.get(xy).pickup = vaultTemplate.stats.primary; + knife.map.get(xy).pickup = new StatPickup(vaultTemplate.stats.primary); } } @@ -274,7 +275,7 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { // TODO: Put check 1 here let check = vaultTemplate.checks[0]; if (check != null) { - knife.map.setCheck(connector, check); + knife.map.get(connector).pickup = new LockPickup(check); } knife.carve(connector) } @@ -282,7 +283,7 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { // TODO: Put check 2 here let check = vaultTemplate.checks[1]; if (check != null) { - knife.map.setCheck(connector, check) + knife.map.get(connector).pickup = new LockPickup(check); } knife.carve(connector) } @@ -297,17 +298,20 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { ] for (let offset of goodies.values()) { let goodie = room.top.offset(offset); + let cell = knife.map.get(goodie); if (a.contains(goodie)) { // TODO: Place the zone's NPC here + let thrall = vaultTemplate.thrall(); + cell.pickup = new ThrallPickup(thrall); } if (b.contains(goodie)) { - knife.map.setPickup(goodie, "EXP"); + cell.pickup = new ExperiencePickup(); } if (c.contains(goodie)) { - knife.map.setPickup(goodie, "EXP"); + cell.pickup = new ExperiencePickup(); // TODO: Fill this room with the common item for this room } @@ -329,7 +333,7 @@ function carveStaircase(knife: Knife, room: Rect, ix: number) { knife.map.entrance = center; knife.map.get(center).pickup = null; } else { - knife.map.get(center).pickup = "Ladder"; + knife.map.get(center).pickup = new LadderPickup(); } } @@ -348,10 +352,10 @@ function carveRoom(knife: Knife, room: Rect) { let xy2 = room.top.offset(new Point(dx, room.size.h - dy - 1)); let xy3 = room.top.offset(new Point(room.size.w - dx - 1, room.size.h - dy - 1)); let stat = choose(ALL_STATS); - knife.map.get(xy0).pickup = stat; - knife.map.get(xy1).pickup = stat; - knife.map.get(xy2).pickup = stat; - knife.map.get(xy3).pickup = stat; + knife.map.get(xy0).pickup = new StatPickup(stat); + knife.map.get(xy1).pickup = new StatPickup(stat); + knife.map.get(xy2).pickup = new StatPickup(stat); + knife.map.get(xy3).pickup = new StatPickup(stat); } } } diff --git a/src/newmap.ts b/src/newmap.ts index d235044..e3c8131 100644 --- a/src/newmap.ts +++ b/src/newmap.ts @@ -1,25 +1,9 @@ -import {Resource, Skill, Stat} from "./datatypes.ts"; import {Grid, Point, Size} from "./engine/datatypes.ts"; -import {choose} from "./utils.ts"; +import {Pickup} from "./pickups.ts"; +import {Skill} from "./datatypes.ts"; + +export enum Architecture { Wall, Floor } -export type Province = "a" | "b" | "c"; -export type Check = "1" | "2"; -export type Progress = Stat | Resource -export type Pickup = Progress | "Ladder"; // TODO: Items -export type NewMapInput = { - id: string, - data: { - architecture: string, - provinces: string, - } - pickups: { - "*"?: string, - stat: {primary: Stat, secondary: Stat}, - "!"?: string, - }, - provinces: Record, - checks: Record, -} export type CheckData = { label: string, options: CheckDataOption[], @@ -32,8 +16,6 @@ export type CheckDataOption = { success: string, } -export enum Architecture { Wall, Floor } - export class LoadedNewMap { #id: string #size: Size @@ -41,7 +23,6 @@ export class LoadedNewMap { #architecture: Grid #pickups: Grid #provinces: Grid - #checks: Grid #revealed: Grid constructor(id: string, size: Size) { @@ -51,7 +32,6 @@ export class LoadedNewMap { this.#architecture = new Grid(size, () => Architecture.Wall); this.#pickups = new Grid(size, () => null); this.#provinces = new Grid(size, () => null); - this.#checks = new Grid(size, () => null); this.#revealed = new Grid(size, () => false); } @@ -98,14 +78,6 @@ export class LoadedNewMap { return this.#provinces.get(point); } - setCheck(point: Point, value: CheckData | null) { - this.#checks.set(point, value); - } - - getCheck(point: Point): CheckData | null { - return this.#checks.get(point); - } - setRevealed(point: Point, value: boolean) { this.#revealed.set(point, value) } @@ -133,9 +105,6 @@ export class CellView { set province(value: string | null) { this.#map.setProvince(this.#point, value) } get province(): string | null { return this.#map.getProvince(this.#point) } - set check(value: CheckData | null) { this.#map.setCheck(this.#point, value) } - get check(): CheckData | null { return this.#map.getCheck(this.#point) } - set revealed(value: boolean) { this.#map.setRevealed(this.#point, value) } get revealed(): boolean { return this.#map.getRevealed(this.#point) } @@ -143,69 +112,6 @@ export class CellView { this.architecture = cell.architecture; this.pickup = cell.pickup; this.province = cell.province; - this.check = cell.check; this.revealed = cell.revealed; } -} - -export type NewMap = () => LoadedNewMap; - -export function compileNewMap(input: NewMapInput): NewMap { - let {architecture: architectureInput, provinces: provincesInput} = input.data; - let architecture = Grid.createGridFromMultilineString(architectureInput); - let provinces = Grid.createGridFromMultilineString(provincesInput); - - let size = architecture.size; - if (!size.equals(provinces.size)) { - throw `${input.id}: malformed, wrong province size (${provinces.size})`; - } - - return () => { - let map = new LoadedNewMap(input.id, size); - - for (let y = 0; y < size.h; y++) { - for (let x = 0; x < size.w; x++) { - let xy = new Point(x, y); - let cell = map.get(xy); - - // set up the wall - let arch = architecture.get(xy); - cell.architecture = Architecture.Floor; - if (arch == "#") { - cell.architecture = Architecture.Wall; - } else if (arch == "@") { - map.entrance = xy; - } else if (arch == " " || arch == "-") { - - } - // player resources: pickups - else if (arch == ".") { - let stat = choose([ - input.pickups.stat.primary, - input.pickups.stat.primary, - input.pickups.stat.secondary - ]) - cell.pickup = choose([stat, stat, stat, "EXP"]); - } else if (arch == "*") { - // TODO: Common item - } else if (arch == "!") { - // TODO: Artifact - } - // stat checks - else if (input.checks.hasOwnProperty(arch)) { - cell.check = input.checks[arch as Check]; - } else { - throw `${input.id}: unrecognized architecture cell: ${arch}` - } - - // set province - let provinceId = provinces.get(xy); - if (input.provinces.hasOwnProperty(provinceId)) { - cell.province = input.provinces[provinceId as Province]; - } - } - } - - return map; - } -} +} \ No newline at end of file diff --git a/src/newmaps/bloodBank/architecture.txt b/src/newmaps/bloodBank/architecture.txt deleted file mode 100644 index cec51f8..0000000 --- a/src/newmaps/bloodBank/architecture.txt +++ /dev/null @@ -1,11 +0,0 @@ -########### -# # # # -# # 2 # -- # # # -# # # # -# ##### # -# 1 # -# ##### -# # -##### # -########### \ No newline at end of file diff --git a/src/newmaps/bloodBank/map.ts b/src/newmaps/bloodBank/map.ts deleted file mode 100644 index 6378250..0000000 --- a/src/newmaps/bloodBank/map.ts +++ /dev/null @@ -1,27 +0,0 @@ -import architecture from "./architecture.txt?raw"; -import provinces from "./provinces.txt?raw"; -import {compileNewMap} from "../../newmap.ts"; - -const mapBloodBank = compileNewMap({ - id: "mapBloodBank", - data: { - architecture: architecture, - provinces: provinces, - }, - pickups: { - // "*": itemGecko, - stat: {primary: "AGI", secondary: "INT"}, - // "!": {"item": "colonialGoose"}, - }, - provinces: { - a: "Blood Bank", - b: "Special Reserve", - c: "Freezer", - }, - checks: { - 1: null!, - 2: null!, - } -}) - -export default mapBloodBank; \ No newline at end of file diff --git a/src/newmaps/bloodBank/provinces.txt b/src/newmaps/bloodBank/provinces.txt deleted file mode 100644 index 98102ed..0000000 --- a/src/newmaps/bloodBank/provinces.txt +++ /dev/null @@ -1,11 +0,0 @@ -########### -#aa#ccc#bb# -#aa#ccc bb# --aa#ccc#bb# -#aa#ccc#bb# -#aa#####bb# -#aaaaaa bb# -#aaaaa##### -#aaaaaaaaa# -#####aaaaa# -########### \ No newline at end of file diff --git a/src/newmaps/club/architecture.txt b/src/newmaps/club/architecture.txt deleted file mode 100644 index 83a4de2..0000000 --- a/src/newmaps/club/architecture.txt +++ /dev/null @@ -1,11 +0,0 @@ -########### -# # -# # -######## # -# 1 # -# ##### - -# # # # -# # # # -# 2 # # -# # # # -########### \ No newline at end of file diff --git a/src/newmaps/club/map.ts b/src/newmaps/club/map.ts deleted file mode 100644 index 3336e23..0000000 --- a/src/newmaps/club/map.ts +++ /dev/null @@ -1,27 +0,0 @@ -import architecture from "./architecture.txt?raw"; -import provinces from "./provinces.txt?raw"; -import {compileNewMap} from "../../newmap.ts"; - -const mapClub = compileNewMap({ - id: "mapClub", - data: { - architecture: architecture, - provinces: provinces, - }, - pickups: { - // "*": itemGecko, - stat: {primary: "CHA", secondary: "PSI"}, - // "!": {"item": "colonialGoose"}, - }, - provinces: { - a: "Club", - b: "Poker Game", - c: "Trophy Collection", - }, - checks: { - 1: null!, - 2: null!, - } -}) - -export default mapClub; \ No newline at end of file diff --git a/src/newmaps/club/provinces.txt b/src/newmaps/club/provinces.txt deleted file mode 100644 index f906984..0000000 --- a/src/newmaps/club/provinces.txt +++ /dev/null @@ -1,11 +0,0 @@ -########### -#aaaaaaaaa# -#aaaaaaaaa# -########aa# -#bbbbbb aa# -#bb#####aa- -#bb#ccc#aa# -#bb#ccc#aa# -#bb ccc#aa# -#bb#ccc#aa# -########### \ No newline at end of file diff --git a/src/newmaps/coffeeShop/architecture.txt b/src/newmaps/coffeeShop/architecture.txt deleted file mode 100644 index f1cb706..0000000 --- a/src/newmaps/coffeeShop/architecture.txt +++ /dev/null @@ -1,11 +0,0 @@ -########### -# # # -# 2 # -# # # -# #####1# -# # # -# # # -###### # -# # -# # -###### #### \ No newline at end of file diff --git a/src/newmaps/coffeeShop/map.ts b/src/newmaps/coffeeShop/map.ts deleted file mode 100644 index 5f27471..0000000 --- a/src/newmaps/coffeeShop/map.ts +++ /dev/null @@ -1,27 +0,0 @@ -import architecture from "./architecture.txt?raw"; -import provinces from "./provinces.txt?raw"; -import {compileNewMap} from "../../newmap.ts"; - -const mapCoffeeShop = compileNewMap({ - id: "mapCoffeeShop", - data: { - architecture: architecture, - provinces: provinces, - }, - pickups: { - // "*": itemGecko, - stat: {primary: "PSI", secondary: "CHA"}, - // "!": {"item": "colonialGoose"}, - }, - provinces: { - a: "Coffee Shop", - b: "Studio", - c: "Personal Photo Room", - }, - checks: { - 1: null!, - 2: null!, - } -}) - -export default mapCoffeeShop; \ No newline at end of file diff --git a/src/newmaps/coffeeShop/provinces.txt b/src/newmaps/coffeeShop/provinces.txt deleted file mode 100644 index 7f277b3..0000000 --- a/src/newmaps/coffeeShop/provinces.txt +++ /dev/null @@ -1,11 +0,0 @@ -########### -#ccc#bbbbb# -#ccc bbbbb# -#ccc#bbbbb# -#ccc##### # -#cccc#aaaa# -#cccc#aaaa# -######aaaa# -#aaaaaaaaa# -#aaaaaaaaa# -###### #### \ No newline at end of file diff --git a/src/newmaps/hub/map.ts b/src/newmaps/hub/map.ts deleted file mode 100644 index ade3186..0000000 --- a/src/newmaps/hub/map.ts +++ /dev/null @@ -1,63 +0,0 @@ -import metamap from "./metamap.txt?raw"; -import {Architecture, LoadedNewMap, NewMap, Progress} from "../../newmap.ts"; -import {Grid, Point} from "../../engine/datatypes.ts"; -import mapZoo from "../zoo/map.ts"; -import mapOptometrist from "../optometrist/map.ts"; -import mapBloodBank from "../bloodBank/map.ts"; -import mapCoffeeShop from "../coffeeShop/map.ts"; -import mapClub from "../club/map.ts"; -import mapManor from "../manor/map.ts"; -import mapLibrary from "../library/map.ts"; -import {choose} from "../../utils.ts"; -import {ALL_STATS} from "../../datatypes.ts"; - -const mapHub: NewMap = () => { - let metamapLayer = Grid.createGridFromMultilineString(metamap); - - // NOTE: We could deduce this from the file -- - // BUT, for now, let's just use the maps directly - let blits = [ - {at: new Point(2, 0), map: mapOptometrist()}, - {at: new Point(0, 12), map: mapZoo()}, - {at: new Point(13, 9), map: mapBloodBank()}, - {at: new Point(24, 9), map: mapCoffeeShop()}, - {at: new Point(0, 22), map: mapClub()}, - {at: new Point(13, 22), map: mapManor(), useEntrance: true}, - {at: new Point(26, 22), map: mapLibrary()}, - ]; - - let metamapContent = new LoadedNewMap("hub", metamapLayer.size); - - for (let y = 0; y < metamapLayer.size.h; y++) { - for (let x = 0; x < metamapLayer.size.w; x++) { - let src = new Point(x, y); - let cell = metamapContent.get(src); - if (metamapLayer.get(src) == "#") { - cell.architecture = Architecture.Wall; - } else if (metamapLayer.get(src) == " ") { - cell.architecture = Architecture.Floor; - let stat = choose(ALL_STATS); - cell.pickup = choose([stat, stat, stat, "EXP"]); - } - } - } - - for (let {at, map, useEntrance} of blits.values()) { - for (let srcY = 0; srcY < map.size.h; srcY++) { - for (let srcX = 0; srcX < map.size.w; srcX++) { - let src = new Point(srcX, srcY); - let dst = at.offset(new Point(srcX, srcY)); - metamapContent.get(dst).copyFrom(map.get(src)) - } - } - - if (useEntrance ?? false) { - console.log("beep"); - metamapContent.entrance = at.offset(map.entrance); - } - } - - return metamapContent; -} - -export default mapHub; \ No newline at end of file diff --git a/src/newmaps/hub/metamap.txt b/src/newmaps/hub/metamap.txt deleted file mode 100644 index b883f62..0000000 --- a/src/newmaps/hub/metamap.txt +++ /dev/null @@ -1,33 +0,0 @@ -##11111111111######################## -##11111111111######################## -##11111111111######################## -##11111111111######################## -##11111111111######################## -##11111111111######################## -##11111111111######################## -##11111111111######################## -##11111111111######################## -##111111111113333333333344444444444## -##111111111113333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 3333333333344444444444## -22222222222 ###### -22222222222 ###### -55555555555 66666666666 77777777777 -55555555555 66666666666 77777777777 -55555555555 66666666666 77777777777 -55555555555 66666666666 77777777777 -55555555555 66666666666 77777777777 -55555555555 66666666666##77777777777 -55555555555##66666666666##77777777777 -55555555555##66666666666##77777777777 -55555555555##66666666666##77777777777 -55555555555##66666666666##77777777777 -55555555555##66666666666##77777777777 diff --git a/src/newmaps/hub/overworld.png b/src/newmaps/hub/overworld.png deleted file mode 100644 index 18e22f24cb4a5b1c39ac292df3c4376f52ff6cb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 912 zcmV;B18@9^P)EX>4Tx04R}tkv&MmKpe$iQ$>-AgGEFHGgKEXNELCEDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRb`5 zkz)ZBsE`~#_#gc4*33^u+@wGh=zOv5k5Qm&7iiRM`}^3o8z+GO8Mx9~{z@H~{Up8C z(n3c--!^b@-O}Ve;Bp5Te9|RDawI=ZA)g1{&*+=7K>sb!v*z~J+{ftykfyGdZ-9eC zV5~sd>mKj!Ztv~iGtK^f03S(m?4{A9x&QzG32;bRa{vGf6951U69E94oEQKA00(qQ zO+^Rk0tyBN0)G~|H2?qso=HSOR7l6&S4(b#Fc5uH`2x95#0`)+M3qalT}8b_)k9z* zbzjtFwmC5!q!A);~UZWFFASopJkJ(@8?aU%tTmMw4qj_cShmZl?V!X(0 z^Q+;E3%#E9eIjqj?NeHz+RU5s!MV+mC^3|>EJ#+B*G(cPc{Iw0()!{|IIThwR^(9j z3iYMXC0WQwPa8GSdz>mWy)}Kmna$<;mE#v3mMYiiDc(|@#V-JScG^7{?)=-}V9&h) zpbwL>r;l0xl}%)vL^Hd-`utyqrMQ13}Q-DmtY$)nO z=hGl6*&_-4HtO=mq|p(wEY+rAjHL4a3wr(KYQG$G8kX5W6 [lore1], - locked: "That wall sure does look impenetrable.", - unlockable: "I see a failure in the construction.", - unlockScene: compile([ - "I dig my clawed fingers into a crack between the bricks and feel the concrete give way.", - "This structure, built by mortals, is impermanent. Soon none of it will exist.", - "I rip another clump of brittle earth from the crack, no longer invisible.", - "And another. When the gap's wide enough to crawl through, I climb in." - ]) - }, - { - skills: () => [stare0], - locked: "The bats are happy by themselves.", - unlockable: "These bats could be enjoying themselves so much more.", - unlockScene: compile([ - "I hold my face to the bars. One bat looks at me.", - "\"Here, little bat\" -- I think before I say it. No, relate to it as an equal.", - "What does it really want?", - "What does any mortal want? It wants to feel a whole lot better --", - "So stare --", - "...", - "... Now it breaks. Like any mortal, but with a loud, high-pitched squeal.", - "Still dripping, it flaps unsurely to the door and -- with only a little coaxing -- it opens the lock." - ]) - } - ] - }, - 2: { - label: - "The unattended food storage cabinet is secure. " + - "The shiny surface, which I lack a reflection in, repels direct attack. " + - "Through the keyhole I can see something delicious.", - options: [ - { - skills: () => [bat2], - locked: "If only were smaller...", - unlockable: "I am small enough to crawl through.", - unlockScene: compile([ - "There's a bat inside me. I guess it's like that with every vampire.", - "I can fight, if I try, to keep it inside. But that's not how we want it.", - "And in the second before I let it out -- as the soft fur behind my ears begins to sprout -- I feel a sense of relief.", - "A sense of gratitude.", - "I can't resist it now. It's urgent. I shed the rest of my mass.", - "Now I'm as sleek and narrow as a dart --", - "I'm inside." - ]) - } - ] - } - } -}) - -export default mapZoo; \ No newline at end of file diff --git a/src/newmaps/zoo/provinces.txt b/src/newmaps/zoo/provinces.txt deleted file mode 100644 index 76ae924..0000000 --- a/src/newmaps/zoo/provinces.txt +++ /dev/null @@ -1,11 +0,0 @@ -########### -#cccc#aaaa# -#cccc#aaaa# -#cccc#aaaa# -## ###a##a- -#bbb#aaaaa- -#bbb##a##a- -#bbbb#aaaa# -#bbbb aaaa# -#bbbb#aaaa# -########### diff --git a/src/pickups.ts b/src/pickups.ts new file mode 100644 index 0000000..75d51b7 --- /dev/null +++ b/src/pickups.ts @@ -0,0 +1,150 @@ +import {getThralls, Thrall} from "./thralls.ts"; +import {CellView, CheckData} from "./newmap.ts"; +import {getPlayerProgress} from "./playerprogress.ts"; +import {getHuntMode, HuntMode, initHuntMode} from "./huntmode.ts"; +import {generateMap} from "./mapgen.ts"; +import {ALL_STATS, Stat} from "./datatypes.ts"; +import {D} from "./engine/public.ts"; +import {sprLadder, sprLock, sprRaccoonWalking, sprResourcePickup, sprStatPickup} from "./sprites.ts"; +import {GridArt} from "./gridart.ts"; +import {getCheckModal} from "./checkmodal.ts"; +import {Point} from "./engine/datatypes.ts"; + +export type Pickup + = LockPickup + | StatPickup + | ExperiencePickup + | LadderPickup + | ThrallPickup + +export class LockPickup { + check: CheckData; + + constructor(check: CheckData) { + this.check = check; + } + + computeCostToClick() { return 0; } + + isObstructive() { return true; } + + drawFloor() { } + drawInAir(gridArt: GridArt) { + for (let z = 0; z < 5; z += 0.25) { + D.drawSprite(sprLock, gridArt.project(z), 0, { + xScale: 2.0, + yScale: 2.0, + }) + } + } + + onClick(cell: CellView): boolean { + getCheckModal().show(this.check, () => cell.pickup = null); + return true; + } +} + +export class StatPickup { + stat: Stat; + + constructor(stat: Stat) { + this.stat = stat; + } + + computeCostToClick() { return 100; } + + isObstructive() { return true; } + + drawFloor() { } + drawInAir(gridArt: GridArt) { + let statIndex = ALL_STATS.indexOf(this.stat); + if (statIndex == -1) { return; } + + D.drawSprite( + sprStatPickup, + gridArt.project(5), + statIndex, + { + xScale: 2, + yScale: 2, + } + ) + } + + onClick(): boolean { + getPlayerProgress().add(this.stat, 1); + getPlayerProgress().purloinItem(); + return false; + } +} + +export class ExperiencePickup { + computeCostToClick() { return 100; } + + isObstructive() { return true; } + + drawFloor() { } + drawInAir(gridArt: GridArt) { + D.drawSprite( + sprResourcePickup, + gridArt.project(0.0).offset(new Point(0, -16)), + 0, + { + xScale: 2, + yScale: 2, + } + ); + } + + onClick(): boolean { + getPlayerProgress().addExperience(250); + getPlayerProgress().purloinItem(); + return false; + } +} + +export class LadderPickup { + computeCostToClick() { return 0; } + + isObstructive() { return false; } + + drawFloor(gridArt: GridArt) { + D.drawSprite(sprLadder, gridArt.project(0.0), 0, { + xScale: 2.0, + yScale: 2.0, + }) + } + drawInAir() { } + + onClick(): boolean { + getPlayerProgress().addBlood(1000); + initHuntMode(new HuntMode(getHuntMode().depth + 1, generateMap())); + return false; + } +} + +export class ThrallPickup { + thrall: Thrall; + + constructor(thrall: Thrall) { + this.thrall = thrall; + } + + computeCostToClick() { return 0; } + + isObstructive() { return false; } + + drawFloor() { } + drawInAir(gridArt: GridArt) { + D.drawSprite(sprRaccoonWalking, gridArt.project(0.0), 0, { + xScale: 2.0, + yScale: 2.0, + }) + } + + onClick(cell: CellView): boolean { + let data = getThralls().get(this.thrall); + getCheckModal().show(data.initialCheck, () => cell.pickup = null); + return true; + } +} \ No newline at end of file diff --git a/src/thralls.ts b/src/thralls.ts index aee2898..1a6b50c 100644 --- a/src/thralls.ts +++ b/src/thralls.ts @@ -42,6 +42,10 @@ export type ThrallData = { let table = new ThrallsTable(); +export function getThralls() { + return table; +} + // Thralls are labeled by which zone's item they like // Their initial check is, generally, the initial check of the // thrall n-2 or thrall n+1 (ex: Party's initial check is Stealth diff --git a/src/vaulttemplate.ts b/src/vaulttemplate.ts index 89afdc3..81c1ea5 100644 --- a/src/vaulttemplate.ts +++ b/src/vaulttemplate.ts @@ -19,11 +19,13 @@ import { stealth2 } from "./skills.ts"; import {CheckData} from "./newmap.ts"; +import {Thrall, thrallBat, thrallCharm, thrallLore, thrallParty, thrallStare, thrallStealth} from "./thralls.ts"; export type VaultTemplate = { stats: {primary: Stat, secondary: Stat}, + thrall: () => Thrall, checks: [CheckData, CheckData] } @@ -31,6 +33,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ { // zoo stats: {primary: "AGI", secondary: "PSI"}, + thrall: () => thrallParty, checks: [ { label: "You're blocked from further access by a sturdy-looking brick wall. Playful bats swoop close to the alligators behind the bars.", @@ -63,6 +66,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ { // blood bank stats: {primary: "AGI", secondary: "INT"}, + thrall: () => thrallLore, checks: [ { label: "The nice old lady at the counter says you can't have any blood without a doctor's note.", @@ -98,6 +102,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ { // coffee shop stats: {primary: "PSI", secondary: "CHA"}, + thrall: () => thrallBat, checks: [ { label: "You don't actually drink coffee, so you probably wouldn't fit in inside.", @@ -130,6 +135,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ { // optometrist stats: {primary: "PSI", secondary: "PSI"}, + thrall: () => thrallCharm, checks: [ { label: "The glasses person doesn't have time for you unless you have a prescription that needs filling.", @@ -162,6 +168,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ { // club, stats: {primary: "CHA", secondary: "PSI"}, + thrall: () => thrallStealth, checks: [ { label: "You're not here to party, are you? Vampires are total nerds! Everyone's going to laugh at you and say you're totally uncool.", @@ -194,6 +201,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ { // library stats: {primary: "INT", secondary: "CHA"}, + thrall: () => thrallStare, checks: [ { label: "Special Collections. This guy is not just a librarian -- he's a vampire, too -- which he makes no effort to hide.",