]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/spawnPoints.cpp
Use time_t to store time data.
[quix0rs-blobwars.git] / src / spawnPoints.cpp
1 /*
2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 */
21
22 #include "spawnPoints.h"
23
24 bool okayToSpawnEnemy(const char *name, int x, int y)
25 {
26         // Don't summon other monsters!!
27         if (map.fightingGaldov)
28         {
29                 return false;
30         }
31
32         if (engine.devNoMonsters)
33         {
34                 return false;
35         }
36         
37         // stop enemies from appearing in the middile of doors
38         Train *train = (Train*)map.trainList.getHead();
39
40         while (train->next != NULL)
41         {
42                 train = (Train*)train->next;
43
44                 // assume enemy is 20 x 20 pixels (most are at least) and trains are 64 x 64
45                 if (Collision::collision(x * BRICKSHIFT, y * BRICKSHIFT, 20, 20, train->x, train->y, 64, 64))
46                 {
47                         debug(("Couldn't add enemy '%s' - Collided with train\n", name));
48                         return false;
49                 }
50         }
51
52         Entity *enemy = getDefinedEnemy(name);
53         
54         if (map.isLiquid(x, y))
55         {
56                 if (enemy->flags & ENT_SWIMS)
57                 {
58                         return true;
59                 }
60                 
61                 debug(("Couldn't add enemy '%s' - Would drown\n", name));
62
63                 return false;
64         }
65         else
66         {
67                 if (enemy->flags & ENT_SWIMS)
68                 {
69                         debug(("Couldn't add enemy '%s' - Not in water\n", name));
70                         
71                         return false;
72                 }
73         }
74
75         if (enemy->flags & ENT_FLIES)
76         {
77                 return true;
78         }
79
80         for (int i = 0 ; i < 30 ; i++)
81         {
82                 y++;
83
84                 if (y > map.limitDown)
85                 {
86                         debug(("Couldn't add enemy '%s' - Outside map limits\n", name));
87                         
88                         return false;
89                 }
90
91                 if (map.isLiquid(x, y))
92                 {
93                         debug(("Couldn't add enemy '%s' - Would drown after free fall\n", name));
94                         
95                         return false;
96                 }
97
98                 if (map.isSolid(x, y))
99                 {
100                         return true;
101                 }
102         }
103         
104         debug(("Couldn't add enemy '%s' - Just couldn't!\n", name));
105
106         return false;
107 }
108
109 void doSpawnPoints()
110 {
111         SpawnPoint *sp = (SpawnPoint*)map.spawnList.getHead();
112
113         int x, y;
114
115         char *enemy;
116
117         while (sp->next != NULL)
118         {
119                 sp = (SpawnPoint*)sp->next;
120
121                 sp->think();
122
123                 if (!sp->active)
124                 {
125                         continue;
126                 }
127
128                 if (sp->spawnType == SPW_HAZARD)
129                 {
130                         if (sp->spawnSubType == HAZARD_ROCKFALL)
131                         {
132                                 x = (int)fabs(sp->x - player.x);
133                                 y = (int)fabs(sp->y - player.y);
134                                 
135                                 if ((x <= 640) && (y <= 480))
136                                 {
137                                         engine.setPlayerPosition((int)player.x + Math::rrand(-MAP_SHAKEAMOUNT, MAP_SHAKEAMOUNT), (int)player.y + Math::rrand(-MAP_SHAKEAMOUNT, MAP_SHAKEAMOUNT), map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
138                                 }
139                         }
140                         else if (sp->spawnSubType == HAZARD_STALAGTITES)
141                         {
142                                 x = (int)fabs(sp->x - player.x);
143                                 y = (int)fabs(sp->y - player.y);
144                                 
145                                 if ((x <= 320) && (y <= 480))
146                                 {
147                                         engine.setPlayerPosition((int)player.x + Math::rrand(-MAP_SHAKEAMOUNT, MAP_SHAKEAMOUNT), (int)player.y + Math::rrand(-MAP_SHAKEAMOUNT, MAP_SHAKEAMOUNT), map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
148                                 }
149                         }
150                 }
151
152                 if (sp->readyToSpawn())
153                 {       
154                         if ((sp->spawnType != SPW_ENEMY) && (sp->spawnType != SPW_ITEM))
155                         {
156                                 // If the player is too far away, don't spawn (unless it's random enemy / item spawning)
157                                 x = (int)fabs(sp->x - player.x);
158                                 y = (int)fabs(sp->y - player.y);
159
160                                 if ((x > 700) || (y > 500))
161                                 {
162                                         sp->reset();
163                                         continue;
164                                 }
165                         }
166
167                         switch (sp->spawnType)
168                         {
169                                 case SPW_HAZARD:
170                                         switch (sp->spawnSubType)
171                                         {
172                                                 case HAZARD_LAVABALL:
173                                                         engine.world.place(sp->x, sp->y);
174                                                         engine.world.currentWeapon = &weapon[WP_LAVABALL1];
175                                                         addBullet(&engine.world, Math::rrand(-5, 5), Math::rrand(-(5 + game.skill), -(2 + game.skill)));
176                                                         break;
177                                                 case HAZARD_ROCKFALL:
178                                                         engine.world.place(sp->x, sp->y);
179                                                         engine.world.currentWeapon = &weapon[WP_ROCK1];
180                                                         addBullet(&engine.world, Math::rrand(-2, 2), Math::rrand(0, 2));
181                                                         break;
182                                                 case HAZARD_BOMBS:
183                                                         engine.world.place(sp->x, sp->y);
184                                                         engine.world.currentWeapon = &weapon[WP_BOMB];
185                                                         addBullet(&engine.world, Math::rrand(-2, 2), Math::rrand(0, 2));
186                                                         break;
187                                                 case HAZARD_EXPLOSION:
188                                                         x = sp->x + Math::rrand(-128, 128);
189                                                         y = sp->y + Math::rrand(-128, 128);
190                                                         addExplosion(x, y, 50, &engine.world);
191                                                         x = x >> BRICKSHIFT;
192                                                         y = y >> BRICKSHIFT;
193                                                         if (map.isSolid(x, y))
194                                                         {
195                                                                 int waterLevel = (int)map.waterLevel;
196                                                                 if (waterLevel == -1 || y < waterLevel)
197                                                                 {
198                                                                         map.data[x][y] = MAP_AIR;
199                                                                 }
200                                                                 else if (y == waterLevel)
201                                                                 {
202                                                                         map.data[x][y] = MAP_WATERANIM;
203                                                                 }
204                                                                 else
205                                                                 {
206                                                                         map.data[x][y] = MAP_WATER;
207                                                                 }
208                                                         }
209                                                         break;
210                                                 case HAZARD_POWERBULLETS:
211                                                         engine.world.place(sp->x, sp->y);
212                                                         engine.world.currentWeapon = &weapon[WP_SHELLS];
213                                                         x = engine.world.currentWeapon->dx;
214                                                         if (player.x < sp->x) x = -x;
215                                                         addBullet(&engine.world, x, 0);
216                                                         break;
217                                                 case HAZARD_STALAGTITES:
218                                                         engine.world.place(sp->x, sp->y);
219                                                         engine.world.currentWeapon = &weapon[WP_STALAGTITE];
220                                                         addBullet(&engine.world, 0, 2);
221                                                         break;
222                                                 default:
223                                                         printf("Spawn Subtype is unknown!\n");
224                                                         break;
225                                         }
226                                         break;
227
228                                 case SPW_ENEMY:
229                                         if (game.missionOverReason != MIS_INPROGRESS)
230                                                 break;
231
232                                         enemy = map.getSpawnableEnemy();
233
234                                         x = (int)(player.x) >> BRICKSHIFT;
235                                         y = (int)(player.y) >> BRICKSHIFT;
236
237                                         x += Math::rrand(-10, 10);
238                                         y += Math::rrand(-10, 10);
239
240                                         if ((x >= 0) && (y >= 0) && (x < MAPWIDTH) && (y < MAPHEIGHT))
241                                         {
242                                                 if ((map.data[x][y] == MAP_AIR) || (map.data[x][y] == MAP_WATER))
243                                                 {
244                                                         if (okayToSpawnEnemy(enemy, x, y))
245                                                         {
246                                                                 x = x << BRICKSHIFT;
247                                                                 y = y << BRICKSHIFT;
248                                                                 addEnemy(enemy, x, y, ENT_SPAWNED);
249                                                                 addTeleportParticles(x, y, 25, SND_TELEPORT2);
250                                                         }
251                                                 }
252                                         }
253
254                                         break;
255                                         
256                                 case SPW_ITEM:
257                                         if (game.missionOverReason != MIS_INPROGRESS)
258                                                 break;
259                                         
260                                         x = (int)(player.x) >> BRICKSHIFT;
261                                         y = (int)(player.y) >> BRICKSHIFT;
262
263                                         x += Math::rrand(-10, 10);
264                                         y += Math::rrand(-10, 10);
265
266                                         if ((x >= 0) && (y >= 0))
267                                         {
268                                                 if (map.data[x][y] == MAP_AIR)
269                                                 {
270                                                         x = x << BRICKSHIFT;
271                                                         y = y << BRICKSHIFT;
272                                                         dropHelperItems(x, y);
273                                                         addTeleportParticles(x, y, 5, SND_TELEPORT2);
274                                                 }
275                                         }
276                                         
277                                         break;
278                                         
279                                 case SPW_BOSSBULLET:
280                                         
281                                         if (game.missionOverReason != MIS_INPROGRESS)
282                                                 break;
283                                         
284                                         if (map.boss[sp->spawnSubType]->health > 0)
285                                         {
286                                                 map.boss[sp->spawnSubType]->active = true;
287                                         }
288                                         
289                                         break;
290
291                                 default:
292                                         debug(("Spawn Type is unknown!\n"));
293                                         break;
294                         }
295
296                         sp->reset();
297
298                         if (sp->spawnType == SPW_ENEMY)
299                         {
300                                 if ((Math::prand() % (game.skill + 2)) > 0)
301                                 {
302                                         sp->requiredInterval = Math::rrand(1, 30);
303                                 }
304                         }
305                 }
306         }
307 }