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