From c23a7b6d7570104ea39354f92ae9764bdda561d1 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Sun, 2 Feb 2025 21:47:45 -0800 Subject: [PATCH] XP system --- src/art/pickups/chest.png | Bin 0 -> 426 bytes src/art/pickups/resources.png | Bin 0 -> 418 bytes src/datatypes.ts | 3 +++ src/hud.ts | 2 +- src/huntmode.ts | 41 ++++++++++++++++++++++++++++++---- src/playerprogress.ts | 24 +++++++++++++++++--- src/skills.ts | 1 - src/skillsmodal.ts | 9 +++++++- src/sprites.ts | 5 +++++ 9 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 src/art/pickups/chest.png create mode 100644 src/art/pickups/resources.png diff --git a/src/art/pickups/chest.png b/src/art/pickups/chest.png new file mode 100644 index 0000000000000000000000000000000000000000..359ae0f7f55f4990fd57dc6c1350b8d525b761d5 GIT binary patch literal 426 zcmV;b0agBqP)Px$WJyFpRCt{2n6VDQP!xtw#fx|WlSHhZz#<;NU^a+|rHeFTFn90((nTybYeP(4 zz@yY8LG)hkx$U`b|8J9)?`Z#?dv1vU00000007k@kS;(+x?5%Q<@V#T#dJVKM5^PR z-o*L;D2dY-C*7?w8^41PmkDY=k@E7Y>?gDhI!(pzt4B+ScSpfk54=VugZK!PE=lj`9 zfaFDhpYJygz_VOp9faSGpY- UsK=E2H~;_u07*qoM6N<$f=#r+IRF3v literal 0 HcmV?d00001 diff --git a/src/art/pickups/resources.png b/src/art/pickups/resources.png new file mode 100644 index 0000000000000000000000000000000000000000..6db5d47d81d3d33fd65d409fbc602c8cf24cc5cf GIT binary patch literal 418 zcmV;T0bTxyP)Px$TuDShRA_-?U>F6XU=)mkQ801=<3Kxr9PlfP>pwF8=@m%^1_lNO#Y1<8q<_c) z|DoX4gIE7=J$Uv1zMb-a!n!cQkPI`xiAuve02mk`NgtayBO@bO zei>2$Fyd3doZHS=1EAvQYZU&QgiA#Gi-kfr(H$hK>_Oq*e)yWF*3=EEHDDtG%!vk&qXf;TR z;^CMDh*pSR2cy@$*Z?W@@j%&6QD5Mg!ycS+v@Q#%W&emT11L%XRtH>g%84w{`%ld* zKr8!6av-+G2sXer?Hf%zP7C` = ["AGI", "INT", "CHA", "PSI"]; +export type Resource = "EXP"; +export const ALL_RESOURCES: Array = ["EXP"] + export type SkillGoverning = { stats: Stat[], underTarget: number, target: number, cost: number, note: string }; diff --git a/src/hud.ts b/src/hud.ts index 21347ca..fa156c3 100644 --- a/src/hud.ts +++ b/src/hud.ts @@ -24,7 +24,7 @@ export class Hud { y += 16; } D.drawText("EXP", new Point(0, 128), FG_BOLD); - D.drawText("0", new Point(32, 128), FG_TEXT); + D.drawText(`${prog.getExperience()}`, new Point(32, 128), FG_TEXT); D.drawText("BLD", new Point(0, 144), FG_BOLD); D.drawText(`${prog.getBlood()}cc`, new Point(32, 144), FG_TEXT); } diff --git a/src/huntmode.ts b/src/huntmode.ts index a74db68..e60b58e 100644 --- a/src/huntmode.ts +++ b/src/huntmode.ts @@ -1,14 +1,15 @@ import {Grid, Point, Rect, Size} from "./engine/datatypes.ts"; import {ConceptualCell, maps} from "./maps.ts"; -import {ALL_STATS, Stat} from "./datatypes.ts"; +import {ALL_STATS, Resource, Stat} from "./datatypes.ts"; import {DrawPile} from "./drawpile.ts"; import {D} from "./engine/public.ts"; -import {sprDrips, sprRaccoonWalking, sprStatPickup} from "./sprites.ts"; +import {sprDrips, sprRaccoonWalking, sprResourcePickup, sprStatPickup} from "./sprites.ts"; import {BG_INSET, FG_TEXT} from "./colors.ts"; import {getPlayerProgress} from "./playerprogress.ts"; export type MapCellContent = {type: "statPickup", stat: Stat} | + {type: "resourcePickup", resource: Resource} | {type: "stairs"} | {type: "empty"} | {type: "block"} @@ -112,9 +113,13 @@ export class HuntMode { let gsp = (): MapCellContent => { return {type: "statPickup", stat: choose(ALL_STATS)} }; + let exp = (): MapCellContent => { + return {type: "resourcePickup", resource: "EXP"} + } // TODO: Other objects? return choose([ - gsp, gsp, gsp, gsp + gsp, gsp, gsp, gsp, + exp, ])(); } @@ -142,17 +147,31 @@ export class HuntMode { #collectResources() { let present = this.cells.get(this.player); + if (present.content.type == "statPickup") { let stat = present.content.stat; let amount = 1; present.content = {type: "empty"}; getPlayerProgress().add(stat, amount); } + + if (present.content.type == "resourcePickup") { + let resource = present.content.resource; + switch(resource) { + case "EXP": + getPlayerProgress().addExperience(25); + break; + default: + throw `not sure how to add ${resource}` + } + } + + present.content = {type: "empty"}; } #computeCostToMoveTo(mapPosition: Point): number | null { let present = this.cells.get(mapPosition); - if (present.content.type == "statPickup") { + if (present.content.type == "statPickup" || present.content.type == "resourcePickup") { return 100; } if (present.content.type == "empty") { @@ -267,6 +286,20 @@ export class HuntMode { ) }); } + + if (cellData.content.type == "resourcePickup" && cellData.content.resource == "EXP") { + this.drawpile.add(inAir, () => { + D.drawSprite( + sprResourcePickup, + cellOffset.offset(new Point(0, -16 * 3)), + 0, + { + xScale: 3, + yScale: 3, + } + ); + }); + } } #drawPlayer(globalOffset: Point) { diff --git a/src/playerprogress.ts b/src/playerprogress.ts index 94db985..66ebad7 100644 --- a/src/playerprogress.ts +++ b/src/playerprogress.ts @@ -3,6 +3,7 @@ import {getSkills} from "./skills.ts"; export class PlayerProgress { #stats: Record + #exp: number; #blood: number #skillsLearned: number[] // use the raw ID representation for indexOf #untrimmedSkillsAvailable: Skill[] @@ -14,6 +15,7 @@ export class PlayerProgress { CHA: 10, PSI: 10, }; + this.#exp = 0; this.#blood = 0; this.#skillsLearned = []; this.#untrimmedSkillsAvailable = [] @@ -82,6 +84,21 @@ export class PlayerProgress { this.#stats[stat] += amount; } + addExperience(amt: number) { + this.#exp += amt; + } + + getExperience(): number { + return this.#exp + } + + spendExperience(cost: number) { + if (this.#exp < cost) { + throw `can't spend ${cost}` + } + this.#exp -= cost; + } + getStat(stat: Stat): number { return this.#stats[stat] } @@ -97,9 +114,6 @@ export class PlayerProgress { getAvailableSkills(): Skill[] { // Sort by cost, then by name, then trim down to first 6 let skillsAvailable = [...this.#untrimmedSkillsAvailable]; - skillsAvailable.sort((a, b) => { - return getSkills().computeCost(a) - getSkills().computeCost(b) - }); skillsAvailable.sort((a, b) => { let name1 = getSkills().get(a).profile.name; let name2 = getSkills().get(b).profile.name; @@ -108,8 +122,12 @@ export class PlayerProgress { if (name1 > name2) { return 1; } return 0; }); + skillsAvailable.sort((a, b) => { + return getSkills().computeCost(a) - getSkills().computeCost(b) + }); return skillsAvailable.slice(0, 6) } + } let active: PlayerProgress = new PlayerProgress(); diff --git a/src/skills.ts b/src/skills.ts index fdd6faa..3622eb3 100644 --- a/src/skills.ts +++ b/src/skills.ts @@ -53,7 +53,6 @@ function geomInterpolate( if (x >= highIn) { return lowOut; } const proportion = 1.0 - (x - lowIn) / (highIn - lowIn); - console.log(`proportion: ${x} ${proportion}`) return lowOut * Math.pow(highOut / lowOut, proportion) } diff --git a/src/skillsmodal.ts b/src/skillsmodal.ts index 7f75a3d..7c16b0a 100644 --- a/src/skillsmodal.ts +++ b/src/skillsmodal.ts @@ -89,6 +89,7 @@ export class SkillsModal { let selection = this.#skillSelection; if (selection != null) { let data = getSkills().get(selection); + let cost = getSkills().computeCost(selection); let size = this.#size; let remainingWidth = size.w - 160; @@ -99,8 +100,14 @@ export class SkillsModal { // add learn button let drawButtonRect = new Rect(new Point(160, 96), new Size(remainingWidth, 32)) + let canAfford = getPlayerProgress().getExperience() >= cost; let caption = `Learn ${data.profile.name}` - addButton(this.#drawpile, caption, drawButtonRect, true, () => { + if (!canAfford) { + caption = `Can't Afford`; + } + + addButton(this.#drawpile, caption, drawButtonRect, canAfford, () => { + getPlayerProgress().spendExperience(cost); getPlayerProgress().learnSkill(selection); }) } diff --git a/src/sprites.ts b/src/sprites.ts index b5ec148..8a0273c 100644 --- a/src/sprites.ts +++ b/src/sprites.ts @@ -7,6 +7,7 @@ import imgSnake from "./art/characters/snake.png"; */ import imgRaccoon from "./art/characters/raccoon.png"; import imgRaccoonWalking from "./art/characters/raccoon_walking.png"; +import imgResourcePickup from "./art/pickups/resources.png"; import imgStatPickup from "./art/pickups/stats.png"; import imgDrips from "./art/tilesets/drips.png"; import {Point, Size} from "./engine/datatypes.ts"; @@ -28,6 +29,10 @@ export let sprRaccoonWalking = new Sprite( new Size(64, 64), new Point(32, 32), new Size(8, 1), 8 ); +export let sprResourcePickup = new Sprite( + imgResourcePickup, new Size(32, 32), new Point(16, 16), + new Size(1, 1), 1 +); export let sprStatPickup = new Sprite( imgStatPickup, new Size(32, 32), new Point(16, 16),