chore(release): 0.2.5
[risinglegends.git] / src / server / locations / healer / index.ts
1 import { Request, Response, Router } from "express";
2 import { maxHp, Player } from "../../../shared/player";
3 import { authEndpoint } from '../../auth';
4 import { logger } from "../../lib/logger";
5 import { loadPlayer, 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 { getEquippedItems } from "../../inventory";
11
12 export const router = Router();
13
14 type TextSegment = 'intro' | 'insufficient_money' | 'heal_successful';
15
16 type HealText = Record<TextSegment, string[]>;
17
18 const healCost = 10;
19
20 const defaultTexts: HealText = {
21   intro: [
22     `Welcome traveller, I am {{NAME}}, Healer of {{CITY_NAME}}`,
23     "Please come in traveller, I am {{NAME}}, Healer of {{CITY_NAME}}",
24   ],
25   insufficient_money: [
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.."
29   ],
30   heal_successful: [
31     "I hope you feel better now",
32     "Good luck on your travels!",
33     "Glad to be of service..."
34   ]
35 };
36
37 // overrides for specific areas
38 const playerTexts: Record<number, HealText> = {
39   [8]: {
40     intro: [
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?'
43     ],
44     insufficient_money: [
45       'Sorry friend, you don\'t have enough money',
46       'Look.. I\'m sorry.. that won\'t be enough...'
47     ],
48     heal_successful: [
49       'Glad to help!'
50     ]
51   },
52   [16]: {
53     intro: [
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'
56     ],
57     insufficient_money: [
58       `Sorry friend, you don't have enough money...`
59     ],
60     heal_successful: [
61       "Hope this small healing will be helpful on your journeys"
62     ]
63
64   },
65   [11]: {
66     intro: [
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'
70     ],
71     insufficient_money: [
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"
74     ],
75     heal_successful: [
76       "*Fizz* *POOF* YOU'RE HEALED!"
77     ]
78   }
79 }
80
81 function getText(type: TextSegment, location: Location, city: City): string {
82   let selected = sample(defaultTexts[type]);
83
84   if(playerTexts[location.id]) {
85     if(playerTexts[location.id][type].length) {
86       selected = sample(playerTexts[location.id][type]);
87     }
88   }
89
90   return selected.replace("{{NAME}}", location.name).replace("{{CITY_NAME}}", city.name);
91
92 }
93
94 router.get('/city/services/city:services:healer/:location_id', authEndpoint, async (req: Request, res: Response) => {
95   const authToken = req.headers['x-authtoken']!.toString();
96   const player: Player = await loadPlayer(authToken)
97   if(!player) {
98     logger.log(`Couldnt find player with id ${authToken}`);
99     return res.sendStatus(400);
100   }
101
102   const service = await getService(parseInt(req.params.location_id));
103   const city = await getCityDetails(service.city_id);
104
105   if(!service || service.city_id !== player.city_id) {
106     logger.log(`Invalid location: [${req.params.location_id}]`);
107     res.sendStatus(400);
108   }
109
110   const text: string[] = [];
111
112   text.push(`<p><b>${service.name}</b></p>`);
113   text.push(`<p>"${getText('intro', service, city)}"</p>`);
114
115
116   if(player.hp === maxHp(player.constitution, player.level)) {
117     text.push(`<p>You're already at full health?</p>`);
118   }
119   else {
120     if(player.gold <= (healCost * 2)) {
121       text.push(`<p>You don't seem to have too much money... I guess I can do it for free this time...</p>`);
122       text.push(`<p><button type="button" hx-post="/city/services/city:services:healer:heal/${service.id}" hx-target="#explore">Heal for Free!</button></p>`);
123     }
124     else {
125       text.push(`<p><button type="button" hx-post="/city/services/city:services:healer:heal/${service.id}" hx-target="#explore">Heal for ${healCost}g!</button></p>`);
126     }
127
128   }
129
130   res.send(`<div>${text.join("\n")}</div>`);
131 });
132
133
134
135 router.post('/city/services/city:services:healer:heal/:location_id', authEndpoint, async (req: Request, res: Response) => {
136   const authToken = req.headers['x-authtoken']!.toString();
137   const player: Player = await loadPlayer(authToken)
138   if(!player) {
139     logger.log(`Couldnt find player with id ${authToken}`);
140     return res.sendStatus(400);
141   }
142
143   const service = await getService(parseInt(req.params.location_id));
144   const city = await getCityDetails(service.city_id);
145
146   if(!service || service.city_id !== player.city_id) {
147     logger.log(`Invalid location: [${req.params.location_id}]`);
148     res.sendStatus(400);
149   }
150
151   const text: string[] = [];
152   text.push(`<p><b>${service.name}</b></p>`);
153
154   const cost = player.gold <= (healCost * 2) ? 0 : healCost;
155
156   if(player.gold < cost) {
157     text.push(`<p>${getText('insufficient_money', service, city)}</p>`)
158     res.send(`<div>${text.join("\n")}</div>`);
159   }
160   else {
161     player.hp = maxHp(player.constitution, player.level);
162     player.gold -= cost;
163
164     await updatePlayer(player);
165     const inventory = await getEquippedItems(player.id);
166
167     text.push(`<p>${getText('heal_successful', service, city)}</p>`);
168     text.push('<p><button hx-get="/player/explore" hx-target="#explore">Back to Town</button></p>');
169     res.send(`<div>${text.join("\n")}</div>` + renderPlayerBar(player, inventory));
170   }
171 });