chore(release): 0.3.2
[risinglegends.git] / src / events / travel / server.ts
1 import {movePlayer} from "../../server/player";
2 import {getCityDetails, getAllServices, getAllPaths, travel, getTravelPlan, stepForward, completeTravel} from "../../server/map";
3 import {SocketEvent} from "../../server/socket-event.server";
4 import { sample, random } from 'lodash';
5 import { getRandomMonster } from "../../server/monster";
6 import { STEP_DELAY } from "./shared";
7
8 const MONSTER_ENCOUNTER_CHANCE = 30;
9
10 export const explore: SocketEvent = {
11   eventName: 'city:travel',
12   handler: async (api, data: { args: string }) => {
13     if(api.player.hp <= 0) {
14       api.socket.emit('alert', {
15         type: 'error',
16         text: 'Sorry, you need some HP to start your travel'
17       });
18       return;
19     }
20
21     const destinationCity = parseInt(data.args);
22
23
24     if(!destinationCity || isNaN(destinationCity)) {
25       console.log(`Invalid destination city [${destinationCity}]`);
26       return;
27     }
28
29     try {
30       const city = await getCityDetails(destinationCity);
31
32       if(!city) {
33         console.log(`Invalid destination city [${destinationCity}]`);
34         return;
35       }
36
37       console.log(`${api.player.username} attempting travel to ${city.name}`);
38       const travelPlan = await travel(api.player, city.id);
39
40       api.socket.emit('city:travel', {
41         things: [],
42         nextAction: 0,
43         closestTown: api.player.city_id,
44         walkingText: ''
45       });
46     }
47     catch(e) {
48       console.log(e);
49     }
50   }
51 }
52
53 const walkingText: string[] = [
54   'You take a step forward',
55   'You keep moving'
56 ];
57
58 export const nextStep: SocketEvent = {
59   eventName: 'travel:step',
60   handler: async (api, data: { args: string }) => {
61     const stepTimerKey = `step:${api.player.id}`;
62     const travelPlan = await getTravelPlan(api.player.id);
63
64     if(api.cache[stepTimerKey]) {
65       if(api.cache[stepTimerKey] > Date.now()) {
66         // clicked too fast
67         return;
68       }
69     }
70
71     if(!travelPlan) {
72       return;
73     }
74
75     travelPlan.current_position++;
76     if(travelPlan.current_position >= travelPlan.total_distance) {
77       const travel = await completeTravel(api.player.id);
78
79       api.player.city_id = travel.destination_id;
80       await movePlayer(travel.destination_id, api.player.id);
81
82       const [city, locations, paths] = await Promise.all([
83         getCityDetails(travel.destination_id),
84         getAllServices(travel.destination_id),
85         getAllPaths(travel.destination_id)
86       ]);
87
88       api.socket.emit('city:display', {
89         city,
90         locations,
91         paths
92       });
93
94       delete api.cache[stepTimerKey];
95     }
96     else {
97       // update existing plan..
98       // decide if they will run into anything
99       const travelPlan = await stepForward(api.player.id);
100
101       const closest: number = (travelPlan.current_position / travelPlan.total_distance) > 0.5 ? travelPlan.destination_id : travelPlan.source_id;
102
103       const chanceToSeeMonster = random(0, 100);
104       const things: any[] = [];
105       if(chanceToSeeMonster < MONSTER_ENCOUNTER_CHANCE) {
106         const monster = await getRandomMonster([closest]);
107         things.push(monster);
108       }
109
110       const nextAction = Date.now() + STEP_DELAY;
111
112       api.cache[stepTimerKey] = nextAction;
113
114       api.socket.emit('city:travel', {
115         things,
116         nextAction,
117         closestTown: closest,
118         walkingText: sample(walkingText)
119       });
120
121     }
122   }
123 };