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.
27 char string[10][1024];
29 bool allowAtSkillLevel = false;
31 bool previouslyCleared = false;
35 Persistant *persistant = NULL;
36 PersistData *persistData = NULL;
40 if (!previouslyCleared)
42 token = strtok(NULL, "\n");
46 persistData = (PersistData*)persistData->next;
48 if (persistData == NULL)
51 token = persistData->data;
55 graphics.showLoading(1, 100);
59 allowAtSkillLevel = false;
61 sscanf(token, "%s", skillLevel);
63 if ((strstr(skillLevel, "E")) && (game.skill == 0))
65 allowAtSkillLevel = true;
68 if ((strstr(skillLevel, "M")) && (game.skill == 1))
70 allowAtSkillLevel = true;
73 if ((strstr(skillLevel, "H")) && (game.skill >= 2))
75 allowAtSkillLevel = true;
78 if ((strstr(skillLevel, "X")) && (game.skill == 3))
80 allowAtSkillLevel = true;
83 // This is just for practice missions
85 allowAtSkillLevel = true;
88 if (strstr(skillLevel, "//"))
89 allowAtSkillLevel = false;
91 if (strcmp("@EOF@", skillLevel) == 0)
96 if (allowAtSkillLevel)
98 sscanf(token, "%*s %s", mapEntity);
100 if (strcmp("STAGENAME", mapEntity) == 0)
102 sscanf(token, "%*s %*s %*c %[^\"] %*c", string[0]);
104 map.setName(string[0]);
105 game.setStageName(string[0]);
107 else if (strcmp("PREVIOUSLY_VISITED", mapEntity) == 0)
109 previouslyCleared = gameData.stagePreviouslyCleared(map.name);
111 if (previouslyCleared)
113 debug(("Reading Persistance Data...\n"));
114 persistant = map.getPersistant(map.name);
115 persistData = (PersistData*)persistant->dataList.getHead();
118 else if (strcmp("TIMELIMIT", mapEntity) == 0)
120 debug(("Loading Time Limit: %s\n", token));
121 sscanf(token, "%*s %*s %d %d", ¶m[0], ¶m[1]);
122 map.remainingMinutes = param[0];
123 map.remainingSeconds = param[1];
125 else if (strcmp("TRAIN", mapEntity) == 0)
127 sscanf(token, "%*s %*s %s %d %d %d %d %d %s %s", string[0], ¶m[0], ¶m[1], ¶m[2], ¶m[3], ¶m[4], string[1], string[2]);
128 map.addTrain(string[0], param[0], param[1], param[2], param[3], param[4], engine.getValueOfDefine(string[1]), engine.getValueOfDefine(string[2]));
130 else if (strcmp("DOOR", mapEntity) == 0)
132 sscanf(token, "%*s %*s %s %s %d %d %d %d %s", string[0], string[1], ¶m[0], ¶m[1], ¶m[2], ¶m[3], string[2]);
133 map.addDoor(string[0], engine.getValueOfDefine(string[1]), param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[2]));
135 else if (strcmp("SWITCH", mapEntity) == 0)
137 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], ¶m[0], ¶m[1], string[5]);
138 map.addSwitch(string[0], string[1], string[2], string[3], engine.getValueOfDefine(string[4]), param[0], param[1], engine.getValueOfDefine(string[5]));
140 else if (strcmp("ITEM", mapEntity) == 0)
142 sscanf(token, "%*s %*s %d %*c %[^\"] %*c %d %d %s", ¶m[0], string[0], ¶m[1], ¶m[2], string[1]);
144 addItem(param[0], string[0], param[1], param[2], string[1], 60, 1, 0, false);
146 if (param[0] >= ITEM_MISC)
151 else if (strcmp("OBSTACLE", mapEntity) == 0)
153 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d %s", string[0], ¶m[0], ¶m[1], string[1]);
155 addObstacle(string[0], param[0], param[1], string[1]);
157 else if (strcmp("OBJECTIVE", mapEntity) == 0)
159 sscanf(token, "%*s %*s %*c %[^\"] %*c %*c %[^\"] %*c %d %s", string[0], string[1], ¶m[0], string[2]);
161 map.addObjective(string[0], string[1], param[0], engine.getValueOfDefine(string[2]));
163 else if (strcmp("START", mapEntity) == 0)
165 sscanf(token, "%*s %*s %d %d", ¶m[0], ¶m[1]);
167 player.place(param[0], param[1]);
169 game.setCheckPoint(param[0], param[1]);
170 game.setObjectiveCheckPoint();
173 else if (strcmp("ENEMY", mapEntity) == 0)
175 if (!engine.devNoMonsters)
177 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d", string[0], ¶m[0], ¶m[1]);
179 if ((game.skill == 0) && (map.waterLevel != -1))
181 addEnemy("Aqua Blob", param[0], param[1], 0);
185 addEnemy(string[0], param[0], param[1], 0);
189 else if (strcmp("MIA", mapEntity) == 0)
191 sscanf(token, "%*s %*s %*c %[^\"] %*c %d %d %s", string[0], ¶m[0], ¶m[1], string[1]);
192 addMIA(string[0], param[0], param[1], engine.getValueOfDefine(string[1]));
195 else if (strcmp("REQUIREDMIAS", mapEntity) == 0)
197 sscanf(token, "%*s %*s %d", ¶m[0]);
198 map.requiredMIAs = param[0];
200 else if (strcmp("LINEDEF", mapEntity) == 0)
202 sscanf(token, "%*s %*s %*c %[^\"] %*c %s %*c %[^\"] %*c %d %d %d %d %s", string[0], string[1], string[2], ¶m[0], ¶m[1], ¶m[2], ¶m[3], string[3]);
204 addLineDef(string[0], string[1], string[2], param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[3]));
206 else if (strcmp("SPAWNPOINT", mapEntity) == 0)
208 sscanf(token, "%*s %*s %s %d %d %s %s %d %d %s", string[0], ¶m[0], ¶m[1], string[1], string[2], ¶m[2], ¶m[3], string[3]);
209 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 else if (strcmp("SPAWNABLE_ENEMY", mapEntity) == 0)
213 sscanf(token, "%*s %*s %*c %[^\"] %*c", string[0]);
214 map.setAllowableEnemy(getDefinedEnemy(string[0]));
216 else if (strcmp("TELEPORTER", mapEntity) == 0)
218 sscanf(token, "%*s %*s %s %d %d %d %d %s", string[0], ¶m[0], ¶m[1], ¶m[2], ¶m[3], string[1]);
219 addTeleporter(string[0], param[0], param[1], param[2], param[3], engine.getValueOfDefine(string[1]));
221 else if (strcmp("TRAP", mapEntity) == 0)
223 sscanf(token, "%*s %*s %s %s %d %d %d %d %d %d %d %d %s %s", string[0], string[1], ¶m[0], ¶m[1], ¶m[2], ¶m[3], ¶m[4], ¶m[5], ¶m[6], ¶m[7], string[2], string[3]);
224 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 else if (strcmp("SPRITE", mapEntity) == 0)
228 sscanf(token, "%*s %*s %[^\n\r]", string[0]);
229 loadSprite(string[0]);
231 else if (strcmp("DEFENEMY", mapEntity) == 0)
233 sscanf(token, "%*s %*s %[^\n\r]", string[0]);
234 loadEnemy(string[0]);
236 else if (strcmp("TILESET", mapEntity) == 0)
238 sscanf(token, "%*s %*s %s", string[0]);
239 map.evalTileset(string[0]);
240 graphics.loadMapTiles(string[0]);
242 else if (strcmp("CLIPPING", mapEntity) == 0)
244 sscanf(token, "%*s %*s %d %d %d %d", ¶m[0], ¶m[1], ¶m[2], ¶m[3]);
245 map.setClipping(param[0], param[1], param[2], param[3]);
247 else if (strcmp("AMBIENCE", mapEntity) == 0)
249 sscanf(token, "%*s %*s %s", string[0]);
250 if (!audio.loadSound(SND_AMBIANCE, string[0]))
251 graphics.showErrorAndExit(ERR_FILE, string[0]);
253 else if (strcmp("WATERLEVEL", mapEntity) == 0)
255 sscanf(token, "%*s %*s %d", ¶m[0]);
257 map.requiredWaterLevel = param[0];
259 if (!previouslyCleared)
261 map.waterLevel = param[0];
265 map.waterLevel = 281;
270 map.waterLevel = 281;
271 map.requiredWaterLevel = 222;
274 else if (strcmp("ALPHATILES", mapEntity) == 0)
276 for (int i = 0 ; i < 15 ; i++)
281 sscanf(token, "%d", ¶m[0]);
286 debug(("Setting Alpha for Tile %d\n", param[0]));
288 SDL_SetAlpha(graphics.tile[param[0]], SDL_SRCALPHA|SDL_RLEACCEL, 130);
299 else if (strcmp("BACKGROUND", mapEntity) == 0)
301 sscanf(token, "%*s %*s %s", string[0]);
302 graphics.loadBackground(string[0]);
304 else if (strcmp("MUSIC", mapEntity) == 0)
306 sscanf(token, "%*s %*s %s", string[0]);
307 audio.loadMusic(string[0]);
309 else if (allowAtSkillLevel)
311 graphics.showErrorAndExit("Symbol '%s' not recognised or not implemented in map data", mapEntity);
316 //debug(("Ignoring Line: %s\n", token));
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
325 if (previouslyCleared)
327 int x = game.checkPointX;
328 int y = game.checkPointY;
333 if ((map.data[x][y] >= MAP_BREAKABLE) && (map.data[x][y] <= MAP_BREAKABLE2))
335 map.data[x][y] = MAP_AIR;
340 const char *getActiveState(bool active)
350 void createPersistantMapData()
352 if (!engine.loadDefines())
354 graphics.showErrorAndExit("Could not load map define list '%s'", "data/defines.h");
357 Persistant *persistant = (Persistant*)map.createPersistant(map.name);
360 if (perfectlyCompleted())
362 debug(("createPersistantMapData :: Perfect - Skipping\n"));
384 sprintf(line, "%c START %d %d\n", skill, (int)game.checkPointX, (int)game.checkPointY);
385 persistant->addLine(line);
391 Teleporter *teleporter;
393 SpawnPoint *spawnPoint;
397 ent = (Entity*)map.enemyList.getHead();
399 while (ent->next != NULL)
401 ent = (Entity*)ent->next;
402 sprintf(line, "%c ENEMY \"%s\" %d %d\n", skill, ent->name, (int)ent->x, (int)ent->y);
403 persistant->addLine(line);
406 ent = (Entity*)map.itemList.getHead();
408 while (ent->next != NULL)
410 ent = (Entity*)ent->next;
412 // Don't save items that are dying...
413 if (ent->flags & ENT_DYING)
418 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);
419 persistant->addLine(line);
422 ent = (Entity*)map.obstacleList.getHead();
424 while (ent->next != NULL)
426 ent = (Entity*)ent->next;
427 sprintf(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);
431 swt = (Switch*)map.switchList.getHead();
433 while (swt->next != NULL)
435 swt = (Switch*)swt->next;
436 define[0] = engine.getDefineOfValue("SWT_", swt->type);
437 define[1] = (char*)getActiveState(swt->activated);
439 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]);
441 persistant->addLine(line);
444 train = (Train*)map.trainList.getHead();
446 while (train->next != NULL)
448 train = (Train*)train->next;
450 if (train->type != TR_TRAIN)
452 if (train->type >= TR_SLIDEDOOR)
454 define[0] = engine.getDefineOfValue("_SLIDE", train->type);
458 define[0] = engine.getDefineOfValue("_DOO", train->type);
461 define[1] = (char*)getActiveState(train->active);
462 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]);
466 define[0] = engine.getDefineOfValue("TR_A", train->waitAtStart);
467 define[1] = (char*)getActiveState(train->active);
468 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]);
471 persistant->addLine(line);
474 trap = (Trap*)map.trapList.getHead();
476 while (trap->next != NULL)
478 trap = (Trap*)trap->next;
479 define[0] = engine.getDefineOfValue("TRAP_TYPE", trap->type);
480 define[1] = (char*)getActiveState(trap->active);
481 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]);
482 persistant->addLine(line);
485 teleporter = (Teleporter*)map.teleportList.getHead();
487 while (teleporter->next != NULL)
489 teleporter = (Teleporter*)teleporter->next;
490 define[0] = (char*)getActiveState(teleporter->active);
491 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]);
492 persistant->addLine(line);
495 lineDef = (LineDef*)map.lineList.getHead();
497 while (lineDef->next != NULL)
499 lineDef = (LineDef*)lineDef->next;
500 define[0] = (char*)getActiveState(lineDef->activated);
501 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]);
502 persistant->addLine(line);
505 spawnPoint = (SpawnPoint*)map.spawnList.getHead();
507 while (spawnPoint->next != NULL)
509 spawnPoint = (SpawnPoint*)spawnPoint->next;
510 define[0] = engine.getDefineOfValue("SPW_", spawnPoint->spawnType);
512 if (strstr(define[0], "HAZARD"))
514 define[1] = engine.getDefineOfValue("HAZARD_", spawnPoint->spawnSubType);
518 define[1] = engine.getDefineOfValue("SPW_", spawnPoint->spawnSubType);
521 define[2] = (char*)getActiveState(spawnPoint->active);
522 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]);
523 persistant->addLine(line);
526 for (int i = 0 ; i < 10 ; i++)
528 if (map.getSpawnableEnemy(i) != NULL)
530 sprintf(line, "%c SPAWNABLE_ENEMY \"%s\"\n", skill, map.getSpawnableEnemy(i));
531 persistant->addLine(line);
535 if (map.waterLevel != -1)
537 sprintf(line, "%c WATERLEVEL %d\n", skill, (int)map.waterLevel);
538 persistant->addLine(line);
541 // We don't need this anymore. Remove it to free up some memory...
542 engine.defineList.clear();