Removed that logo from this bramch aswell..
[dbw.git] / src / mapData.cpp
blobd2fbeae49c3da04e1ef7131bdcfaa8604739d1cd
1 /*
2 Copyright © 2004 Parallel Realities
3 Copyright © 2007-2008 Kővágó Zoltán <DirtY.iCE.hu@gmail.com>
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.
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.
14 See the GNU General Public License for more details.
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.
22 #include "CAudio.h"
23 #include "CGame.h"
24 #include "CGameData.h"
25 #include "CGraphics.h"
26 #include "CMap.h"
27 #include "CPersistant.h"
28 #include "CPersistData.h"
29 #include "CSwitch.h"
30 #include "CTrain.h"
31 #include "CSpawnPoint.h"
32 #include "console/console.hpp"
33 #include "gettext.hpp"
34 #include "mapData.h"
36 void getMapTokens()
38 char skillLevel[10];
39 char mapEntity[255];
40 char string[10][1024];
41 int param[10];
42 bool allowAtSkillLevel = false;
44 bool previouslyCleared = false;
46 char *token = NULL;
48 Persistant *persistant = NULL;
49 PersistData *persistData = NULL;
51 while (true)
53 if (!previouslyCleared)
55 token = strtok(NULL, "\n");
57 else
59 persistData = (PersistData*)persistData->next;
61 if (persistData == NULL)
62 break;
64 token = persistData->data;
67 graphics.showLoading(1, 100);
68 graphics.delay(1);
70 allowAtSkillLevel = false;
72 sscanf(token, "%s", skillLevel);
74 if ((strstr(skillLevel, "E")) && (game.skill == 0))
76 allowAtSkillLevel = true;
79 if ((strstr(skillLevel, "M")) && (game.skill == 1))
81 allowAtSkillLevel = true;
84 if ((strstr(skillLevel, "H")) && (game.skill >= 2))
86 allowAtSkillLevel = true;
89 if ((strstr(skillLevel, "X")) && (game.skill == 3))
91 allowAtSkillLevel = true;
94 // This is just for practice missions
95 if (game.skill == -1)
96 allowAtSkillLevel = true;
98 // Ignore comments
99 if (strstr(skillLevel, "//"))
100 allowAtSkillLevel = false;
102 if (strcmp("@EOF@", skillLevel) == 0)
104 break;
107 if (allowAtSkillLevel)
109 sscanf(token, "%*s %s", mapEntity);
111 if (strcmp("STAGENAME", mapEntity) == 0)
113 sscanf(token, "%*s %*s %*c %[^\"] %*c", string[0]);
115 map.setName(string[0]);
116 game.setStageName(string[0]);
118 else if (strcmp("PREVIOUSLY_VISITED", mapEntity) == 0)
120 previouslyCleared = gameData.stagePreviouslyCleared(map.name);
122 if (previouslyCleared)
124 debug("pers", 2) << "Reading Persistance Data..." << std::endl;
125 persistant = map.getPersistant(map.name);
126 persistData = (PersistData*)persistant->dataList.getHead();
129 else if (strcmp("TIMELIMIT", mapEntity) == 0)
131 sscanf(token, "%*s %*s %d %d", &param[0], &param[1]);
132 map.remainingMinutes = param[0];
133 map.remainingSeconds = param[1];
135 else if (strcmp("TRAIN", mapEntity) == 0)
137 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]);
138 map.addTrain(string[0], param[0], param[1], param[2], param[3], param[4], engine.getValueOfDefine(string[1]), engine.getValueOfDefine(string[2]));
140 else if (strcmp("DOOR", mapEntity) == 0)
142 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]);
143 map.addDoor(string[0], engine.getValueOfDefine(string[1]), param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[2]));
145 else if (strcmp("SWITCH", mapEntity) == 0)
147 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]);
148 map.addSwitch(string[0], string[1], string[2], string[3], engine.getValueOfDefine(string[4]), param[0], param[1], engine.getValueOfDefine(string[5]));
150 else if (strcmp("ITEM", mapEntity) == 0)
152 sscanf(token, "%*s %*s %d %*c %[^\"] %*c %d %d %s", &param[0], string[0], &param[1], &param[2], string[1]);
154 addItem(param[0], string[0], param[1], param[2], string[1], 60, 1, 0, false);
156 if (param[0] >= ITEM_MISC)
158 map.totalItems++;
161 else if (strcmp("OBSTACLE", mapEntity) == 0)
163 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d %s", string[0], &param[0], &param[1], string[1]);
165 addObstacle(string[0], param[0], param[1], string[1]);
167 else if (strcmp("OBJECTIVE", mapEntity) == 0)
169 sscanf(token, "%*s %*s %*c %[^\"] %*c %*c %[^\"] %*c %d %s", string[0], string[1], &param[0], string[2]);
171 map.addObjective(string[0], string[1], param[0], engine.getValueOfDefine(string[2]));
173 else if (strcmp("START", mapEntity) == 0)
175 sscanf(token, "%*s %*s %d %d", &param[0], &param[1]);
177 player.place(param[0], param[1]);
179 game.setCheckPoint(param[0], param[1]);
180 game.setObjectiveCheckPoint();
183 else if (strcmp("ENEMY", mapEntity) == 0)
185 if (!engine.devNoMonsters)
187 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d", string[0], &param[0], &param[1]);
189 if ((game.skill == 0) && (map.waterLevel != -1))
191 addEnemy("Aqua Blob", param[0], param[1], 0);
193 else
195 addEnemy(string[0], param[0], param[1], 0);
199 else if (strcmp("MIA", mapEntity) == 0)
201 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d %s", string[0], &param[0], &param[1], string[1]);
202 addMIA(string[0], param[0], param[1], engine.getValueOfDefine(string[1]));
203 map.totalMIAs++;
205 else if (strcmp("REQUIREDMIAS", mapEntity) == 0)
207 sscanf(token, "%*s %*s %d", &param[0]);
208 map.requiredMIAs = param[0];
210 else if (strcmp("LINEDEF", mapEntity) == 0)
212 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]);
214 addLineDef(string[0], string[1], string[2], param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[3]));
216 else if (strcmp("SPAWNPOINT", mapEntity) == 0)
218 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]);
219 map.addSpawnPoint(string[0], param[0], param[1], engine.getValueOfDefine(string[1]), engine.getValueOfDefine(string[2]), param[2], param[3], engine.getValueOfDefine(string[3]));
221 else if (strcmp("SPAWNABLE_ENEMY", mapEntity) == 0)
223 sscanf(token, "%*s %*s %*c %[^\"] %*c", string[0]);
224 map.setAllowableEnemy(getDefinedEnemy(string[0]));
226 else if (strcmp("TELEPORTER", mapEntity) == 0)
228 sscanf(token, "%*s %*s %s %d %d %d %d %s", string[0], &param[0], &param[1], &param[2], &param[3], string[1]);
229 addTeleporter(string[0], param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[1]));
231 else if (strcmp("TRAP", mapEntity) == 0)
233 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]);
234 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]));
236 else if (strcmp("SPRITE", mapEntity) == 0)
238 sscanf(token, "%*s %*s %[^\n\r]", string[0]);
239 loadSprite(string[0]);
241 else if (strcmp("DEFENEMY", mapEntity) == 0)
243 sscanf(token, "%*s %*s %[^\n\r]", string[0]);
244 loadEnemy(string[0]);
246 else if (strcmp("TILESET", mapEntity) == 0)
248 sscanf(token, "%*s %*s %s", string[0]);
249 map.evalTileset(string[0]);
250 graphics.loadMapTiles(string[0]);
252 else if (strcmp("CLIPPING", mapEntity) == 0)
254 sscanf(token, "%*s %*s %d %d %d %d", &param[0], &param[1], &param[2], &param[3]);
255 map.setClipping(param[0], param[1], param[2], param[3]);
257 else if (strcmp("AMBIENCE", mapEntity) == 0)
259 sscanf(token, "%*s %*s %s", string[0]);
260 if (!audio.loadSound(SND_AMBIANCE, string[0]))
261 graphics.showErrorAndExit(ERR_FILE, string[0]);
263 else if (strcmp("WATERLEVEL", mapEntity) == 0)
265 sscanf(token, "%*s %*s %d", &param[0]);
267 map.requiredWaterLevel = param[0];
269 if (!previouslyCleared)
271 map.waterLevel = param[0];
273 else
275 map.waterLevel = 281;
278 if (game.skill == 0)
280 map.waterLevel = 281;
281 map.requiredWaterLevel = 222;
284 else if (strcmp("ALPHATILES", mapEntity) == 0)
286 for (int i = 0 ; i < 15 ; i++)
287 *token++;
289 while (true)
291 sscanf(token, "%d", &param[0]);
293 if (param[0] == -1)
294 break;
296 debug("misc", 3) << "Setting Alpha for Tile " << param[0] << std::endl;
298 SDL_SetAlpha(graphics.tile[param[0]], SDL_SRCALPHA|SDL_RLEACCEL, 128);
300 while (true)
302 *token++;
304 if (*token == ' ')
305 break;
309 else if (strcmp("BACKGROUND", mapEntity) == 0)
311 sscanf(token, "%*s %*s %s", string[0]);
312 graphics.loadBackground(string[0], true);
314 else if (strcmp("MUSIC", mapEntity) == 0)
316 sscanf(token, "%*s %*s %s", string[0]);
317 audio.loadMusic(string[0]);
319 else if (allowAtSkillLevel)
321 graphics.showErrorAndExit(_("Symbol '%s' not recognised or not implemented in map data"), mapEntity);
324 else
326 //debug(("Ignoring Line: %s\n", token));
331 We need to make sure the player doesn't appear in a wall that was previously
332 destroyed. Things like this aren't stored so we will just remove a block they
333 make have been "in"
335 if (previouslyCleared)
337 int x = game.checkPointX;
338 int y = game.checkPointY;
340 x = x >> BRICKSHIFT;
341 y = y >> BRICKSHIFT;
343 if ((map.data[x][y] >= MAP_BREAKABLE) && (map.data[x][y] <= MAP_BREAKABLE2))
345 map.data[x][y] = MAP_AIR;
350 const char *getActiveState(bool active)
352 if (active)
354 return "ACTIVE";
357 return "INACTIVE";
360 void createPersistantMapData()
362 if (!engine.loadDefines())
364 graphics.showErrorAndExit(_("Could not load map define list '%s'"), "data/defines.h");
367 Persistant *persistant = (Persistant*)map.createPersistant(map.name);
368 persistant->clear();
370 if (perfectlyCompleted())
372 debug("pers", 2) << "createPersistantMapData :: Perfect - Skipping" << std::endl;
373 return;
376 char line[1024];
377 strcpy(line, "");
379 char skill;
381 switch (game.skill)
383 case 0:
384 skill = 'E';
385 break;
386 case 1:
387 skill = 'M';
388 break;
389 default:
390 skill = 'H';
391 break;
394 sprintf(line, "%c START %d %d\n", skill, (int)game.checkPointX, (int)game.checkPointY);
395 persistant->addLine(line);
397 Entity *ent;
398 Switch *swt;
399 Train *train;
400 Trap *trap;
401 Teleporter *teleporter;
402 LineDef *lineDef;
403 SpawnPoint *spawnPoint;
405 const char *define[3];
407 ent = (Entity*)map.enemyList.getHead();
409 while (ent->next != NULL)
411 ent = (Entity*)ent->next;
412 sprintf(line, "%c ENEMY \"%s\" %d %d\n", skill, ent->name, (int)ent->x, (int)ent->y);
413 persistant->addLine(line);
416 ent = (Entity*)map.itemList.getHead();
418 while (ent->next != NULL)
420 ent = (Entity*)ent->next;
422 // Don't save items that are dying...
423 if (ent->flags & ENT_DYING)
425 continue;
428 sprintf(line, "%c ITEM %d \"%s\" %d %d %s\n", skill, ent->id, ent->name, (int)ent->x, (int)ent->y, ent->sprite[0]->name);
429 persistant->addLine(line);
432 ent = (Entity*)map.obstacleList.getHead();
434 while (ent->next != NULL)
436 ent = (Entity*)ent->next;
437 sprintf(line, "%c OBSTACLE \"%s\" %d %d %s\n", skill, ent->name, (int)ent->x, (int)ent->y, ent->sprite[0]->name);
438 persistant->addLine(line);
441 swt = (Switch*)map.switchList.getHead();
443 while (swt->next != NULL)
445 swt = (Switch*)swt->next;
446 define[0] = engine.getDefineOfValue("SWT_", swt->type);
447 define[1] = getActiveState(swt->activated);
449 sprintf(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]);
451 persistant->addLine(line);
454 train = (Train*)map.trainList.getHead();
456 while (train->next != NULL)
458 train = (Train*)train->next;
460 if (train->type != TR_TRAIN)
462 if (train->type >= TR_SLIDEDOOR)
464 define[0] = engine.getDefineOfValue("_SLIDE", train->type);
466 else
468 define[0] = engine.getDefineOfValue("_DOO", train->type);
471 define[1] = getActiveState(train->active);
472 sprintf(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]);
474 else
476 define[0] = engine.getDefineOfValue("TR_A", train->waitAtStart);
477 define[1] = getActiveState(train->active);
478 sprintf(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]);
481 persistant->addLine(line);
484 trap = (Trap*)map.trapList.getHead();
486 while (trap->next != NULL)
488 trap = (Trap*)trap->next;
489 define[0] = engine.getDefineOfValue("TRAP_TYPE", trap->type);
490 define[1] = getActiveState(trap->active);
491 sprintf(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]);
492 persistant->addLine(line);
495 teleporter = (Teleporter*)map.teleportList.getHead();
497 while (teleporter->next != NULL)
499 teleporter = (Teleporter*)teleporter->next;
500 define[0] = getActiveState(teleporter->active);
501 sprintf(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]);
502 persistant->addLine(line);
505 lineDef = (LineDef*)map.lineList.getHead();
507 while (lineDef->next != NULL)
509 lineDef = (LineDef*)lineDef->next;
510 define[0] = getActiveState(lineDef->activated);
511 sprintf(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]);
512 persistant->addLine(line);
515 spawnPoint = (SpawnPoint*)map.spawnList.getHead();
517 while (spawnPoint->next != NULL)
519 spawnPoint = (SpawnPoint*)spawnPoint->next;
520 define[0] = engine.getDefineOfValue("SPW_", spawnPoint->spawnType);
522 if (strstr(define[0], "HAZARD"))
524 define[1] = engine.getDefineOfValue("HAZARD_", spawnPoint->spawnSubType);
526 else
528 define[1] = engine.getDefineOfValue("SPW_", spawnPoint->spawnSubType);
531 define[2] = getActiveState(spawnPoint->active);
532 sprintf(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]);
533 persistant->addLine(line);
536 for (int i = 0 ; i < 10 ; i++)
538 if (map.getSpawnableEnemy(i) != NULL)
540 sprintf(line, "%c SPAWNABLE_ENEMY \"%s\"\n", skill, map.getSpawnableEnemy(i));
541 persistant->addLine(line);
545 if (map.waterLevel != -1)
547 sprintf(line, "%c WATERLEVEL %d\n", skill, (int)map.waterLevel);
548 persistant->addLine(line);
551 // We don't need this anymore. Remove it to free up some memory...
552 engine.defineList.clear();