]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/CMap.cpp
Allow playing sounds with stereo effects.
[quix0rs-blobwars.git] / src / CMap.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 "headers.h"
23
24 Map::Map()
25 {
26         clear();
27         
28         for (int i = 0 ; i < 10 ; i++)
29         {
30                 boss[i] = NULL;
31         }
32 }
33
34
35 void Map::clear()
36 {
37         fightingGaldov = false;
38         bossNextThink = 0;
39
40         foundItems = totalItems = 0;
41         foundMIAs = totalMIAs = 0;
42         requiredMIAs = 0;
43
44         limitLeft = limitUp = 0;
45         limitRight = ((MAPWIDTH - 40) * BRICKSIZE);
46         limitDown = ((MAPHEIGHT - 30) * BRICKSIZE);
47
48         name[0] = 0;
49
50         for (int x = 0 ; x < MAPWIDTH ; x++)
51                 for (int y = 0 ; y < MAPHEIGHT ; y++)
52                         data[x][y] = 0;
53
54         for (int i = 0 ; i < 10 ; i++)
55                 allowableEnemy[i] = NULL;
56
57         maxAllowableEnemies = 0;
58
59         trainList.clear();
60         itemList.clear();
61         bulletList.clear();
62         enemyList.clear();
63         miaList.clear();
64         obstacleList.clear();
65         particleList.clear();
66         switchList.clear();
67         spawnList.clear();
68         effectList.clear();
69         objectiveList.clear();
70         teleportList.clear();
71         lineList.clear();
72         trapList.clear();
73         
74         remainingMinutes = 0;
75         remainingSeconds = 0;
76         
77         waterLevel = requiredWaterLevel = -1;
78         isBossMission = false;
79         isIceLevel = false;
80         isBlizzardLevel = false;
81         isCavesTileset = false;
82         isGrasslandsTileset = false;
83         bossNextThink = 0;
84         mainBossPart = NULL;
85         doBossLevelAction = NULL;
86         bossEnergyMeterBit = 0;
87         
88         for (int i = 0 ; i < 10 ; i++)
89         {
90                 if (boss[i] != NULL)
91                 {
92                         delete boss[i];
93                 }
94                 boss[i] = NULL;
95         }
96         
97         windPower = windChangeTime = 0;
98 }
99
100 void Map::destroy()
101 {
102         clear();
103         
104         persistantList.clear();
105 }
106
107 bool Map::isPracticeMission()
108 {
109         if (strstr(name, "Practice"))
110                 return true;
111                 
112         return false;
113 }
114
115 bool Map::isSolid(int x, int y)
116 {
117         if ((data[x][y] >= MAP_BREAKABLE) && (data[x][y] < MAP_DECORATION))
118         {
119                 return true;
120         }
121
122         return false;
123 }
124
125 bool Map::isBreakable(int x, int y)
126 {
127         if ((data[x][y] >= MAP_BREAKABLE) && (data[x][y] <= MAP_BREAKABLE2))
128         {
129                 return true;
130         }
131
132         return false;
133 }
134
135 bool Map::isNoReset(int x, int y)
136 {
137         if ((data[x][y] >= MAP_NORESET) && (data[x][y] < MAP_DECORATION))
138         {
139                 return true;
140         }
141
142         return false;
143 }
144
145 bool Map::isLiquid(int x, int y)
146 {
147         if (data[x][y] == 0)
148         {
149                 return false;
150         }
151         else if ((data[x][y] >= MAP_WATER) && (data[x][y] <= MAP_LAVA))
152         {
153                 return true;
154         }
155         else if ((data[x][y] >= MAP_WATERANIM) && (data[x][y] <= MAP_LAVAANIM))
156         {
157                 return true;
158         }
159
160         return false;
161 }
162
163 bool Map::isTopLayer(int x, int y)
164 {
165         if (data[x][y] >= MAP_TOPLAYER)
166         {
167                 return true;
168         }
169
170         return false;
171 }
172
173 Persistant *Map::getPersistant(const char *name)
174 {
175         Persistant *p = (Persistant*)persistantList.getHead();
176         
177         while (p->next != NULL)
178         {
179                 p = (Persistant*)p->next;
180                 
181                 if (strcmp(p->stageName, name) == 0)
182                 {
183                         return p;
184                 }
185         }
186         
187         return NULL;
188 }
189
190 Persistant *Map::createPersistant(const char *name)
191 {
192         Persistant *p = (Persistant*)persistantList.getHead();
193         
194         while (p->next != NULL)
195         {
196                 p = (Persistant*)p->next;
197                 
198                 if (strcmp(p->stageName, name) == 0)
199                 {
200                         return p;
201                 }
202         }
203         
204         debug(("Creating %s in persistance list...\n", name));
205         
206         p = new Persistant();
207         p->setName(name);
208         
209         persistantList.add(p);
210         
211         return p;
212 }
213
214 void Map::destroyPersistant(const char *name)
215 {
216         Persistant *p = (Persistant*)persistantList.getHead();
217         
218         while (p->next != NULL)
219         {
220                 p = (Persistant*)p->next;
221                 
222                 if (strcmp(p->stageName, name) == 0)
223                 {
224                         strlcpy(p->stageName, "@none@", sizeof p->stageName);
225                         p->clear();
226                         return;
227                 }
228         }
229 }
230
231 void Map::setName(const char *name)
232 {
233         strlcpy(this->name, name, sizeof this->name);
234         
235         if (strstr(name, "BioMech"))
236         {
237                 isBossMission = true;
238         }
239                 
240         if (strcmp(name, "Galdov") == 0)
241         {
242                 isBossMission = true;
243         }
244
245         if (strcmp(name, "Final Battle") == 0)
246         {
247                 isBossMission = true;
248         }
249                 
250         if (strstr(name, "Ice"))
251         {
252                 isIceLevel = true;
253         }
254                 
255         if (strstr(name, "Arctic"))
256         {
257                 isIceLevel = true;
258                 isBlizzardLevel = true;
259         }
260 }
261
262 void Map::setClipping(int limitLeft, int limitRight, int limitUp, int limitDown)
263 {
264         if (limitLeft != -1) this->limitLeft = limitLeft;
265         if (limitRight != -1) this->limitRight = limitRight;
266         if (limitUp != -1) this->limitUp = limitUp;
267         if (limitDown != -1) this->limitDown = limitDown;
268 }
269
270 void Map::addTrain(const char *name, int startX, int startY, int endX, int endY, int pause, bool atStart, bool active)
271 {
272         Train *train = new Train();
273         train->setName(name);
274         train->type = TR_TRAIN;
275         train->set(startX, startY, endX, endY, pause, atStart);
276         train->active = active;
277
278         train->width = 64;
279         train->height = 16;
280         
281         if (pause == 0)
282         {
283                 debug(("WARNING: TRAIN WITH 0 WAIT TIME ADDED '%s' (%d:%d)\n", name, startX, startY));
284         }
285
286         trainList.add(train);
287 }
288
289 void Map::addDoor(const char *name, int type, int startX, int startY, int endX, int endY, bool active)
290 {
291         Train *train = new Train();
292         train->setName(name);
293
294         train->type = type;
295
296         train->set(startX, startY, endX, endY, 0, false);
297         train->active = active;
298
299         if (type < TR_SLIDEDOOR)
300         {
301                 train->width = 16;
302                 train->height = 64;
303         }
304         else
305         {
306                 train->width = 64;
307                 train->height = 16;
308         }
309         
310         trainList.add(train);
311 }
312
313 void Map::addSwitch(const char *name, const char *linkName, const char *requiredObjectName, const char *activateMessage, int type, int x, int y, bool activated)
314 {
315         Switch *swt = new Switch();
316         swt->set(name, linkName, requiredObjectName, activateMessage, type, x, y, activated);
317
318         switchList.add(swt);
319 }
320
321 void Map::addItem(Entity *item)
322 {
323         itemList.add(item);
324 }
325
326 void Map::addBullet(Entity *bullet)
327 {
328         bulletList.add(bullet);
329 }
330
331 void Map::addParticle(float x, float y, float dx, float dy, int health, int color, Sprite *sprite, int flags)
332 {
333         Particle *particle = new Particle();
334         particle->set(x, y, dx, dy, color, health, flags);
335         particle->setSprite(sprite);
336         
337         particleList.add(particle);
338 }
339
340 void Map::addEnemy(Entity *enemy)
341 {
342         enemyList.add(enemy);
343 }
344
345 void Map::addMIA(Entity *mia)
346 {
347         miaList.add(mia);
348 }
349
350 void Map::addObstacle(Entity *obstacle)
351 {
352         obstacleList.add(obstacle);
353 }
354
355 void Map::addSpawnPoint(const char *name, int x, int y, int type, int subtype, int min, int max, bool active)
356 {
357         SpawnPoint *spawnPoint = new SpawnPoint();
358         spawnPoint->create(name, x, y, type, subtype, min, max, active);
359
360         spawnList.add(spawnPoint);
361 }
362
363 void Map::addEffect(Effect *effect)
364 {
365         effectList.add(effect);
366 }
367
368 void Map::addObjective(const char *description, const char *target, int targetValue, bool required)
369 {
370         Objective *objective = new Objective(description, target, targetValue, required);
371
372         objectiveList.add(objective);
373 }
374
375 void Map::addTeleporter(Teleporter *teleporter)
376 {
377         teleportList.add(teleporter);
378 }
379
380 void Map::addLineDef(LineDef *lineDef)
381 {
382         lineList.add(lineDef);
383 }
384
385 void Map::addTrap(Trap *trap)
386 {
387         trapList.add(trap);
388 }
389
390 void Map::evalTileset(const char *baseDir)
391 {
392         if (strstr(baseDir, "caves"))
393         {
394                 isCavesTileset = true;
395         }
396         else if (strstr(baseDir, "grasslands"))
397         {
398                 isGrasslandsTileset = true;
399         }
400 }
401
402 void Map::killAllEnemies()
403 {
404         Entity *enemy = (Entity*)enemyList.getHead()->next;
405
406         while (enemy != NULL)
407         {
408                 enemy->health = -1;
409
410                 enemy = (Entity*)enemy->next;
411         }
412 }
413
414 void Map::setAllowableEnemy(Entity *enemy)
415 {
416         for (int i = 0 ; i < 10 ; i++)
417         {
418                 if (allowableEnemy[i] == NULL)
419                 {
420                         allowableEnemy[i] = enemy;
421                         maxAllowableEnemies = i + 1;
422                         return;
423                 }
424         }
425
426         debug(("WARNING: Can't add anymore spawnable enemies to list!!!\n"));
427 }
428
429 char *Map::getSpawnableEnemy(int i)
430 {
431         if (allowableEnemy[i] == NULL)
432                 return NULL;
433         
434         return allowableEnemy[i]->name;
435 }
436
437 char *Map::getSpawnableEnemy()
438 {
439         if (maxAllowableEnemies == 0)
440         {
441                 printf("ERROR: No enemy spawn list defined for map '%s'!! Please report this Error!\n", name);
442                 exit(1);
443         }
444
445         return allowableEnemy[Math::prand() % maxAllowableEnemies]->name;
446 }
447
448 void Map::getRandomEntityPosition(int *x, int *y)
449 {
450         Entity *ent = (Entity*)miaList.getHead();
451
452         while (ent->next != NULL)
453         {
454                 ent = (Entity*)ent->next;
455
456                 if ((Math::prand() % 5) == 0)
457                 {
458                         *x = (int)ent->x;
459                         *y = (int)ent->y;
460                         return;
461                 }
462         }
463
464         ent = (Entity*)enemyList.getHead();
465
466         while (ent->next != NULL)
467         {
468                 ent = (Entity*)ent->next;
469
470                 if ((Math::prand() % 5) == 0)
471                 {
472                         *x = (int)ent->x;
473                         *y = (int)ent->y;
474                         return;
475                 }
476         }
477
478         ent = (Entity*)itemList.getHead();
479
480         while (ent->next != NULL)
481         {
482                 ent = (Entity*)ent->next;
483
484                 if ((Math::prand() % 5) == 0)
485                 {
486                         *x = (int)ent->x;
487                         *y = (int)ent->y;
488                         return;
489                 }
490         }
491 }
492
493 void Map::setMainBossPart(Boss *boss)
494 {
495         mainBossPart = boss;
496         
497         if (mainBossPart != NULL)
498         {
499                 bossEnergyMeterBit = 200;
500                 bossEnergyMeterBit /= boss->maxHealth;
501         }
502 }