1 import { Request, Response, Router } from "express";
2 import { maxHp, maxVigor } from "../../shared/player";
3 import { authEndpoint } from '../auth';
4 import { logger } from "../lib/logger";
5 import { updatePlayer } from "../player";
6 import { getCityDetails, getService } from '../map';
7 import { sample } from 'lodash';
8 import { City, Location } from "../../shared/map";
9 import { renderPlayerBar } from "../views/player-bar";
10 import { BackToTown } from "../views/components/button";
12 export const router = Router();
14 type TextSegment = 'intro' | 'insufficient_money' | 'heal_successful';
16 type HealText = Record<TextSegment, string[]>;
20 const defaultTexts: HealText = {
22 `Welcome traveller, I am {{NAME}}, Healer of {{CITY_NAME}}`,
23 "Please come in traveller, I am {{NAME}}, Healer of {{CITY_NAME}}",
26 "Sorry friend, you don't have enough money..",
27 "Sorry, that won't be enough..",
28 "Healing is hard work.. I'm afraid that won't cover it.."
31 "I hope you feel better now",
32 "Good luck on your travels!",
33 "Glad to be of service..."
37 // overrides for specific areas
38 const playerTexts: Record<number, HealText> = {
41 'Welcome to Midfield traveller, I am Casim - healer in these parts',
42 'I am Casim the Healer here... how are you enjoying your stay at Midfield?'
45 'Sorry friend, you don\'t have enough money',
46 'Look.. I\'m sorry.. that won\'t be enough...'
54 'Ah, welcome to Wildegard, one of the few safehavens in the Akari Woods. I am Adovras, healer in these parts.',
55 'Welcome traveller, I am Adovras - healer in these parts'
58 `Sorry friend, you don't have enough money...`
61 "Hope this small healing will be helpful on your journeys"
67 'Ah, welcome traveler - I am Uthar, healer of Davelfell',
68 'Hello, I am Uthar, healer of Davelfell',
69 'Sorry I\'m a bit busy today, I am Uthar, healer of Davelfell'
72 "Bah, don't bother me if you don't have the money",
73 "Look, I'm very busy - come back when you have the money"
76 "*Fizz* *POOF* YOU'RE HEALED!"
81 function getText(type: TextSegment, location: Location, city: City): string {
82 let selected = sample(defaultTexts[type]);
84 if(playerTexts[location.id]) {
85 if(playerTexts[location.id][type].length) {
86 selected = sample(playerTexts[location.id][type]);
90 return selected.replace("{{NAME}}", location.name).replace("{{CITY_NAME}}", city.name);
94 router.get('/city/services/healer/:location_id', authEndpoint, async (req: Request, res: Response) => {
95 const service = await getService(parseInt(req.params.location_id));
96 const city = await getCityDetails(service.city_id);
98 if(!service || service.city_id !== req.player.city_id) {
99 logger.log(`Invalid location: [${req.params.location_id}]`);
103 const text: string[] = [];
105 text.push(`<p>"${getText('intro', service, city)}"</p>`);
107 if(req.player.hp === maxHp(req.player.constitution, req.player.level) && req.player.vigor === maxVigor(req.player.constitution, req.player.level)) {
108 text.push(`<p>You're already in peak condition!</p>`);
111 if(req.player.gold <= (healCost * 2)) {
112 text.push(`<p>You don't seem to have too much money... I guess I can do it for free this time...</p>`);
113 text.push(`<p><button type="button" hx-post="/city/services/healer/heal/${service.id}" hx-target="#explore">Heal for Free!</button></p>`);
116 text.push(`<p><button type="button" hx-post="/city/services/healer/heal/${service.id}" hx-target="#explore">Heal for ${healCost}g!</button></p>`);
122 <div class="city-title-wrapper"><div class="city-title">${service.city_name}</div></div>
123 <div class="city-details">
124 <h3 class="location-name"><span>${service.name}</span></h3>
125 <div class="service-in-town">
132 //res.send(`<div class="service-in-town">${text.join("\n")}</div>`);
137 router.post('/city/services/healer/heal/:location_id', authEndpoint, async (req: Request, res: Response) => {
138 const service = await getService(parseInt(req.params.location_id));
139 const city = await getCityDetails(service.city_id);
141 if(!service || service.city_id !== req.player.city_id) {
142 logger.log(`Invalid location: [${req.params.location_id}]`);
146 const text: string[] = [];
147 const cost = req.player.gold <= (healCost * 2) ? 0 : healCost;
149 if(req.player.gold < cost) {
150 text.push(`<p>${getText('insufficient_money', service, city)}</p>`)
153 req.player.hp = maxHp(req.player.constitution, req.player.level);
154 req.player.vigor = maxVigor(req.player.constitution, req.player.level);
155 req.player.gold -= cost;
157 await updatePlayer(req.player);
159 text.push(`<p>${getText('heal_successful', service, city)}</p>`);
163 <div class="city-title-wrapper"><div class="city-title">${service.city_name}</div></div>
164 <div class="city-details">
165 <h3 class="location-name"><span>${service.name}</span></h3>
166 <div class="service-in-town">
171 ${renderPlayerBar(req.player)}