]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/mapData.cpp
Use time_t to store time data.
[quix0rs-blobwars.git] / src / mapData.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 "mapData.h"
23
24 void getMapTokens()
25 {
26         char skillLevel[10];
27         char mapEntity[255];
28         char string[10][1024];
29         int param[10];
30         bool allowAtSkillLevel = false;
31         
32         bool previouslyCleared = false;
33         
34         char *token = NULL;
35         
36         Persistant *persistant = NULL;
37         PersistData *persistData = NULL;
38         
39         while (true)
40         {
41                 if (!previouslyCleared)
42                 {
43                         token = strtok(NULL, "\n");
44                 }
45                 else
46                 {
47                         persistData = (PersistData*)persistData->next;
48                         
49                         if (persistData == NULL)
50                                 break;
51                         
52                         token = persistData->data;
53                 }
54
55                 #if USEPAK
56                 graphics.showLoading(1, 100);
57                 graphics.delay(1);
58                 #endif
59
60                 allowAtSkillLevel = false;
61
62                 sscanf(token, "%s", skillLevel);
63
64                 if ((strstr(skillLevel, "E")) && (game.skill == 0))
65                 {
66                         allowAtSkillLevel = true;
67                 }
68
69                 if ((strstr(skillLevel, "M")) && (game.skill == 1))
70                 {
71                         allowAtSkillLevel = true;
72                 }
73
74                 if ((strstr(skillLevel, "H")) && (game.skill >= 2))
75                 {
76                         allowAtSkillLevel = true;
77                 }
78                 
79                 if ((strstr(skillLevel, "X")) && (game.skill == 3))
80                 {
81                         allowAtSkillLevel = true;
82                 }
83                         
84                 // This is just for practice missions
85                 if (game.skill == -1)
86                         allowAtSkillLevel = true;
87
88                 // Ignore comments
89                 if (strstr(skillLevel, "//"))
90                         allowAtSkillLevel = false;
91
92                 if (strcmp("@EOF@", skillLevel) == 0)
93                 {
94                         break;
95                 }
96
97                 if (allowAtSkillLevel)
98                 {
99                         sscanf(token, "%*s %s", mapEntity);
100
101                         if (strcmp("STAGENAME", mapEntity) == 0)
102                         {
103                                 sscanf(token, "%*s %*s %*c %[^\"] %*c", string[0]);
104
105                                 map.setName(string[0]);
106                                 game.setStageName(string[0]);
107                         }
108                         else if (strcmp("PREVIOUSLY_VISITED", mapEntity) == 0)
109                         {
110                                 previouslyCleared = gameData.stagePreviouslyCleared(map.name);
111                                 
112                                 if (previouslyCleared)
113                                 {
114                                         debug(("Reading Persistance Data...\n"));
115                                         persistant = map.getPersistant(map.name);
116                                         persistData = (PersistData*)persistant->dataList.getHead();
117                                 }
118                         }
119                         else if (strcmp("TIMELIMIT", mapEntity) == 0)
120                         {
121                                 debug(("Loading Time Limit: %s\n", token));
122                                 sscanf(token, "%*s %*s %d %d", &param[0], &param[1]);
123                                 map.remainingMinutes = param[0];
124                                 map.remainingSeconds = param[1];
125                         }
126                         else if (strcmp("TRAIN", mapEntity) == 0)
127                         {
128                                 sscanf(token, "%*s %*s %s %d %d %d %d %d %s %s", string[0], &param[0], &param[1], &param[2], &param[3], &param[4], string[1], string[2]);
129                                 map.addTrain(string[0], param[0], param[1], param[2], param[3], param[4], engine.getValueOfDefine(string[1]), engine.getValueOfDefine(string[2]));
130                         }
131                         else if (strcmp("DOOR", mapEntity) == 0)
132                         {
133                                 sscanf(token, "%*s %*s %s %s %d %d %d %d %s", string[0], string[1], &param[0], &param[1], &param[2], &param[3], string[2]);
134                                 map.addDoor(string[0], engine.getValueOfDefine(string[1]), param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[2]));
135                         }
136                         else if (strcmp("SWITCH", mapEntity) == 0)
137                         {
138                                 sscanf(token, "%*s %*s %*c %[^\"] %*c %s %*c %[^\"] %*c %*c %[^\"] %*c %s %d %d %s", string[0], string[1], string[2], string[3], string[4], &param[0], &param[1], string[5]);
139                                 map.addSwitch(string[0], string[1], string[2], string[3], engine.getValueOfDefine(string[4]), param[0], param[1], engine.getValueOfDefine(string[5]));
140                         }
141                         else if (strcmp("ITEM", mapEntity) == 0)
142                         {
143                                 sscanf(token, "%*s %*s %d %*c %[^\"] %*c %d %d %s", &param[0], string[0], &param[1], &param[2], string[1]);
144                                 
145                                 addItem(param[0], string[0], param[1], param[2], string[1], 60, 1, 0, false);
146
147                                 if (param[0] >= ITEM_MISC)
148                                 {
149                                         map.totalItems++;
150                                 }
151                         }
152                         else if (strcmp("OBSTACLE", mapEntity) == 0)
153                         {
154                                 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d %s", string[0], &param[0], &param[1], string[1]);
155
156                                 addObstacle(string[0], param[0], param[1], string[1]);
157                         }
158                         else if (strcmp("OBJECTIVE", mapEntity) == 0)
159                         {
160                                 sscanf(token, "%*s %*s %*c %[^\"] %*c %*c %[^\"] %*c %d %s", string[0], string[1], &param[0], string[2]);
161
162                                 map.addObjective(string[0], string[1], param[0], engine.getValueOfDefine(string[2]));
163                         }
164                         else if (strcmp("START", mapEntity) == 0)
165                         {
166                                 sscanf(token, "%*s %*s %d %d", &param[0], &param[1]);
167
168                                 player.place(param[0], param[1]);
169
170                                 game.setCheckPoint(param[0], param[1]);
171                                 game.setObjectiveCheckPoint();
172
173                         }
174                         else if (strcmp("ENEMY", mapEntity) == 0)
175                         {
176                                 if (!engine.devNoMonsters)
177                                 {
178                                         sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d", string[0], &param[0], &param[1]);
179                                         
180                                         if ((game.skill == 0) && (map.waterLevel != -1))
181                                         {
182                                                 addEnemy("Aqua Blob", param[0], param[1], 0);
183                                         }
184                                         else
185                                         {
186                                                 addEnemy(string[0], param[0], param[1], 0);
187                                         }
188                                 }
189                         }
190                         else if (strcmp("MIA", mapEntity) == 0)
191                         {
192                                 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d %s", string[0], &param[0], &param[1], string[1]);
193                                 addMIA(string[0], param[0], param[1], engine.getValueOfDefine(string[1]));
194                                 map.totalMIAs++;
195                         }
196                         else if (strcmp("REQUIREDMIAS", mapEntity) == 0)
197                         {
198                                 sscanf(token, "%*s %*s %d", &param[0]);
199                                 map.requiredMIAs = param[0];
200                         }
201                         else if (strcmp("LINEDEF", mapEntity) == 0)
202                         {
203                                 sscanf(token, "%*s %*s %*c %[^\"] %*c %s %*c %[^\"] %*c %d %d %d %d %s", string[0], string[1], string[2], &param[0], &param[1], &param[2], &param[3], string[3]);
204
205                                 addLineDef(string[0], string[1], string[2], param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[3]));
206                         }
207                         else if (strcmp("SPAWNPOINT", mapEntity) == 0)
208                         {
209                                 sscanf(token, "%*s %*s %s %d %d %s %s %d %d %s", string[0], &param[0], &param[1], string[1], string[2], &param[2], &param[3], string[3]);
210                                 map.addSpawnPoint(string[0], param[0], param[1], engine.getValueOfDefine(string[1]), engine.getValueOfDefine(string[2]), param[2], param[3], engine.getValueOfDefine(string[3]));
211                         }
212                         else if (strcmp("SPAWNABLE_ENEMY", mapEntity) == 0)
213                         {
214                                 sscanf(token, "%*s %*s %*c %[^\"] %*c", string[0]);
215                                 map.setAllowableEnemy(getDefinedEnemy(string[0]));
216                         }
217                         else if (strcmp("TELEPORTER", mapEntity) == 0)
218                         {
219                                 sscanf(token, "%*s %*s %s %d %d %d %d %s", string[0], &param[0], &param[1], &param[2], &param[3], string[1]);
220                                 addTeleporter(string[0], param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[1]));
221                         }
222                         else if (strcmp("TRAP", mapEntity) == 0)
223                         {
224                                 sscanf(token, "%*s %*s %s %s %d %d %d %d %d %d %d %d %s %s", string[0], string[1], &param[0], &param[1], &param[2], &param[3], &param[4], &param[5], &param[6], &param[7], string[2], string[3]);
225                                 addTrap(string[0], engine.getValueOfDefine(string[1]), param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7], string[2], engine.getValueOfDefine(string[3]));
226                         }
227                         else if (strcmp("SPRITE", mapEntity) == 0)
228                         {
229                                 sscanf(token, "%*s %*s %[^\n\r]", string[0]);
230                                 loadSprite(string[0]);
231                         }
232                         else if (strcmp("DEFENEMY", mapEntity) == 0)
233                         {
234                                 sscanf(token, "%*s %*s %[^\n\r]", string[0]);
235                                 loadEnemy(string[0]);
236                         }
237                         else if (strcmp("TILESET", mapEntity) == 0)
238                         {
239                                 sscanf(token, "%*s %*s %s", string[0]);
240                                 map.evalTileset(string[0]);
241                                 graphics.loadMapTiles(string[0]);
242                         }
243                         else if (strcmp("CLIPPING", mapEntity) == 0)
244                         {
245                                 sscanf(token, "%*s %*s %d %d %d %d", &param[0], &param[1], &param[2], &param[3]);
246                                 map.setClipping(param[0], param[1], param[2], param[3]);
247                         }
248                         else if (strcmp("AMBIENCE", mapEntity) == 0)
249                         {
250                                 sscanf(token, "%*s %*s %s", string[0]);
251                                 audio.loadSound(SND_AMBIANCE, string[0]);
252                         }
253                         else if (strcmp("WATERLEVEL", mapEntity) == 0)
254                         {
255                                 sscanf(token, "%*s %*s %d", &param[0]);
256                                 
257                                 map.requiredWaterLevel = param[0];
258                                 
259                                 if (!previouslyCleared)
260                                 {
261                                         map.waterLevel = param[0];
262                                 }
263                                 else
264                                 {
265                                         map.waterLevel = 281;
266                                 }
267                                 
268                                 if (game.skill == 0)
269                                 {
270                                         map.waterLevel = 281;
271                                         map.requiredWaterLevel = 222;
272                                 }                               
273                         }
274                         else if (strcmp("ALPHATILES", mapEntity) == 0)
275                         {
276                                 for (int i = 0 ; i < 15 ; i++)
277                                         token++;
278
279                                 while (true)
280                                 {
281                                         sscanf(token, "%d", &param[0]);
282
283                                         if (param[0] == -1)
284                                                 break;
285                                                 
286                                         debug(("Setting Alpha for Tile %d\n", param[0]));
287
288                                         SDL_SetAlpha(graphics.tile[param[0]], 130);
289
290                                         while (true)
291                                         {
292                                                 token++;
293
294                                                 if (*token == ' ')
295                                                         break;
296                                         }
297                                 }
298                         }
299                         else if (strcmp("BACKGROUND", mapEntity) == 0)
300                         {
301                                 sscanf(token, "%*s %*s %s", string[0]);
302                                 graphics.loadBackground(string[0]);
303                         }
304                         else if (strcmp("MUSIC", mapEntity) == 0)
305                         {
306                                 sscanf(token, "%*s %*s %s", string[0]);
307                                 audio.loadMusic(string[0]);
308                         }
309                         else if (allowAtSkillLevel)
310                         {
311                                 graphics.showErrorAndExit("Symbol '%s' not recognised or not implemented in map data", mapEntity);
312                         }
313                 }
314                 else
315                 {
316                         //debug(("Ignoring Line: %s\n", token));
317                 }
318         }
319         
320         /*
321         We need to make sure the player doesn't appear in a wall that was previously
322         destroyed. Things like this aren't stored so we will just remove a block they
323         make have been "in"
324         */
325         if (previouslyCleared)
326         {
327                 int x = game.checkPointX;
328                 int y = game.checkPointY;
329                 
330                 x = x >> BRICKSHIFT;
331                 y = y >> BRICKSHIFT;
332                 
333                 if ((map.data[x][y] >= MAP_BREAKABLE) && (map.data[x][y] <= MAP_BREAKABLE2))
334                 {
335                         map.data[x][y] = MAP_AIR;
336                 }
337         }
338 }
339
340 const char *getActiveState(bool active)
341 {
342         if (active)
343         {
344                 return "ACTIVE";
345         }
346         
347         return "INACTIVE";
348 }
349
350 void createPersistantMapData()
351 {
352         if (!engine.loadDefines())
353         {
354                 graphics.showErrorAndExit("Could not load map define list '%s'", "data/defines.h");
355         }
356         
357         Persistant *persistant = (Persistant*)map.createPersistant(map.name);
358         persistant->clear();
359         
360         if (perfectlyCompleted())
361         {
362                 debug(("createPersistantMapData :: Perfect - Skipping\n"));
363                 return;
364         }
365         
366         char line[1024];
367         line[0] = 0;
368         
369         char skill;
370         
371         switch (game.skill)
372         {
373                 case 0:
374                         skill = 'E';
375                         break;
376                 case 1:
377                         skill = 'M';
378                         break;
379                 default:
380                         skill = 'H';
381                         break;
382         }
383         
384         snprintf(line, sizeof line, "%c START %d %d\n", skill, (int)game.checkPointX, (int)game.checkPointY);
385         persistant->addLine(line);
386
387         Entity *ent;
388         Switch *swt;
389         Train *train;
390         Trap *trap;
391         Teleporter *teleporter;
392         LineDef *lineDef;
393         SpawnPoint *spawnPoint;
394         
395         char *define[3];
396         
397         ent = (Entity*)map.enemyList.getHead();
398         
399         while (ent->next != NULL)
400         {
401                 ent = (Entity*)ent->next;
402                 snprintf(line, sizeof line, "%c ENEMY \"%s\" %d %d\n", skill, ent->name, (int)ent->x, (int)ent->y);
403                 persistant->addLine(line);
404         }
405         
406         ent = (Entity*)map.itemList.getHead();
407         
408         while (ent->next != NULL)
409         {
410                 ent = (Entity*)ent->next;
411                 
412                 // Don't save items that are dying...
413                 if (ent->flags & ENT_DYING)
414                 {
415                         continue;
416                 }
417                 
418                 snprintf(line, sizeof line, "%c ITEM %d \"%s\" %d %d %s\n", skill, ent->id, ent->name, (int)ent->x, (int)ent->y, ent->sprite[0]->name);
419                 persistant->addLine(line);
420         }
421         
422         ent = (Entity*)map.obstacleList.getHead();
423         
424         while (ent->next != NULL)
425         {
426                 ent = (Entity*)ent->next;
427                 snprintf(line, sizeof line, "%c OBSTACLE \"%s\" %d %d %s\n", skill, ent->name, (int)ent->x, (int)ent->y, ent->sprite[0]->name);
428                 persistant->addLine(line);
429         }
430         
431         swt = (Switch*)map.switchList.getHead();
432         
433         while (swt->next != NULL)
434         {
435                 swt = (Switch*)swt->next;
436                 define[0] = engine.getDefineOfValue("SWT_", swt->type);
437                 define[1] = (char*)getActiveState(swt->activated);
438                 
439                 snprintf(line, sizeof line, "%c SWITCH \"%s\" %s \"%s\" \"%s\" %s %d %d %s\n", skill, swt->name, swt->linkName, swt->requiredObjectName, swt->activateMessage, define[0], (int)swt->x, (int)swt->y, define[1]);
440                 
441                 persistant->addLine(line);
442         }
443         
444         train = (Train*)map.trainList.getHead();
445         
446         while (train->next != NULL)
447         {
448                 train = (Train*)train->next;
449                 
450                 if (train->type != TR_TRAIN)
451                 {
452                         if (train->type >= TR_SLIDEDOOR)
453                         {
454                                 define[0] = engine.getDefineOfValue("_SLIDE", train->type);
455                         }
456                         else
457                         {
458                                 define[0] = engine.getDefineOfValue("_DOO", train->type);
459                         }
460                         
461                         define[1] = (char*)getActiveState(train->active);
462                         snprintf(line, sizeof line, "%c DOOR %s %s %d %d %d %d %s\n", skill, train->name, define[0], train->startX, train->startY, train->endX, train->endY, define[1]);
463                 }
464                 else
465                 {
466                         define[0] = engine.getDefineOfValue("TR_A", train->waitAtStart);
467                         define[1] = (char*)getActiveState(train->active);
468                         snprintf(line, sizeof line, "%c TRAIN %s %d %d %d %d %d %s %s\n", skill, train->name, train->startX, train->startY, train->endX, train->endY, train->getPause(), define[0], define[1]);
469                 }
470                                 
471                 persistant->addLine(line);
472         }
473         
474         trap = (Trap*)map.trapList.getHead();
475         
476         while (trap->next != NULL)
477         {
478                 trap = (Trap*)trap->next;
479                 define[0] = engine.getDefineOfValue("TRAP_TYPE", trap->type);
480                 define[1] = (char*)getActiveState(trap->active);
481                 snprintf(line, sizeof line, "%c TRAP %s %s %d %d %d %d %d %d %d %d %s %s\n", skill, trap->name, define[0], (int)trap->damage, (int)trap->speed, (int)trap->startX, (int)trap->startY, (int)trap->endX, (int)trap->endY, (int)trap->waitTime[0], (int)trap->waitTime[1], trap->sprite->name, define[1]);
482                 persistant->addLine(line);
483         }
484         
485         teleporter = (Teleporter*)map.teleportList.getHead();
486         
487         while (teleporter->next != NULL)
488         {
489                 teleporter = (Teleporter*)teleporter->next;
490                 define[0] = (char*)getActiveState(teleporter->active);
491                 snprintf(line, sizeof line, "%c TELEPORTER %s %d %d %d %d %s\n", skill, teleporter->name, (int)teleporter->x, (int)teleporter->y, (int)teleporter->destX, (int)teleporter->destY, define[0]);
492                 persistant->addLine(line);
493         }
494         
495         lineDef = (LineDef*)map.lineList.getHead();
496         
497         while (lineDef->next != NULL)
498         {
499                 lineDef = (LineDef*)lineDef->next;
500                 define[0] = (char*)getActiveState(lineDef->activated);
501                 snprintf(line, sizeof line, "%c LINEDEF \"%s\" %s \"%s\" %d %d %d %d %s\n", skill, lineDef->name, lineDef->linkName, lineDef->activateMessage, (int)lineDef->x, (int)lineDef->y, (int)lineDef->width, (int)lineDef->height, define[0]);
502                 persistant->addLine(line);
503         }
504         
505         spawnPoint = (SpawnPoint*)map.spawnList.getHead();
506         
507         while (spawnPoint->next != NULL)
508         {
509                 spawnPoint = (SpawnPoint*)spawnPoint->next;
510                 define[0] = engine.getDefineOfValue("SPW_", spawnPoint->spawnType);
511                 
512                 if (strstr(define[0], "HAZARD"))
513                 {
514                         define[1] = engine.getDefineOfValue("HAZARD_", spawnPoint->spawnSubType);
515                 }
516                 else
517                 {
518                         define[1] = engine.getDefineOfValue("SPW_", spawnPoint->spawnSubType);
519                 }
520                         
521                 define[2] = (char*)getActiveState(spawnPoint->active);
522                 snprintf(line, sizeof line, "%c SPAWNPOINT %s %d %d %s %s %d %d %s\n", skill, spawnPoint->name, (int)spawnPoint->x, (int)spawnPoint->y, define[0], define[1], (int)(spawnPoint->minInterval / 60), (int)(spawnPoint->maxInterval / 60), define[2]);
523                 persistant->addLine(line);
524         }
525         
526         for (int i = 0 ; i < 10 ; i++)
527         {
528                 if (map.getSpawnableEnemy(i) != NULL)
529                 {
530                         snprintf(line, sizeof line, "%c SPAWNABLE_ENEMY \"%s\"\n", skill, map.getSpawnableEnemy(i));
531                         persistant->addLine(line);
532                 }
533         }
534         
535         if (map.waterLevel != -1)
536         {
537                 snprintf(line, sizeof line, "%c WATERLEVEL %d\n", skill, (int)map.waterLevel);
538                 persistant->addLine(line);
539         }
540         
541         // We don't need this anymore. Remove it to free up some memory...
542         engine.defineList.clear();
543 }