2 Copyright (C) 2004 Parallel Realities
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.
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.
13 See the GNU General Public License for more details.
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.
21 #include "spawnPoints.h"
23 bool okayToSpawnEnemy(const char *name, int x, int y)
25 // Don't summon other monsters!!
26 if (map.fightingGaldov)
31 if (engine.devNoMonsters)
36 // stop enemies from appearing in the middile of doors
37 Train *train = (Train*)map.trainList.getHead();
39 while (train->next != NULL)
41 train = (Train*)train->next;
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))
46 debug(("Couldn't add enemy '%s' - Collided with train\n", name));
51 Entity *enemy = getDefinedEnemy(name);
53 if (map.isLiquid(x, y))
55 if (enemy->flags & ENT_SWIMS)
60 debug(("Couldn't add enemy '%s' - Would drown\n", name));
66 if (enemy->flags & ENT_SWIMS)
68 debug(("Couldn't add enemy '%s' - Not in water\n", name));
74 if (enemy->flags & ENT_FLIES)
79 for (int i = 0 ; i < 30 ; i++)
83 if (y > map.limitDown)
85 debug(("Couldn't add enemy '%s' - Outside map limits\n", name));
90 if (map.isLiquid(x, y))
92 debug(("Couldn't add enemy '%s' - Would drown after free fall\n", name));
97 if (map.isSolid(x, y))
103 debug(("Couldn't add enemy '%s' - Just couldn't!\n", name));
110 SpawnPoint *sp = (SpawnPoint*)map.spawnList.getHead();
116 while (sp->next != NULL)
118 sp = (SpawnPoint*)sp->next;
127 if (sp->spawnType == SPW_HAZARD)
129 if (sp->spawnSubType == HAZARD_ROCKFALL)
131 x = (int)fabs(sp->x - player.x);
132 y = (int)fabs(sp->y - player.y);
134 if ((x <= 640) && (y <= 480))
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);
139 else if (sp->spawnSubType == HAZARD_STALAGTITES)
141 x = (int)fabs(sp->x - player.x);
142 y = (int)fabs(sp->y - player.y);
144 if ((x <= 320) && (y <= 480))
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);
151 if (sp->readyToSpawn())
153 if ((sp->spawnType != SPW_ENEMY) && (sp->spawnType != SPW_ITEM))
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);
159 if ((x > 700) || (y > 500))
166 switch (sp->spawnType)
169 switch (sp->spawnSubType)
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)));
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));
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));
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);
192 if (map.isSolid(x, y))
194 int waterLevel = (int)map.waterLevel;
195 if (waterLevel == -1 || y < waterLevel)
197 map.data[x][y] = MAP_AIR;
199 else if (y == waterLevel)
201 map.data[x][y] = MAP_WATERANIM;
205 map.data[x][y] = MAP_WATER;
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);
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);
222 printf("Spawn Subtype is unknown!\n");
228 if (game.missionOverReason != MIS_INPROGRESS)
231 enemy = map.getSpawnableEnemy();
233 x = (int)(player.x) >> BRICKSHIFT;
234 y = (int)(player.y) >> BRICKSHIFT;
236 x += Math::rrand(-10, 10);
237 y += Math::rrand(-10, 10);
239 if ((x >= 0) && (y >= 0) && (x < MAPWIDTH) && (y < MAPHEIGHT))
241 if ((map.data[x][y] == MAP_AIR) || (map.data[x][y] == MAP_WATER))
243 if (okayToSpawnEnemy(enemy, x, y))
247 addEnemy(enemy, x, y, ENT_SPAWNED);
248 addTeleportParticles(x, y, 25, SND_TELEPORT2);
256 if (game.missionOverReason != MIS_INPROGRESS)
259 x = (int)(player.x) >> BRICKSHIFT;
260 y = (int)(player.y) >> BRICKSHIFT;
262 x += Math::rrand(-10, 10);
263 y += Math::rrand(-10, 10);
265 if ((x >= 0) && (y >= 0))
267 if (map.data[x][y] == MAP_AIR)
271 dropHelperItems(x, y);
272 addTeleportParticles(x, y, 5, SND_TELEPORT2);
280 if (game.missionOverReason != MIS_INPROGRESS)
283 if (map.boss[sp->spawnSubType]->health > 0)
285 map.boss[sp->spawnSubType]->active = true;
291 debug(("Spawn Type is unknown!\n"));
297 if (sp->spawnType == SPW_ENEMY)
299 if ((Math::prand() % (game.skill + 2)) > 0)
301 sp->requiredInterval = Math::rrand(1, 30);