From 08fcbaf4e29f2b8c39e820b5e37eede92093a2ec Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Mon, 17 Feb 2025 22:17:41 -0800 Subject: [PATCH] Thrall item pickups --- src/art/thralls/thrall_bat.png | Bin 523 -> 597 bytes src/art/thralls/thrall_charm.png | Bin 601 -> 660 bytes src/art/thralls/thrall_lore.png | Bin 614 -> 676 bytes src/art/thralls/thrall_party.png | Bin 559 -> 630 bytes src/art/thralls/thrall_stare.png | Bin 570 -> 652 bytes src/art/thralls/thrall_stealth.png | Bin 572 -> 647 bytes src/checkmodal.ts | 3 +- src/manormap.ts | 19 ++-- src/mapgen.ts | 12 ++- src/pickups.ts | 141 ++++++++++++++++++++++++++++- src/playerprogress.ts | 31 ++++++- src/sprites.ts | 24 ++--- src/thralls.ts | 73 +++++++++++++++ src/vaulttemplate.ts | 7 ++ 14 files changed, 285 insertions(+), 25 deletions(-) diff --git a/src/art/thralls/thrall_bat.png b/src/art/thralls/thrall_bat.png index 4f258f72eb8104acd76a6af09eaa10cdfc84f061..3a6ce57078590197738e2c247e70efb4df76ece0 100644 GIT binary patch delta 313 zcmV-90mlA|1l0r~iBL{Q4GJ0x0000DNk~Le0001B0000O2m=5B05UfSrm-O?0e|;N zL_t(YiS3g?5`!QNML7mZ=pDk!mEQkY4ba-weC$}Y-Si907-s$>354+1??k4P?aw68 zmjL@LY_0|Suy0`zA1Sa0Skpk)%K1@z ztl9vuR|5edV?db3adJnD^YlrJu()82XBb~5Kr?`uqfbCYk^rY(yaQx1**`iE!NYn7QM8-><_f*Wu-w{7&NT^=cekQ=}^*9WL@F00000 LNkvXXu0mjfGcb$h delta 238 zcmV#4#Y4B1o;MR@&{bGa{m9U1E)JLC*|Za8%(hhV+;{__396)#@PWfi?f5I zsSTVUb?x+mnHS%EX5Q0DOw0G`@@Q|(Gcyv5(Vv492b+;9pPt_$6@r7gLF&q;=WY=c z6kpNONv4%jl5vnU4w7q(i$ie)Fxo26s9!Y%-~g$p{1T*DK=$eBv#nJi$$}?- o39=ch+Kg2{hRy$r!v9+T2hlJc2HxzT#Q*>R07*qoM6N<$f>;z}k^lez diff --git a/src/art/thralls/thrall_charm.png b/src/art/thralls/thrall_charm.png index 698c4e3640dffc49f19e7f5e3a2d4d4c1968a9ce..0e62abfed331d540bfb52e8524c0f5597c840dce 100644 GIT binary patch delta 377 zcmV-<0fzqB1e66KiBL{Q4GJ0x0000DNk~Le0001B0000O2m=5B05UfSrm-O>0e=BD zNklf0{2e7yyY(YwFz_EXCL#QFU6F<2 ziFIfFi9OnqhQNk-zCjT0S$53Uf0`!#V8CU>1~_cl05%DnF{`Nnp#zA=p3ni6$LEGp zA{iUCUPJ~E*f*k!VBdr;qLh*?V1IcD0I>gd%PHr>@{)-#AR_>$KxRWvfrZZF05Z!0 zIAN_Ril++hOzUl9-QNL7O|Qm70H^7I2M+^~gvIEXGnZcDphncfjSQj^1h6M0B?#b1 zpx**`om2?5Y4^8X6r;@8Hj?(t8I%aV*EX6IwJChxC-JbhwwlHMLnFthdQScUO^n|J zn9`a8r&`?%Ai!NM0DEU0fZ`6o6*++VCBW!9^ZL~v#8v2$U3=>1*&j-Oav=Ur;6e&d X+QnJz6fdWr00000NkvXXu0mjf{*j|_ delta 318 zcmV-E0m1&11=$24iBL{Q4GJ0x0000DNk~Le0000;0000O2m=5B0B*fYg0Ued0e=Ad zNklnF|gHRxOQXjf2;v)oL0VzCbOGw(#1!ffR^YV#46-x)rdh^n{>h;9-t>FJIO#RNqz&;ebyOnuBhTQ*tM4eTI;R|qPISsy`R9A&HlFI5Ds|H zAkf;jqCE)B&OmUc8<1>3?Iq~C&G71-1AJE;w*Rbsyo-B=|E$3O7IbqzY!d-LZvk&f Qb^rhX07*qoM6N<$f(D(5r2qf` diff --git a/src/art/thralls/thrall_lore.png b/src/art/thralls/thrall_lore.png index 82eec91971e9bbbf9d97dd4c61180955cdfa3c9b..36ffb74ceecd9143bcc001845b10fa307a55bd36 100644 GIT binary patch delta 392 zcmV;30eAl91f&HaiBL{Q4GJ0x0000DNk~Le0001B0000O2m=5B05UfSrm-O?0e?nG zL_t(YiS3lZj>8}fM1ATX8c;0I#3JyP`Hr*0000DZrZ9b zR!gsUI`upOXn4<{>DF#H+mU11fPch6Qc~CKAdY$I_LL4d>mvX}b3zG3)C+-GPbuS@ zsuhjeZX>vmUgW8odaj#1(KQvb(#-@v5KeHdFz>ow*FBaaHaW=$DzmK}C>JCXWI?sR z`oI%pLABOTKvq$os{}udGFK^pgFtSkxoLI=Ki#Yf@>`J0tsKD5)_kX51RoCj2ZTv& cLkjjk0F7QdcuXlRUH||907*qoM6N<$f@3X+#{d8T diff --git a/src/art/thralls/thrall_party.png b/src/art/thralls/thrall_party.png index a25718fd3b3686bcbdfd605b504bb2be4eee33a6..d3ca241fcb7bd52f53640a143784d755931bdec4 100644 GIT binary patch delta 347 zcmV-h0i^z~1oi|WiBL{Q4GJ0x0000DNk~Le0001B0000O2m=5B05UfSrm-O>0e=A) zNklwxA#9*2|6ywkFA|{*T2x2sQ-~4f#|Ovs+3;? zE`Q)GiJ4(tM6RyL0gwyu2+Oi0jKG2b33uG`vdI#>6*0_6q*fTJn(IBy1QASN#so!x z>TYiVA|Zr+vHrc@FUF~Lx&90R_kU0d0^CB3000Bs{UfIdAeyPzPW3zefUR9Xbn%zt832~;B;^muntYd zwCwTKb9Mne*7Y&h(k|pb05;V&02u&413Q7>;o<=38sJ1tD*THYXE4s+0KngF t2-<%Dz-O24Gz>sPegVLQlM%ep!V@z0IRKPi`3e94002ovPDHLkV1gmMjkN#( delta 275 zcmV+u0qp+v1g``kiBL{Q4GJ0x0000DNk~Le0000;0000O2m=5B0B*fYg0Ued0e=9| zNklzI% zD>H+AcV`m_NGOPqs8|Sc-G~J?!Js$y2ponxCYfPUqOcxST}$Px{#we0xr%@`9Rq=0 z+8O}iAUr*LHN9L#SZl2cqSib)h-j1?Kne_!NKK&M&H8#2kif66>`;2FpB^3o?Pnnn zxsQ|FB02W`fPxZKUC$HL!44uw2uOYa1w6HB-TF5mdYl3=A3)@y3N}W=zJ3x6q7mIB Zy#cL$EiJTtBI^JE002ovPDHLkV1l>yYN-GK diff --git a/src/art/thralls/thrall_stare.png b/src/art/thralls/thrall_stare.png index 12a800a486ad9aabcd2af2c889a8b7f1cd6f8fb1..a324b8fbd0d420965ca22f36d6178bb492dd7ead 100644 GIT binary patch delta 369 zcmV-%0gnE<1dIhCiBL{Q4GJ0x0000DNk~Le0001B0000O2m=5B05UfSrm-O>0e=B5 zNkl9*f-p^h&v5K{WbMMi!Gp(iR} zisU&K2JE{fwF2UcWPOf7krJ*N`}A=@w(YzP3ege`kgYO6*2(M4{SjThN~Eo)y(Lh* z_W+*^pq$BR=1AL|$SANa{=MiH2XmlkP)m!e8G?jPMb{x?_W{I>3WyOs1&^y1A)NDq zZ7tOnk7*QT8BC)n%l&fHdJrA-!}bnR6$BtI)aQ_ZunH2^ni@r|F_3__b}^PfGB^fQ k2Is5A7L%J};)Eup7q$0G9ON9@q5uE@07*qoM6N<$f;B;QAOHXW diff --git a/src/art/thralls/thrall_stealth.png b/src/art/thralls/thrall_stealth.png index bd6a5f3b7d4ffa055333b3062522f00d3e60d280..6b8120ecfc22ac5e9bee4ab96df3109d09e6ab5f 100644 GIT binary patch delta 364 zcmV-y0h9i`1cwD7iBL{Q4GJ0x0000DNk~Le0001B0000O2m=5B05UfSrm-O>0e=B0 zNklyK(~|3`J36)HAd28LWH!|DP2J;++KUWwLIg!i9{^(ZdemABTQaM5=NI zFO|LC^HG)aXNT%d!6;aZvWI_8&!cKeHyrv7#Lo-g4e`zp>ARo#{Uhhc1M$P1C5_g* zApR^Ft#?5|3P`V1;PhYoYdr<>MSnzPrdMK!5pFb>qm)86WP)QBm|+B)Va~G)4?Yld zMM^b+ibxJt5S|HYJ-Yx5(NqOA6k5(OFQ#a1Nt@w>TN393k~kk40^*1340E4y90o@?$6nn^5g-}C@@ThVhPkiX?EUah@Q|EC$&5k3&m0bH=m&}^SrfI;(n!E+V( zbEm9VCi%Sp9HEmyn&z3n6qJvCjV!-CGB6AdTr~L`Y<{LDxC~!$Co!?iLt8gn5z5U9r~_LGDey(RB1I~2c&Jw@4Mx+l3r0inr423P%3nvB2BPf zksPllA}SD-HM1Ubis0^tKLaJ`Ky{!&o_mnz77D6EVBH*u9F!|-K-~=Jl8wOs7padZ z-3*P!oGa=ft;h615(zOdeZ(rv0S2aLoe?Jq^cx5Ux(yK+)O8A4*A&oVIt7h&PJB { this.#success = resultMessage; diff --git a/src/manormap.ts b/src/manormap.ts index a14ccf6..7c0bfc5 100644 --- a/src/manormap.ts +++ b/src/manormap.ts @@ -3,6 +3,7 @@ import { Grid, Point } from "./engine/datatypes.ts"; import { getThralls } from "./thralls.ts"; import { LadderPickup, + ThrallCollectionPlatePickup, ThrallPosterPickup, ThrallRecruitedPickup, } from "./pickups.ts"; @@ -11,15 +12,15 @@ import { getPlayerProgress } from "./playerprogress.ts"; const BASIC_PLAN = Grid.createGridFromMultilineString(` ##################### ######### ######### -##### A # L # D ##### -##### a # # d ##### +##### a # L # d ##### +##### A # # D ##### ##### ## ## ##### # ## ## ## ## # -#Bb eE# +#bB Ee# # ## ## ## ## # ##### ## ## ##### -##### c # # f ##### -##### C # @ # F ##### +##### C # # F ##### +##### c # @ # f ##### ######### ######### ##################### `); @@ -32,16 +33,20 @@ export function generateManor(): LoadedNewMap { for (let x = 0; x < BASIC_PLAN.size.w; x++) { let xy = new Point(x, y); let cell = map.get(xy); + let unlocked = (ix: number) => + getPlayerProgress().isThrallUnlocked(thralls[ix]); let placeThrall = (ix: number) => { cell.architecture = Architecture.Floor; - if (true || getPlayerProgress().isThrallUnlocked(thralls[ix])) { + if (unlocked(ix)) { cell.pickup = new ThrallRecruitedPickup(thralls[ix]); } }; let placeThrallPoster = (ix: number) => { cell.architecture = Architecture.Floor; - if (!getPlayerProgress().isThrallUnlocked(thralls[ix])) { + if (unlocked(ix)) { + cell.pickup = new ThrallCollectionPlatePickup(thralls[ix]); + } else { cell.pickup = new ThrallPosterPickup(thralls[ix]); } }; diff --git a/src/mapgen.ts b/src/mapgen.ts index 3b5526d..849b62e 100644 --- a/src/mapgen.ts +++ b/src/mapgen.ts @@ -8,9 +8,11 @@ import { LadderPickup, LockPickup, StatPickup, + ThrallItemPickup, ThrallPickup, } from "./pickups.ts"; import { getPlayerProgress } from "./playerprogress.ts"; +import { ItemStage } from "./thralls.ts"; const WIDTH = 19; const HEIGHT = 19; @@ -334,6 +336,7 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { let cell = knife.map.get(goodie); if (a.contains(goodie)) { + cell.pickup = new ExperiencePickup(); let thrall = vaultTemplate.thrall(); if (!getPlayerProgress().isThrallUnlocked(thrall)) { cell.pickup = new ThrallPickup(thrall); @@ -350,7 +353,14 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { } if (d.contains(goodie)) { - // TOOD: Put a fancy item here + cell.pickup = new ExperiencePickup(); + + // replace with a fancy item if nothing is eligible + let thrallItem = vaultTemplate.thrallItem(); + let stage = getPlayerProgress().getThrallItemStage(thrallItem); + if (stage == ItemStage.Untouched) { + cell.pickup = new ThrallItemPickup(thrallItem); + } } } } diff --git a/src/pickups.ts b/src/pickups.ts index 8790de2..5ed734a 100644 --- a/src/pickups.ts +++ b/src/pickups.ts @@ -1,4 +1,4 @@ -import { getThralls, LifeStage, Thrall } from "./thralls.ts"; +import { getThralls, ItemStage, LifeStage, Thrall } from "./thralls.ts"; import { CellView, CheckData } from "./newmap.ts"; import { getPlayerProgress } from "./playerprogress.ts"; import { getHuntMode, HuntMode, initHuntMode } from "./huntmode.ts"; @@ -13,8 +13,9 @@ import { } from "./sprites.ts"; import { GridArt } from "./gridart.ts"; import { getCheckModal } from "./checkmodal.ts"; -import { Point } from "./engine/datatypes.ts"; +import { Point, Size } from "./engine/datatypes.ts"; import { choose } from "./utils.ts"; +import { FG_TEXT } from "./colors.ts"; export type Pickup = | LockPickup @@ -293,3 +294,139 @@ export class ThrallRecruitedPickup { return true; } } + +export class ThrallCollectionPlatePickup { + thrall: Thrall; + rewarded: boolean; + + constructor(thrall: Thrall) { + this.thrall = thrall; + this.rewarded = false; + } + + computeCostToClick() { + return 0; + } + + isObstructive() { + return false; + } + + drawFloor() {} + drawInAir(gridArt: GridArt) { + let itemStage = getPlayerProgress().getThrallItemStage(this.thrall); + let data = getThralls().get(this.thrall); + + if (itemStage != ItemStage.Delivered) { + D.drawRect( + gridArt.project(0).offset(new Point(-18, -18)), + new Size(36, 36), + FG_TEXT, + ); + } else { + D.drawSprite(data.sprite, gridArt.project(2), 3, { + xScale: 2.0, + yScale: 2.0, + }); + } + } + + onClick(cell: CellView): boolean { + let lifeStage = getPlayerProgress().getThrallLifeStage(this.thrall); + let itemStage = getPlayerProgress().getThrallItemStage(this.thrall); + let data = getThralls().get(this.thrall); + + // if (itemStage == ItemStage.Untouched) { itemStage = ItemStage.Obtained; } + + if (itemStage == ItemStage.Untouched) { + if (lifeStage == LifeStage.Dead) { + getCheckModal().show( + { + label: "There's no point in delivering this now.", + options: [], + }, + null, + ); + } else { + getCheckModal().show( + { + label: data.itemHint, + options: [], + }, + null, + ); + } + } else if (itemStage == ItemStage.Obtained) { + getPlayerProgress().deliverThrallItem(this.thrall); + if (lifeStage != LifeStage.Dead) { + getCheckModal().show( + { + label: data.deliveryMessage, + options: [], + }, + null, + ); + } + } else { + if (lifeStage == LifeStage.Dead) { + // nothing happens + } else if (this.rewarded) { + // nothing happens + } else { + this.rewarded = true; + getCheckModal().show( + { + label: data.rewardMessage, + options: [], + }, + null, + ); + data.rewardCallback(); + } + } + + // getCheckModal().show(this.check, () => (cell.pickup = null)); + return true; + } +} + +export class ThrallItemPickup { + thrall: Thrall; + + constructor(thrall: Thrall) { + this.thrall = thrall; + } + + computeCostToClick() { + return 100; + } + + isObstructive() { + return false; + } + + drawFloor() {} + drawInAir(gridArt: GridArt) { + let data = getThralls().get(this.thrall); + + D.drawSprite(data.sprite, gridArt.project(2), 3, { + xScale: 2.0, + yScale: 2.0, + }); + } + + onClick(cell: CellView): boolean { + let data = getThralls().get(this.thrall); + + cell.pickup = null; + getCheckModal().show( + { + label: data.itemPickupMessage, + options: [], + }, + null, + ); + getPlayerProgress().obtainThrallItem(this.thrall); + return true; + } +} diff --git a/src/playerprogress.ts b/src/playerprogress.ts index 76d4264..9c5576a 100644 --- a/src/playerprogress.ts +++ b/src/playerprogress.ts @@ -1,6 +1,6 @@ import { ALL_STATS, Skill, Stat, SuccessorOption, Wish } from "./datatypes.ts"; import { getSkills } from "./skills.ts"; -import { getThralls, LifeStage, Thrall } from "./thralls.ts"; +import { getThralls, ItemStage, LifeStage, Thrall } from "./thralls.ts"; export class PlayerProgress { #name: string; @@ -15,6 +15,8 @@ export class PlayerProgress { #untrimmedSkillsAvailable: Skill[]; #thrallsUnlocked: number[]; #thrallDamage: Record; + #thrallsObtainedItem: number[]; + #thrallsDeliveredItem: number[]; constructor(asSuccessor: SuccessorOption, withWish: Wish | null) { this.#name = asSuccessor.name; @@ -29,6 +31,8 @@ export class PlayerProgress { this.#untrimmedSkillsAvailable = []; this.#thrallsUnlocked = []; this.#thrallDamage = {}; + this.#thrallsObtainedItem = []; + this.#thrallsDeliveredItem = []; this.refill(); } @@ -232,7 +236,6 @@ export class PlayerProgress { getThrallLifeStage(thrall: Thrall): LifeStage { let damage = this.#thrallDamage[thrall.id] ?? 0; - console.log(`damage: ${damage}`); if (damage < 0.5) { return LifeStage.Fresh; } @@ -247,6 +250,30 @@ export class PlayerProgress { } return LifeStage.Dead; } + + obtainThrallItem(thrall: Thrall) { + if (this.#thrallsObtainedItem.indexOf(thrall.id) != -1) { + return; + } + this.#thrallsObtainedItem.push(thrall.id); + } + + deliverThrallItem(thrall: Thrall) { + if (this.#thrallsDeliveredItem.indexOf(thrall.id) != -1) { + return; + } + this.#thrallsDeliveredItem.push(thrall.id); + } + + getThrallItemStage(thrall: Thrall): ItemStage { + if (this.#thrallsDeliveredItem.indexOf(thrall.id) != -1) { + return ItemStage.Delivered; + } + if (this.#thrallsObtainedItem.indexOf(thrall.id) != -1) { + return ItemStage.Obtained; + } + return ItemStage.Untouched; + } } let active: PlayerProgress | null = null; diff --git a/src/sprites.ts b/src/sprites.ts index 5a83957..5b916c2 100644 --- a/src/sprites.ts +++ b/src/sprites.ts @@ -57,41 +57,41 @@ export let sprThrallBat = new Sprite( imgThrallBat, new Size(24, 24), new Point(12, 12), - new Size(3, 1), - 3, + new Size(4, 1), + 4, ); export let sprThrallCharm = new Sprite( imgThrallCharm, new Size(24, 24), new Point(12, 12), - new Size(3, 1), - 3, + new Size(4, 1), + 4, ); export let sprThrallLore = new Sprite( imgThrallLore, new Size(24, 24), new Point(12, 12), - new Size(3, 1), - 3, + new Size(4, 1), + 4, ); export let sprThrallParty = new Sprite( imgThrallParty, new Size(24, 24), new Point(12, 12), - new Size(3, 1), - 3, + new Size(4, 1), + 4, ); export let sprThrallStare = new Sprite( imgThrallStare, new Size(24, 24), new Point(12, 12), - new Size(3, 1), - 3, + new Size(4, 1), + 4, ); export let sprThrallStealth = new Sprite( imgThrallStealth, new Size(24, 24), new Point(12, 12), - new Size(3, 1), - 3, + new Size(4, 1), + 4, ); diff --git a/src/thralls.ts b/src/thralls.ts index 51bbf84..6de2d12 100644 --- a/src/thralls.ts +++ b/src/thralls.ts @@ -22,6 +22,7 @@ import { sprThrallStealth, } from "./sprites.ts"; import { Sprite } from "./engine/internal/sprite.ts"; +import { getPlayerProgress } from "./playerprogress.ts"; export type Thrall = { id: number; @@ -57,6 +58,11 @@ export type ThrallData = { sprite: Sprite; posterCheck: CheckData; initialCheck: CheckData; + itemHint: string; + itemPickupMessage: string; + deliveryMessage: string; + rewardMessage: string; + rewardCallback: () => void; lifeStageText: Record; }; @@ -69,6 +75,12 @@ export enum LifeStage { Dead = "dead", } +export enum ItemStage { + Untouched = "untouched", + Obtained = "obtained", + Delivered = "delivered", +} + export type LifeStageText = { prebite: string; postbite: string; @@ -113,6 +125,16 @@ export let thrallParty = table.add({ }, ], }, + itemHint: + '"Ah. I lost my wedding ring in a poker game.\n\nNot _my_ wedding ring, I won it from a lady."', + itemPickupMessage: + "This antique wedding ring looks like it was worth at least fifty big blinds.", + deliveryMessage: + '"Oh, that? Yeah, I won it." And then lost it, apparently.\n\nHe\'s elated. He will never leave.', + rewardMessage: "Garrett showers you with INT!", + rewardCallback: () => { + getPlayerProgress().add("INT", 10); + }, lifeStageText: { fresh: { prebite: "Garrett flips a poker chip and mutters to himself.", @@ -175,6 +197,16 @@ export let thrallLore = table.add({ }, ], }, + itemHint: + "He sniffs his heels like a wolf.\nMaybe shattering his illusion would be good for him. Maybe it would be really bad...", + itemPickupMessage: + "You can't see yourself in this antique silver mirror. On the other hand, they say silver is effective against wolves.", + deliveryMessage: + "Lupin looks at his own reflection -- with interest, confusion, dismissal, and then deep satisfaction. He loves it. He will never leave.", + rewardMessage: "Lupin showers you with AGI!", + rewardCallback: () => { + getPlayerProgress().add("AGI", 10); + }, lifeStageText: { fresh: { prebite: "Lupin awoos quietly to himself.", @@ -234,6 +266,17 @@ export let thrallBat = table.add({ }, ], }, + itemHint: + "\"I'm from New Zealand, actually.\n\nThere's this regional dish -- I haven't had it in years...\"", + itemPickupMessage: + "This particular instance of gator food resembles an infamous Aotearoan entree: colonial goose.", + deliveryMessage: + 'Monica salivates. "This is... this is... simply exquisite!"\n\nShe is happy. She will never leave.', + rewardMessage: "Monica showers you with CHA and INT!", + rewardCallback: () => { + getPlayerProgress().add("CHA", 5); + getPlayerProgress().add("INT", 5); + }, lifeStageText: { fresh: { prebite: "Monica nibbles a pastry.", @@ -294,6 +337,15 @@ export let thrallCharm = table.add({ }, ], }, + itemHint: '"I wish I had some way to look at you... when you\'re not here."', + itemPickupMessage: + "Your photo is going to be in a lot of places if it gets out, but you've got the original.", + deliveryMessage: + "Renfield inhales sharply and widens his stance, trying to hide his physical reaction to your face. He is elated and will never leave.", + rewardMessage: "Renfield showers you with PSI!", + rewardCallback: () => { + getPlayerProgress().add("PSI", 10); + }, lifeStageText: { fresh: { prebite: "Renfield exposes the underside of his jaw.", @@ -351,6 +403,17 @@ export let thrallStealth = table.add({ }, ], }, + itemHint: + '"Do you know what a kobold is? They\'re like me but much smaller."', + itemPickupMessage: + "The freezer is empty except for this frozen kobold, who mutters something about collecting blood for its master.", + deliveryMessage: + "\"That? That's not mine.\" But she wants it. Now it's hers. She will never leave.", + rewardMessage: "Narthyss showers you with CHA and AGI!", + rewardCallback: () => { + getPlayerProgress().add("CHA", 5); + getPlayerProgress().add("AGI", 5); + }, lifeStageText: { fresh: { prebite: "Narthyss is producing a new track on her gamer PC.", @@ -409,6 +472,16 @@ export let thrallStare = table.add({ }, ], }, + itemHint: + "The slight syncopation of its beeping reminds you that it's missing a gear.", + itemPickupMessage: + "This glinting gear would be perfect for a malfunctioning robot.", + deliveryMessage: + "Ridley admires the gear but -- to your surprise -- refuses to jam it into its brain.\n\nThe pup is elated and will never leave.", + rewardMessage: "Ridley showers you with EXP!", + rewardCallback: () => { + getPlayerProgress().addExperience(100); + }, lifeStageText: { fresh: { prebite: "Ridley is solving math problems.", diff --git a/src/vaulttemplate.ts b/src/vaulttemplate.ts index 708cf9c..8ffc9e1 100644 --- a/src/vaulttemplate.ts +++ b/src/vaulttemplate.ts @@ -33,6 +33,7 @@ import { export type VaultTemplate = { stats: { primary: Stat; secondary: Stat }; thrall: () => Thrall; + thrallItem: () => Thrall; checks: [CheckData, CheckData]; }; @@ -41,6 +42,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ // zoo stats: { primary: "AGI", secondary: "PSI" }, thrall: () => thrallParty, + thrallItem: () => thrallBat, checks: [ { label: @@ -87,6 +89,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ // blood bank stats: { primary: "AGI", secondary: "INT" }, thrall: () => thrallLore, + thrallItem: () => thrallStealth, checks: [ { label: @@ -132,6 +135,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ // coffee shop stats: { primary: "PSI", secondary: "CHA" }, thrall: () => thrallBat, + thrallItem: () => thrallCharm, checks: [ { label: @@ -178,6 +182,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ // optometrist stats: { primary: "PSI", secondary: "PSI" }, thrall: () => thrallCharm, + thrallItem: () => thrallStare, checks: [ { label: @@ -224,6 +229,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ // club, stats: { primary: "CHA", secondary: "PSI" }, thrall: () => thrallStealth, + thrallItem: () => thrallParty, checks: [ { label: @@ -270,6 +276,7 @@ export const standardVaultTemplates: VaultTemplate[] = [ // library stats: { primary: "INT", secondary: "CHA" }, thrall: () => thrallStare, + thrallItem: () => thrallLore, checks: [ { label: