Thralls deteriorate over many bites
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| import {DrawPile} from "./drawpile.ts"; | ||||
| import {CheckData, CheckDataOption} from "./newmap.ts"; | ||||
| import {CheckData, CheckDataOption, ChoiceOption} from "./newmap.ts"; | ||||
| import {getPartLocation, withCamera} from "./layout.ts"; | ||||
| import {AlignX, AlignY, Point, Rect, Size} from "./engine/datatypes.ts"; | ||||
| import {D} from "./engine/public.ts"; | ||||
| @@ -81,21 +81,34 @@ export class CheckModal { | ||||
|  | ||||
|     let options = check.options; | ||||
|  | ||||
|     let addOptionButton = (option: CheckDataOption, rect: Rect) => { | ||||
|       let skill = option.skill(); | ||||
|       let skillName = getSkills().get(skill).profile.name; | ||||
|       let hasSkill = getPlayerProgress().hasLearned(skill); | ||||
|       // hasSkill ||= true; | ||||
|       let optionLabel: string | ||||
|       if (hasSkill) { | ||||
|         optionLabel = `[${skillName}] ${option.unlockable}`; | ||||
|     let addOptionButton = (option: CheckDataOption | ChoiceOption, rect: Rect) => { | ||||
|       let accomplished: boolean; | ||||
|       let optionLabel: string; | ||||
|       let resultMessage: string; | ||||
|       if ((option as ChoiceOption).isChoice) { | ||||
|         // TODO: Use OOP here | ||||
|         option = option as ChoiceOption; | ||||
|         accomplished = option.countsAsSuccess; | ||||
|         optionLabel = option.unlockable; | ||||
|         resultMessage = option.success; | ||||
|  | ||||
|       } else { | ||||
|         optionLabel = `[Needs ${skillName}] ${option.locked}`; | ||||
|         option = option as CheckDataOption; | ||||
|         let skill = option.skill(); | ||||
|         let skillName = getSkills().get(skill).profile.name; | ||||
|         let hasSkill = getPlayerProgress().hasLearned(skill); | ||||
|         // hasSkill ||= true; | ||||
|         if (hasSkill) { | ||||
|           optionLabel = `[${skillName}] ${option.unlockable}`; | ||||
|         } else { | ||||
|           optionLabel = `[Needs ${skillName}] ${option.locked}`; | ||||
|         } | ||||
|         resultMessage = hasSkill ? option.success : option.failure; | ||||
|       } | ||||
|       addButton(this.#drawpile, optionLabel, rect, true, () => { | ||||
|         this.#success = hasSkill ? option.success : option.failure; | ||||
|         this.#success = resultMessage; | ||||
|  | ||||
|         if (hasSkill) { | ||||
|         if (accomplished) { | ||||
|           let cb = this.#callback; | ||||
|           if (cb) { cb(); } | ||||
|         } | ||||
|   | ||||
| @@ -251,7 +251,7 @@ export function initHuntMode(huntMode: HuntMode) { | ||||
|  | ||||
| export function getHuntMode() { | ||||
|   if (active == null) { | ||||
|     throw `trying to get player progress before it has been initialized` | ||||
|     throw new Error(`trying to get hunt mode before it has been initialized`) | ||||
|   } | ||||
|   return active; | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import {Architecture, LoadedNewMap} from "./newmap.ts"; | ||||
| import {Grid, Point} from "./engine/datatypes.ts"; | ||||
| import {getThralls} from "./thralls.ts"; | ||||
| import {LadderPickup, ThrallPosterPickup} from "./pickups.ts"; | ||||
| import {LadderPickup, ThrallPosterPickup, ThrallRecruitedPickup} from "./pickups.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
|  | ||||
| const BASIC_PLAN = Grid.createGridFromMultilineString(` | ||||
| ##################### | ||||
| @@ -29,12 +30,16 @@ export function generateManor(): LoadedNewMap { | ||||
|       let cell = map.get(xy); | ||||
|  | ||||
|       let placeThrall = (ix: number) => { | ||||
|         // TODO | ||||
|         cell.architecture = Architecture.Floor; | ||||
|         if (true || getPlayerProgress().isThrallUnlocked(thralls[ix])) { | ||||
|           cell.pickup = new ThrallRecruitedPickup(thralls[ix]); | ||||
|         } | ||||
|       }; | ||||
|       let placeThrallPoster = (ix: number) => { | ||||
|         cell.architecture = Architecture.Floor; | ||||
|         cell.pickup = new ThrallPosterPickup(thralls[ix]); | ||||
|         if (!getPlayerProgress().isThrallUnlocked(thralls[ix])) { | ||||
|           cell.pickup = new ThrallPosterPickup(thralls[ix]); | ||||
|         } | ||||
|       }; | ||||
|  | ||||
|       switch (BASIC_PLAN.get(xy)) { | ||||
|   | ||||
| @@ -4,6 +4,7 @@ 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"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
|  | ||||
| const WIDTH = 19; | ||||
| const HEIGHT = 19; | ||||
| @@ -301,9 +302,10 @@ function carveVault(knife: Knife, room: Rect, vaultTemplate: VaultTemplate) { | ||||
|     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 (!getPlayerProgress().isThrallUnlocked(thrall)) { | ||||
|         cell.pickup = new ThrallPickup(thrall); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (b.contains(goodie)) { | ||||
|   | ||||
| @@ -6,7 +6,14 @@ export enum Architecture { Wall, Floor } | ||||
|  | ||||
| export type CheckData = { | ||||
|   label: string, | ||||
|   options: CheckDataOption[], | ||||
|   options: (CheckDataOption | ChoiceOption)[], | ||||
| } | ||||
|  | ||||
| export type ChoiceOption = { | ||||
|   isChoice: true, | ||||
|   countsAsSuccess: boolean, | ||||
|   unlockable: string, | ||||
|   success: string, | ||||
| } | ||||
| export type CheckDataOption = { | ||||
|   skill: () => Skill, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import {getThralls, Thrall} from "./thralls.ts"; | ||||
| import {getThralls, LifeStage, Thrall} from "./thralls.ts"; | ||||
| import {CellView, CheckData} from "./newmap.ts"; | ||||
| import {getPlayerProgress} from "./playerprogress.ts"; | ||||
| import {getHuntMode, HuntMode, initHuntMode} from "./huntmode.ts"; | ||||
| @@ -9,6 +9,7 @@ import {sprLadder, sprLock, sprResourcePickup, sprStatPickup} from "./sprites.ts | ||||
| import {GridArt} from "./gridart.ts"; | ||||
| import {getCheckModal} from "./checkmodal.ts"; | ||||
| import {Point} from "./engine/datatypes.ts"; | ||||
| import {choose} from "./utils.ts"; | ||||
|  | ||||
| export type Pickup | ||||
|   = LockPickup | ||||
| @@ -17,6 +18,7 @@ export type Pickup | ||||
|   | LadderPickup | ||||
|   | ThrallPickup | ||||
|   | ThrallPosterPickup | ||||
|   | ThrallRecruitedPickup | ||||
|  | ||||
| export class LockPickup { | ||||
|   check: CheckData; | ||||
| @@ -146,7 +148,10 @@ export class ThrallPickup { | ||||
|  | ||||
|   onClick(cell: CellView): boolean { | ||||
|     let data = getThralls().get(this.thrall); | ||||
|     getCheckModal().show(data.initialCheck, () => cell.pickup = null); | ||||
|     getCheckModal().show(data.initialCheck, () => { | ||||
|       getPlayerProgress().unlockThrall(this.thrall); | ||||
|       cell.pickup = null | ||||
|     }); | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
| @@ -177,3 +182,71 @@ export class ThrallPosterPickup { | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| export class ThrallRecruitedPickup { | ||||
|   thrall: Thrall; | ||||
|   bitten: boolean; | ||||
|  | ||||
|   constructor(thrall: Thrall) { | ||||
|     this.thrall = thrall; | ||||
|     this.bitten = false; | ||||
|   } | ||||
|  | ||||
|   computeCostToClick() { return 0; } | ||||
|  | ||||
|   isObstructive() { return false; } | ||||
|  | ||||
|   drawFloor() { } | ||||
|   drawInAir(gridArt: GridArt) { | ||||
|     let data = getThralls().get(this.thrall); | ||||
|     let lifeStage = getPlayerProgress().getThrallLifeStage(this.thrall); | ||||
|     let ix = 0; | ||||
|     let rot = 0; | ||||
|  | ||||
|     if (lifeStage == LifeStage.Vampirized) { ix = 1; } | ||||
|     if (lifeStage == LifeStage.Dead) { ix = 1; rot = 270; } | ||||
|     D.drawSprite(data.sprite, gridArt.project(0.0), ix, { | ||||
|       xScale: 2.0, | ||||
|       yScale: 2.0, | ||||
|       angle: rot | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   onClick(_cell: CellView): boolean { | ||||
|     if (this.bitten) { return true; } | ||||
|  | ||||
|     let data = getThralls().get(this.thrall); | ||||
|     let lifeStage = getPlayerProgress().getThrallLifeStage(this.thrall); | ||||
|     let text = data.lifeStageText[lifeStage]; | ||||
|     getCheckModal().show({ | ||||
|       label: `${text.prebite}`, | ||||
|       options: [ | ||||
|         { | ||||
|           isChoice: true, | ||||
|           countsAsSuccess: true, | ||||
|           unlockable: "Bite!", | ||||
|           success: text.postbite, | ||||
|         }, | ||||
|         { | ||||
|           isChoice: true, | ||||
|           countsAsSuccess: false, | ||||
|           unlockable: "Refrain", | ||||
|           success: "Maybe next time." | ||||
|         } | ||||
|       ] | ||||
|     }, () => { | ||||
|       this.bitten = true; | ||||
|       getPlayerProgress().addBlood( | ||||
|         lifeStage == LifeStage.Fresh ? 1000 : | ||||
|           lifeStage == LifeStage.Average ? 500 : | ||||
|             lifeStage == LifeStage.Poor ? 300 : | ||||
|               lifeStage == LifeStage.Vampirized ? 1500 : // lethal bite | ||||
|                 // lifeStage == LifeStage.Dead ? | ||||
|                 100 | ||||
|       ); | ||||
|       getPlayerProgress().damageThrall(this.thrall, choose([0.9])) | ||||
|     }); | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| import {ALL_STATS, Skill, Stat, SuccessorOption, Wish} from "./datatypes.ts"; | ||||
| import {getSkills} from "./skills.ts"; | ||||
| import {getThralls, LifeStage, Thrall} from "./thralls.ts"; | ||||
|  | ||||
| export class PlayerProgress { | ||||
|   #name: string | ||||
| @@ -12,6 +13,8 @@ export class PlayerProgress { | ||||
|   #itemsPurloined: number | ||||
|   #skillsLearned: number[]  // use the raw ID representation for indexOf | ||||
|   #untrimmedSkillsAvailable: Skill[] | ||||
|   #thrallsUnlocked: number[] | ||||
|   #thrallDamage: Record<number, number> | ||||
|  | ||||
|   constructor(asSuccessor: SuccessorOption, withWish: Wish | null) { | ||||
|     this.#name = asSuccessor.name; | ||||
| @@ -24,6 +27,8 @@ export class PlayerProgress { | ||||
|     this.#itemsPurloined = 0; | ||||
|     this.#skillsLearned = [] | ||||
|     this.#untrimmedSkillsAvailable = []; | ||||
|     this.#thrallsUnlocked = []; | ||||
|     this.#thrallDamage = {}; | ||||
|  | ||||
|     this.refill(); | ||||
|   } | ||||
| @@ -52,6 +57,12 @@ export class PlayerProgress { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     for (let thrall of getThralls().getAll()) { | ||||
|       let stage = this.getThrallLifeStage(thrall); | ||||
|       if (stage == LifeStage.Vampirized || stage == LifeStage.Dead) { continue; } | ||||
|       this.#thrallDamage[thrall.id] = Math.max(this.#thrallDamage[thrall.id] ?? 0 - 0.2, 0.0); | ||||
|     } | ||||
|  | ||||
|     this.#untrimmedSkillsAvailable = learnableSkills | ||||
|   } | ||||
|  | ||||
| @@ -175,7 +186,38 @@ export class PlayerProgress { | ||||
|   } | ||||
|  | ||||
|   getStats() { return {...this.#stats} } | ||||
|   getTalents() { return {...this.#talents} } } | ||||
|   getTalents() { return {...this.#talents} } | ||||
|  | ||||
|   unlockThrall(thrall: Thrall) { | ||||
|     let {id} = thrall; | ||||
|     if (this.#thrallsUnlocked.indexOf(id) != -1) { return; } | ||||
|     this.#thrallsUnlocked.push(id); | ||||
|   } | ||||
|  | ||||
|   isThrallUnlocked(thrall: Thrall) { | ||||
|     return this.#thrallsUnlocked.indexOf(thrall.id) != -1; | ||||
|   } | ||||
|  | ||||
|   damageThrall(thrall: Thrall, amount: number) { | ||||
|     if (amount <= 0.0) { | ||||
|       throw new Error(`damage must be some positive amount, not ${amount}`) | ||||
|     } | ||||
|     let stage = this.getThrallLifeStage(thrall); | ||||
|  | ||||
|     if (stage == LifeStage.Vampirized) { this.#thrallDamage[thrall.id] = 4.0; } | ||||
|     this.#thrallDamage[thrall.id] = (this.#thrallDamage[thrall.id] ?? 0.0) + amount | ||||
|   } | ||||
|  | ||||
|   getThrallLifeStage(thrall: Thrall): LifeStage { | ||||
|     let damage = this.#thrallDamage[thrall.id] ?? 0; | ||||
|     console.log(`damage: ${damage}`) | ||||
|     if (damage < 0.5) { return LifeStage.Fresh; } | ||||
|     if (damage < 1.75) { return LifeStage.Average; } | ||||
|     if (damage < 3.0) { return LifeStage.Poor; } | ||||
|     if (damage < 4.0) { return LifeStage.Vampirized; } | ||||
|     return LifeStage.Dead; | ||||
|   } | ||||
| } | ||||
|  | ||||
| let active: PlayerProgress | null = null; | ||||
|  | ||||
| @@ -185,7 +227,7 @@ export function initPlayerProgress(asSuccessor: SuccessorOption, withWish: Wish | ||||
|  | ||||
| export function getPlayerProgress(): PlayerProgress { | ||||
|   if (active == null) { | ||||
|     throw `trying to get player progress before it has been initialized` | ||||
|     throw new Error(`trying to get player progress before it has been initialized`) | ||||
|   } | ||||
|   return active | ||||
| } | ||||
| @@ -22,8 +22,8 @@ export class StateManager { | ||||
|  | ||||
|   startGame(asSuccessor: SuccessorOption, withWish: Wish | null) { | ||||
|     this.#turn = 1; | ||||
|     initHuntMode(new HuntMode(1, generateManor())); | ||||
|     initPlayerProgress(asSuccessor, withWish); | ||||
|     initHuntMode(new HuntMode(1, generateManor())); | ||||
|   } | ||||
|  | ||||
|   advance() { | ||||
|   | ||||
							
								
								
									
										159
									
								
								src/thralls.ts
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								src/thralls.ts
									
									
									
									
									
								
							| @@ -57,6 +57,21 @@ export type ThrallData = { | ||||
|   sprite: Sprite, | ||||
|   posterCheck: CheckData, | ||||
|   initialCheck: CheckData, | ||||
|  | ||||
|   lifeStageText: Record<LifeStage, LifeStageText> | ||||
| } | ||||
|  | ||||
| export enum LifeStage { | ||||
|   Fresh = "fresh", | ||||
|   Average = "average", | ||||
|   Poor = "poor", | ||||
|   Vampirized = "vampirized", | ||||
|   Dead = "dead", | ||||
| } | ||||
|  | ||||
| export type LifeStageText = { | ||||
|   prebite: string, | ||||
|   postbite: string, | ||||
| } | ||||
|  | ||||
| let table = new ThrallsTable(); | ||||
| @@ -94,7 +109,29 @@ export let thrallParty = table.add({ | ||||
|         success: "TODO", | ||||
|       }, | ||||
|     ] | ||||
|   } | ||||
|   }, | ||||
|   lifeStageText: { | ||||
|     fresh: { | ||||
|       prebite: "Garrett flips a poker chip and mutters to himself.", | ||||
|       postbite: "You plunge your fangs into his feathered neck and feed.", | ||||
|     }, | ||||
|     average: { | ||||
|       prebite: "Garrett looks a little less fresh than last time. He's resigned to the fate of being bitten.", | ||||
|       postbite: "You puncture him in almost the same place as before and take a moderate amount of blood from his veins." | ||||
|     }, | ||||
|     poor: { | ||||
|       prebite: "Garrett, limp in bed, doesn't look like he's doing so well. He's pale and he's breathing heavily.", | ||||
|       postbite: "\"Please...\" you hear him moan as you force him into the state of ecstasy that brings compliance.", | ||||
|     }, | ||||
|     vampirized: { | ||||
|       prebite: "Garrett looks about as cold and pale as you. Another bite may kill him.", | ||||
|       postbite: "The final bite is always the most satisfying. You feel little emotion as you hold the body of a dead crow in your arms.", | ||||
|     }, | ||||
|     dead: { | ||||
|       prebite: "This bird is dead, on account of the fact that you killed him with your teeth.", | ||||
|       postbite: "The blood in his veins hasn't coagulated yet. There's still more. Still more...", | ||||
|     } | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| export let thrallLore = table.add({ | ||||
| @@ -122,7 +159,29 @@ export let thrallLore = table.add({ | ||||
|         success: "Taken aback at how well you know the cheer, he freezes -- then joins you with a similar howl.", | ||||
|       }, | ||||
|     ] | ||||
|   } | ||||
|   }, | ||||
|   lifeStageText: { | ||||
|     fresh: { | ||||
|       prebite: "Lupin awoos quietly to himself.", | ||||
|       postbite: "You bite the raccoon and drink his blood.", | ||||
|     }, | ||||
|     average: { | ||||
|       prebite: "The color in Lupin's cheeks is beginning to fade. He's becoming accustomed to your bite.", | ||||
|       postbite: "He'll let you do anything to him if you make him feel good, so you make him feel good. Fresh blood...", | ||||
|     }, | ||||
|     poor: { | ||||
|       prebite: "Lupin is barely conscious. There's drool at the edges of his mouth and his eyes are glassy.", | ||||
|       postbite: "This is no concern to you. You're hungry. You need this.", | ||||
|     }, | ||||
|     vampirized: { | ||||
|       prebite: "Lupin's fangs have erupted partially from his jaw. You've taken enough. More will kill him.", | ||||
|       postbite: "His life is less valuable to you than his warm, delicious blood. You need sustenance.", | ||||
|     }, | ||||
|     dead: { | ||||
|       prebite: "This dead raccoon used to be full of blood. Now he's empty. Isn't that a shame?", | ||||
|       postbite: "You root around in his neck. His decaying muscle is soft.", | ||||
|     } | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| export let thrallBat = table.add({ | ||||
| @@ -150,7 +209,29 @@ export let thrallBat = table.add({ | ||||
|         success: "\"Settle down!\" she says, lowering your volume with a sweep of her hand. \"It's true though.\"", | ||||
|       }, | ||||
|     ] | ||||
|   } | ||||
|   }, | ||||
|   lifeStageText: { | ||||
|     fresh: { | ||||
|       prebite: "Monica nibbles a pastry.", | ||||
|       postbite: "You dig your teeth into the koala's mortal flesh.", | ||||
|     }, | ||||
|     average: { | ||||
|       prebite: "Monica doesn't look as fresh and vibrant as you recall from her TV show.", | ||||
|       postbite: "A little bite seems to improve her mood, even though she twitches involuntarily as if you're hurting her.", | ||||
|     }, | ||||
|     poor: { | ||||
|       prebite: "Monica weakly raises a hand as if to stop you from approaching for a bite.", | ||||
|       postbite: "You press yourself to her body and embrace her. Her fingers curl around you and she lets you drink your fill.", | ||||
|     }, | ||||
|     vampirized: { | ||||
|       prebite: "Monica shows no interest in food. She's lethargic, apathetic. A bite would kill her, but you're thirsty.", | ||||
|       postbite: "Her last words are too quiet to make out, but you're not interested in them. Nothing matters except blood.", | ||||
|     }, | ||||
|     dead: { | ||||
|       prebite: "This used to be Monica. Now it's just her corpse.", | ||||
|       postbite: "She's very delicate, even as a corpse.", | ||||
|     } | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| export let thrallCharm = table.add({ | ||||
| @@ -178,7 +259,29 @@ export let thrallCharm = table.add({ | ||||
|         success: "His mind overflows with fantasy, and when you let a glint of fang peek through, he claps his arms affectionately around your supercold torso.", | ||||
|       }, | ||||
|     ] | ||||
|   } | ||||
|   }, | ||||
|   lifeStageText: { | ||||
|     fresh: { | ||||
|       prebite: "Renfield exposes the underside of his jaw.", | ||||
|       postbite: "You press your face flat to his armorlike scales and part them with your teeth.", | ||||
|     }, | ||||
|     average: { | ||||
|       prebite: "Renfield seems relieved to be free of all that extra blood.", | ||||
|       postbite: "You taste a little bit of fear as you press yourself to him. Is he less devoted than you thought?", | ||||
|     }, | ||||
|     poor: { | ||||
|       prebite: "Renfield presses his face to the window. He won't resist you and won't look at you. He does not want your bite.", | ||||
|       postbite: "Does it matter that he doesn't want your bite? You're hungry. He should have known you would do this.", | ||||
|     }, | ||||
|     vampirized: { | ||||
|       prebite: "Renfield is repulsed by the vampiric features that his body has begun to display. Another bite would kill him.", | ||||
|       postbite: "Better to free him if he's going to behave like this anyways.", | ||||
|     }, | ||||
|     dead: { | ||||
|       prebite: "Here lies a crocodile who really, really liked vampires.", | ||||
|       postbite: "At least in death he can't backslide on his promise to feed you.", | ||||
|     } | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| export let thrallStealth = table.add({ | ||||
| @@ -206,7 +309,29 @@ export let thrallStealth = table.add({ | ||||
|         success: "TODO", | ||||
|       }, | ||||
|     ] | ||||
|   } | ||||
|   }, | ||||
|   lifeStageText: { | ||||
|     fresh: { | ||||
|       prebite: "Narthyss is producing a new track on her gamer PC.", | ||||
|       postbite: "You push her mouse and keyboard aside and focus her attention on your eyes.", | ||||
|     }, | ||||
|     average: { | ||||
|       prebite: "Narthyss has no desire to be interrupted, but you're thirsty.", | ||||
|       postbite: "You dazzle her with your eyes and nip her neck with erotic enthusiasm.", | ||||
|     }, | ||||
|     poor: { | ||||
|       prebite: "Narthyss knows better than to resist you -- but you sense that you've taken more than she wants.", | ||||
|       postbite: "Her response to your approach is automatic. No matter what she tells you, you show fang -- she shows neck.", | ||||
|     }, | ||||
|     vampirized: { | ||||
|       prebite: "Narthyss' fire has gone out. She's a creature of venom and blood now. Another bite would kill her.", | ||||
|       postbite: "Now she is a creature of nothing at all.", | ||||
|     }, | ||||
|     dead: { | ||||
|       prebite: "Narthyss used to be a dragon. Now she's dead.", | ||||
|       postbite: "Dragons decay slowly. There's still some warmth in there if you bury your fangs deep enough.", | ||||
|     } | ||||
|   }, | ||||
| }) | ||||
|  | ||||
| export let thrallStare = table.add({ | ||||
| @@ -234,5 +359,27 @@ export let thrallStare = table.add({ | ||||
|         success: "TODO", | ||||
|       }, | ||||
|     ] | ||||
|   } | ||||
|   }, | ||||
|   lifeStageText: { | ||||
|     fresh: { | ||||
|       prebite: "Ridley is solving math problems.", | ||||
|       postbite: "You delicately sip electronic blood from the robot's neck." | ||||
|     }, | ||||
|     average: { | ||||
|       prebite: "Ridley's display brightens at your presence. It looks damaged.", | ||||
|       postbite: "Damaged or not -- the robot has blood and you need it badly.", | ||||
|     }, | ||||
|     poor: { | ||||
|       prebite: "The symbols on Ridley's screen have less and less rational connection. It's begging to be fed upon.", | ||||
|       postbite: "The quality of the robot's blood decreases with every bite, but the taste is still pleasurable." | ||||
|     }, | ||||
|     vampirized: { | ||||
|       prebite: "With no concern for its survival, the now-fanged robot begs you for one more bite. This would kill it.", | ||||
|       postbite: "Nothing is stronger than your need for blood -- and its desperation has put you in quite a state...", | ||||
|     }, | ||||
|     dead: { | ||||
|       prebite: "Ridley was a robot and now Ridley is a dead robot.", | ||||
|       postbite: "Tastes zappy.", | ||||
|     } | ||||
|   }, | ||||
| }) | ||||
		Reference in New Issue
	
	Block a user