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