1 /*
2 Copyright (C) 2009-2021 Parallel Realities
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 */
19
20 #include "headers.h"
21
22 #include "audio/audio.h"
23 #include "draw.h"
24 #include "game.h"
25 #include "graphics/graphics.h"
26 #include "map.h"
27 #include "system/error.h"
28 #include "system/random.h"
29 #include "weather.h"
30
31 static Droplet droplet[MAX_DROPS];
32 extern Game game;
33 extern Entity player;
34
35 static void initLightRain(void);
36 static void initHeavyRain(void);
37 static void initStorm(void);
38 static void initSnow(void);
39 static void rain(void);
40 static void snow(void);
41 static void storm(void);
42 static void drawRain(void);
43 static void drawSnow(void);
44
45 static Type weatherType[] = {
46 {NO_WEATHER, "NO_WEATHER"},
47 {LIGHT_RAIN, "LIGHT_RAIN"},
48 {HEAVY_RAIN, "HEAVY_RAIN"},
49 {STORMY, "STORMY"},
50 {SNOW, "SNOW"},
51 };
52 static int weatherLength = sizeof(weatherType) / sizeof(Type);
53
setWeather(int weatherType)54 void setWeather(int weatherType)
55 {
56 switch (weatherType)
57 {
58 case LIGHT_RAIN:
59 game.weatherAction = &initLightRain;
60 game.weatherDraw = &drawRain;
61 break;
62
63 case HEAVY_RAIN:
64 game.weatherAction = &initHeavyRain;
65 game.weatherDraw = &drawRain;
66 break;
67
68 case STORMY:
69 game.weatherAction = &initStorm;
70 game.weatherDraw = &drawRain;
71 break;
72
73 case SNOW:
74 game.weatherAction = &initSnow;
75 game.weatherDraw = &drawSnow;
76 break;
77
78 default:
79 game.weatherAction = NULL;
80 game.weatherDraw = NULL;
81 break;
82
83 }
84
85 game.weatherType = weatherType;
86 game.weatherThinkTime = 60;
87 }
88
initLightRain()89 static void initLightRain()
90 {
91 int i;
92
93 memset(droplet, 0, sizeof(Droplet) * MAX_DROPS);
94
95 for (i=0;i<MAX_DROPS/4;i++)
96 {
97 droplet[i].x = prand() % SCREEN_WIDTH;
98 droplet[i].y = prand() % SCREEN_HEIGHT;
99
100 droplet[i].dirX = 0;
101 droplet[i].dirY = 8 + prand() % 8;
102
103 droplet[i].active = TRUE;
104 }
105
106 game.weatherAction = &rain;
107 }
108
initHeavyRain()109 static void initHeavyRain()
110 {
111 int i;
112
113 memset(droplet, 0, sizeof(Droplet) * MAX_DROPS);
114
115 for (i=0;i<MAX_DROPS/2;i++)
116 {
117 droplet[i].x = prand() % SCREEN_WIDTH;
118 droplet[i].y = prand() % SCREEN_HEIGHT;
119
120 droplet[i].dirX = 0;
121 droplet[i].dirY = 8 + prand() % 8;
122
123 droplet[i].active = TRUE;
124 }
125
126 game.weatherAction = &rain;
127 }
128
rain()129 static void rain()
130 {
131 int i;
132
133 for (i=0;i<MAX_DROPS;i++)
134 {
135 if (droplet[i].active == TRUE)
136 {
137 droplet[i].y += droplet[i].dirY;
138
139 if (droplet[i].y >= SCREEN_HEIGHT)
140 {
141 droplet[i].y = -8 - prand() % 20;
142
143 droplet[i].dirX = 0;
144 droplet[i].dirY = 8 + prand() % 8;
145 }
146 }
147
148 else
149 {
150 break;
151 }
152 }
153 }
154
initStorm()155 static void initStorm()
156 {
157 int i;
158
159 memset(droplet, 0, sizeof(Droplet) * MAX_DROPS);
160
161 for (i=0;i<MAX_DROPS/2;i++)
162 {
163 droplet[i].x = prand() % SCREEN_WIDTH;
164 droplet[i].y = prand() % SCREEN_HEIGHT;
165
166 droplet[i].dirX = 0;
167 droplet[i].dirY = 8 + prand() % 8;
168
169 droplet[i].active = TRUE;
170 }
171
172 game.weatherAction = &storm;
173 }
174
storm()175 static void storm()
176 {
177 rain();
178
179 game.weatherThinkTime--;
180 }
181
initSnow()182 static void initSnow()
183 {
184 int i;
185
186 memset(droplet, 0, sizeof(Droplet) * MAX_DROPS);
187
188 for (i=0;i<MAX_DROPS;i++)
189 {
190 droplet[i].x = prand() % SCREEN_WIDTH;
191 droplet[i].y = prand() % SCREEN_HEIGHT;
192
193 droplet[i].dirX = 0.1f * (prand() % 20) - 0.1f * (prand() % 20);
194 droplet[i].dirY = 0.5f + 0.1f * (prand() % 6);
195
196 droplet[i].active = TRUE;
197 }
198
199 game.weatherAction = &snow;
200 }
201
snow()202 static void snow()
203 {
204 int i;
205
206 for (i=0;i<MAX_DROPS;i++)
207 {
208 droplet[i].x += droplet[i].dirX;
209 droplet[i].y += droplet[i].dirY;
210
211 if (droplet[i].x < 0)
212 {
213 droplet[i].x = SCREEN_WIDTH + droplet[i].x;
214 }
215
216 else if (droplet[i].x > SCREEN_WIDTH)
217 {
218 droplet[i].x = droplet[i].x - SCREEN_WIDTH;
219 }
220
221 if (prand() % 30 == 0)
222 {
223 droplet[i].dirX = 0.1f * (prand() % 20) - 0.1f * (prand() % 20);
224 }
225
226 if (droplet[i].y >= SCREEN_HEIGHT)
227 {
228 droplet[i].x = prand() % SCREEN_WIDTH;
229 droplet[i].y = 0;
230
231 droplet[i].dirX = 0.1f * (prand() % 20) - 0.1f * (prand() % 20);
232 droplet[i].dirY = 0.5f + 0.1f * (prand() % 6);
233 }
234 }
235 }
236
drawRain()237 static void drawRain()
238 {
239 int i;
240
241 if (game.weatherThinkTime <= 0)
242 {
243 i = playSoundToMap("sound/enemy/thunder_cloud/lightning", -1, player.x, player.y, 0);
244
245 fadeFromColour(255, 255, 255, 30);
246
247 game.weatherThinkTime = 600 + i * 60;
248 }
249
250 for (i=0;i<MAX_DROPS;i++)
251 {
252 if (droplet[i].active == TRUE)
253 {
254 drawBox(droplet[i].x, droplet[i].y, 1, 8, 220, 220, 220, 255);
255 }
256 }
257 }
258
drawSnow()259 static void drawSnow()
260 {
261 int i;
262
263 for (i=0;i<MAX_DROPS;i++)
264 {
265 if (droplet[i].active == TRUE)
266 {
267 drawBox(droplet[i].x, droplet[i].y, 2, 2, 255, 255, 255, 255);
268 }
269 }
270 }
271
getWeatherTypeByName(char * name)272 int getWeatherTypeByName(char *name)
273 {
274 int i;
275
276 for (i=0;i<weatherLength;i++)
277 {
278 if (strcmpignorecase(name, weatherType[i].name) == 0)
279 {
280 return weatherType[i].id;
281 }
282 }
283
284 showErrorAndExit("Unknown Weather Type %s", name);
285
286 return 0;
287 }
288
getWeatherTypeByID(int id)289 char *getWeatherTypeByID(int id)
290 {
291 int i;
292
293 for (i=0;i<weatherLength;i++)
294 {
295 if (id == weatherType[i].id)
296 {
297 return weatherType[i].name;
298 }
299 }
300
301 showErrorAndExit("Unknown Weather ID %d", id);
302
303 return 0;
304 }
305
getWeather()306 char *getWeather()
307 {
308 return getWeatherTypeByID(game.weatherType);
309 }
310