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