chore(release): 0.3.0
[risinglegends.git] / src / server / locations / healer / index.ts
1 import { Response, Router } from "express";
2 import { maxHp, maxVigor } from "../../../shared/player";
3 import { authEndpoint, AuthRequest } 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
11 export const router = Router();
12
13 type TextSegment = 'intro' | 'insufficient_money' | 'heal_successful';
14
15 type HealText = Record<TextSegment, string[]>;
16
17 const healCost = 10;
18
19 const defaultTexts: HealText = {
20   intro: [
21     `Welcome traveller, I am {{NAME}}, Healer of {{CITY_NAME}}`,
22     "Please come in traveller, I am {{NAME}}, Healer of {{CITY_NAME}}",
23   ],
24   insufficient_money: [
25     "Sorry friend, you don't have enough money..",
26     "Sorry, that won't be enough..",
27     "Healing is hard work.. I'm afraid that won't cover it.."
28   ],
29   heal_successful: [
30     "I hope you feel better now",
31     "Good luck on your travels!",
32     "Glad to be of service..."
33   ]
34 };
35
36 // overrides for specific areas
37 const playerTexts: Record<number, HealText> = {
38   [8]: {
39     intro: [
40       'Welcome to Midfield traveller, I am Casim - healer in these parts',
41       'I am Casim the Healer here... how are you enjoying your stay at Midfield?'
42     ],
43     insufficient_money: [
44       'Sorry friend, you don\'t have enough money',
45       'Look.. I\'m sorry.. that won\'t be enough...'
46     ],
47     heal_successful: [
48       'Glad to help!'
49     ]
50   },
51   [16]: {
52     intro: [
53       'Ah, welcome to Wildegard, one of the few safehavens in the Akari Woods. I am Adovras, healer in these parts.',
54       'Welcome traveller, I am Adovras - healer in these parts'
55     ],
56     insufficient_money: [
57       `Sorry friend, you don't have enough money...`
58     ],
59     heal_successful: [
60       "Hope this small healing will be helpful on your journeys"
61     ]
62
63   },
64   [11]: {
65     intro: [
66       'Ah, welcome traveler - I am Uthar, healer of Davelfell',
67       'Hello, I am Uthar, healer of Davelfell',
68       'Sorry I\'m a bit busy today, I am Uthar, healer of Davelfell'
69     ],
70     insufficient_money: [
71       "Bah, don't bother me if you don't have the money",
72       "Look, I'm very busy - come back when you have the money"
73     ],
74     heal_successful: [
75       "*Fizz* *POOF* YOU'RE HEALED!"
76     ]
77   }
78 }
79
80 function getText(type: TextSegment, location: Location, city: City): string {
81   let selected = sample(defaultTexts[type]);
82
83   if(playerTexts[location.id]) {
84     if(playerTexts[location.id][type].length) {
85       selected = sample(playerTexts[location.id][type]);
86     }
87   }
88
89   return selected.replace("{{NAME}}", location.name).replace("{{CITY_NAME}}", city.name);
90
91 }
92
93 router.get('/city/services/healer/:location_id', authEndpoint, async (req: AuthRequest, res: Response) => {
94   const service = await getService(parseInt(req.params.location_id));
95   const city = await getCityDetails(service.city_id);
96
97   if(!service || service.city_id !== req.player.city_id) {
98     logger.log(`Invalid location: [${req.params.location_id}]`);
99     res.sendStatus(400);
100   }
101
102   const text: string[] = [];
103
104   text.push(`<p>"${getText('intro', service, city)}"</p>`);
105
106   if(req.player.hp === maxHp(req.player.constitution, req.player.level) && req.player.vigor === maxVigor(req.player.constitution, req.player.level)) {
107     text.push(`<p>You're already in peak condition!</p>`);
108   }
109   else {
110     if(req.player.gold <= (healCost * 2)) {
111       text.push(`<p>You don't seem to have too much money... I guess I can do it for free this time...</p>`);
112       text.push(`<p><button type="button" hx-post="/city/services/healer/heal/${service.id}" hx-target="#explore">Heal for Free!</button></p>`);
113     }
114     else {
115       text.push(`<p><button type="button" hx-post="/city/services/healer/heal/${service.id}" hx-target="#explore">Heal for ${healCost}g!</button></p>`);
116     }
117
118   }
119
120   res.send(`
121 <div class="city-title-wrapper"><div class="city-title">${service.city_name}</div></div>
122 <div class="city-details">
123 <h3 class="location-name"><span>${service.name}</span></h3>
124 <div class="service-in-town">
125 ${text.join("\n")}
126 </div>
127 </div>
128   `);
129
130   //res.send(`<div class="service-in-town">${text.join("\n")}</div>`);
131 });
132
133
134
135 router.post('/city/services/healer/heal/:location_id', authEndpoint, async (req: AuthRequest, res: Response) => {
136   const service = await getService(parseInt(req.params.location_id));
137   const city = await getCityDetails(service.city_id);
138
139   if(!service || service.city_id !== req.player.city_id) {
140     logger.log(`Invalid location: [${req.params.location_id}]`);
141     res.sendStatus(400);
142   }
143
144   const text: string[] = [];
145   const cost = req.player.gold <= (healCost * 2) ? 0 : healCost;
146
147   if(req.player.gold < cost) {
148     text.push(`<p>${getText('insufficient_money', service, city)}</p>`)
149   }
150   else {
151     req.player.hp = maxHp(req.player.constitution, req.player.level);
152     req.player.vigor = maxVigor(req.player.constitution, req.player.level);
153     req.player.gold -= cost;
154
155     await updatePlayer(req.player);
156
157     text.push(`<p>${getText('heal_successful', service, city)}</p>`);
158     text.push('<p><button hx-get="/player/explore" hx-target="#explore">Back to Town</button></p>');
159   }
160
161   res.send(`
162 <div class="city-title-wrapper"><div class="city-title">${service.city_name}</div></div>
163 <div class="city-details">
164 <h3 class="location-name"><span>${service.name}</span></h3>
165 <div class="service-in-town">
166 ${text.join("\n")}
167 </div>
168 </div>
169 ${renderPlayerBar(req.player)}
170 `);
171 });