1 | /* |
1 | /* |
2 | * static char *rcsid_map_c = |
2 | * static char *rcsid_map_c = |
3 | * "$Id: map.C,v 1.16 2006/08/30 16:30:37 root Exp $"; |
3 | * "$Id: map.C,v 1.20 2006/09/03 00:18:40 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
482 | op->x += tmp->x; |
482 | op->x += tmp->x; |
483 | op->y += tmp->y; |
483 | op->y += tmp->y; |
484 | op->head = tmp; |
484 | op->head = tmp; |
485 | op->map = m; |
485 | op->map = m; |
486 | last->more = op; |
486 | last->more = op; |
487 | if (tmp->name != op->name) { |
|
|
488 | if (op->name) free_string(op->name); |
|
|
489 | op->name = add_string(tmp->name); |
487 | op->name = tmp->name; |
490 | } |
|
|
491 | if (tmp->title != op->title) { |
|
|
492 | if (op->title) free_string(op->title); |
|
|
493 | op->title = add_string(tmp->title); |
488 | op->title = tmp->title; |
494 | } |
|
|
495 | /* we could link all the parts onto tmp, and then just |
489 | /* we could link all the parts onto tmp, and then just |
496 | * call insert_ob_in_map once, but the effect is the same, |
490 | * call insert_ob_in_map once, but the effect is the same, |
497 | * as insert_ob_in_map will call itself with each part, and |
491 | * as insert_ob_in_map will call itself with each part, and |
498 | * the coding is simpler to just to it here with each part. |
492 | * the coding is simpler to just to it here with each part. |
499 | */ |
493 | */ |
… | |
… | |
528 | /* if the archetype for the object is null, means that we |
522 | /* if the archetype for the object is null, means that we |
529 | * got an invalid object. Don't do anything with it - the game |
523 | * got an invalid object. Don't do anything with it - the game |
530 | * or editor will not be able to do anything with it either. |
524 | * or editor will not be able to do anything with it either. |
531 | */ |
525 | */ |
532 | if (op->arch==NULL) { |
526 | if (op->arch==NULL) { |
533 | LOG(llevDebug,"Discarding object without arch: %s\n", op->name?op->name:"(null)"); |
527 | LOG(llevDebug,"Discarding object without arch: %s\n", op->name?(const char *)op->name:"(null)"); |
534 | continue; |
528 | continue; |
535 | } |
529 | } |
536 | |
530 | |
537 | |
531 | |
538 | switch(i) { |
532 | switch(i) { |
… | |
… | |
618 | * Modified to no longer take a path option which was not being |
612 | * Modified to no longer take a path option which was not being |
619 | * used anyways. MSW 2001-07-01 |
613 | * used anyways. MSW 2001-07-01 |
620 | */ |
614 | */ |
621 | |
615 | |
622 | mapstruct *get_linked_map(void) { |
616 | mapstruct *get_linked_map(void) { |
623 | mapstruct *map=(mapstruct *) calloc(1,sizeof(mapstruct)); |
617 | mapstruct *map = new mapstruct; |
624 | mapstruct *mp; |
618 | mapstruct *mp; |
625 | |
|
|
626 | if(map==NULL) |
|
|
627 | fatal(OUT_OF_MEMORY); |
|
|
628 | |
619 | |
629 | for(mp=first_map;mp!=NULL&&mp->next!=NULL;mp=mp->next); |
620 | for(mp=first_map;mp!=NULL&&mp->next!=NULL;mp=mp->next); |
630 | if(mp==NULL) |
621 | if(mp==NULL) |
631 | first_map=map; |
622 | first_map=map; |
632 | else |
623 | else |
… | |
… | |
888 | * what really should be used. |
879 | * what really should be used. |
889 | */ |
880 | */ |
890 | else if (!strcmp(key,"oid")) { |
881 | else if (!strcmp(key,"oid")) { |
891 | fp.get (m, atoi(value)); |
882 | fp.get (m, atoi(value)); |
892 | } else if (!strcmp(key, "attach")) { |
883 | } else if (!strcmp(key, "attach")) { |
893 | m->attach = add_string (value); |
884 | m->attach = value; |
894 | } else if (!strcmp(key,"hp") || !strcmp(key, "enter_x")) { |
885 | } else if (!strcmp(key,"hp") || !strcmp(key, "enter_x")) { |
895 | m->enter_x = atoi(value); |
886 | m->enter_x = atoi(value); |
896 | } else if (!strcmp(key,"sp") || !strcmp(key, "enter_y")) { |
887 | } else if (!strcmp(key,"sp") || !strcmp(key, "enter_y")) { |
897 | m->enter_y = atoi(value); |
888 | m->enter_y = atoi(value); |
898 | } else if (!strcmp(key,"x") || !strcmp(key, "width")) { |
889 | } else if (!strcmp(key,"x") || !strcmp(key, "width")) { |
… | |
… | |
1225 | } |
1216 | } |
1226 | else |
1217 | else |
1227 | { |
1218 | { |
1228 | if (!m->tmpname) |
1219 | if (!m->tmpname) |
1229 | m->tmpname = tempnam_local (settings.tmpdir, NULL); |
1220 | m->tmpname = tempnam_local (settings.tmpdir, NULL); |
|
|
1221 | |
1230 | strcpy (filename, m->tmpname); |
1222 | strcpy (filename, m->tmpname); |
1231 | } |
1223 | } |
1232 | |
1224 | |
1233 | LOG (llevDebug, "Saving map %s to %s\n", m->path, filename); |
1225 | LOG (llevDebug, "Saving map %s to %s\n", m->path, filename); |
1234 | m->in_memory = MAP_SAVING; |
1226 | m->in_memory = MAP_SAVING; |
1235 | |
1227 | |
1236 | object_freezer fp (filename); |
1228 | object_freezer freezer; |
1237 | |
1229 | |
1238 | /* legacy */ |
1230 | /* legacy */ |
1239 | fprintf (fp, "arch map\n"); |
1231 | fprintf (freezer, "arch map\n"); |
1240 | if (m->name) |
1232 | if (m->name) |
1241 | fprintf (fp, "name %s\n", m->name); |
1233 | fprintf (freezer, "name %s\n", m->name); |
1242 | if (!flag) |
1234 | if (!flag) |
1243 | fprintf (fp, "swap_time %d\n", m->swap_time); |
1235 | fprintf (freezer, "swap_time %d\n", m->swap_time); |
1244 | if (m->reset_timeout) |
1236 | if (m->reset_timeout) |
1245 | fprintf (fp, "reset_timeout %d\n", m->reset_timeout); |
1237 | fprintf (freezer, "reset_timeout %d\n", m->reset_timeout); |
1246 | if (m->fixed_resettime) |
1238 | if (m->fixed_resettime) |
1247 | fprintf (fp, "fixed_resettime %d\n", m->fixed_resettime); |
1239 | fprintf (freezer, "fixed_resettime %d\n", m->fixed_resettime); |
1248 | /* we unfortunately have no idea if this is a value the creator set |
1240 | /* we unfortunately have no idea if this is a value the creator set |
1249 | * or a difficulty value we generated when the map was first loaded |
1241 | * or a difficulty value we generated when the map was first loaded |
1250 | */ |
1242 | */ |
1251 | if (m->difficulty) |
1243 | if (m->difficulty) |
1252 | fprintf (fp, "difficulty %d\n", m->difficulty); |
1244 | fprintf (freezer, "difficulty %d\n", m->difficulty); |
1253 | if (m->region) |
1245 | if (m->region) |
1254 | fprintf (fp, "region %s\n", m->region->name); |
1246 | fprintf (freezer, "region %s\n", m->region->name); |
1255 | if (m->shopitems) |
1247 | if (m->shopitems) |
1256 | { |
1248 | { |
1257 | print_shop_string (m, shop); |
1249 | print_shop_string (m, shop); |
1258 | fprintf (fp, "shopitems %s\n", shop); |
1250 | fprintf (freezer, "shopitems %s\n", shop); |
1259 | } |
1251 | } |
1260 | if (m->shopgreed) |
1252 | if (m->shopgreed) |
1261 | fprintf (fp, "shopgreed %f\n", m->shopgreed); |
1253 | fprintf (freezer, "shopgreed %f\n", m->shopgreed); |
1262 | #ifndef WIN32 |
1254 | #ifndef WIN32 |
1263 | if (m->shopmin) |
1255 | if (m->shopmin) |
1264 | fprintf (fp, "shopmin %llu\n", m->shopmin); |
1256 | fprintf (freezer, "shopmin %llu\n", m->shopmin); |
1265 | if (m->shopmax) |
1257 | if (m->shopmax) |
1266 | fprintf (fp, "shopmax %llu\n", m->shopmax); |
1258 | fprintf (freezer, "shopmax %llu\n", m->shopmax); |
1267 | #else |
1259 | #else |
1268 | if (m->shopmin) |
1260 | if (m->shopmin) |
1269 | fprintf (fp, "shopmin %I64u\n", m->shopmin); |
1261 | fprintf (freezer, "shopmin %I64u\n", m->shopmin); |
1270 | if (m->shopmax) |
1262 | if (m->shopmax) |
1271 | fprintf (fp, "shopmax %I64u\n", m->shopmax); |
1263 | fprintf (freezer, "shopmax %I64u\n", m->shopmax); |
1272 | #endif |
1264 | #endif |
1273 | if (m->shoprace) |
1265 | if (m->shoprace) |
1274 | fprintf (fp, "shoprace %s\n", m->shoprace); |
1266 | fprintf (freezer, "shoprace %s\n", m->shoprace); |
1275 | if (m->darkness) |
1267 | if (m->darkness) |
1276 | fprintf (fp, "darkness %d\n", m->darkness); |
1268 | fprintf (freezer, "darkness %d\n", m->darkness); |
1277 | if (m->width) |
1269 | if (m->width) |
1278 | fprintf (fp, "width %d\n", m->width); |
1270 | fprintf (freezer, "width %d\n", m->width); |
1279 | if (m->height) |
1271 | if (m->height) |
1280 | fprintf (fp, "height %d\n", m->height); |
1272 | fprintf (freezer, "height %d\n", m->height); |
1281 | if (m->enter_x) |
1273 | if (m->enter_x) |
1282 | fprintf (fp, "enter_x %d\n", m->enter_x); |
1274 | fprintf (freezer, "enter_x %d\n", m->enter_x); |
1283 | if (m->enter_y) |
1275 | if (m->enter_y) |
1284 | fprintf (fp, "enter_y %d\n", m->enter_y); |
1276 | fprintf (freezer, "enter_y %d\n", m->enter_y); |
1285 | if (m->msg) |
1277 | if (m->msg) |
1286 | fprintf (fp, "msg\n%sendmsg\n", m->msg); |
1278 | fprintf (freezer, "msg\n%sendmsg\n", m->msg); |
1287 | if (m->maplore) |
1279 | if (m->maplore) |
1288 | fprintf (fp, "maplore\n%sendmaplore\n", m->maplore); |
1280 | fprintf (freezer, "maplore\n%sendmaplore\n", m->maplore); |
1289 | if (m->unique) |
1281 | if (m->unique) |
1290 | fprintf (fp, "unique %d\n", m->unique); |
1282 | fprintf (freezer, "unique %d\n", m->unique); |
1291 | if (m->templatemap) |
1283 | if (m->templatemap) |
1292 | fprintf (fp, "template %d\n", m->templatemap); |
1284 | fprintf (freezer, "template %d\n", m->templatemap); |
1293 | if (m->outdoor) |
1285 | if (m->outdoor) |
1294 | fprintf (fp, "outdoor %d\n", m->outdoor); |
1286 | fprintf (freezer, "outdoor %d\n", m->outdoor); |
1295 | if (m->temp) |
1287 | if (m->temp) |
1296 | fprintf (fp, "temp %d\n", m->temp); |
1288 | fprintf (freezer, "temp %d\n", m->temp); |
1297 | if (m->pressure) |
1289 | if (m->pressure) |
1298 | fprintf (fp, "pressure %d\n", m->pressure); |
1290 | fprintf (freezer, "pressure %d\n", m->pressure); |
1299 | if (m->humid) |
1291 | if (m->humid) |
1300 | fprintf (fp, "humid %d\n", m->humid); |
1292 | fprintf (freezer, "humid %d\n", m->humid); |
1301 | if (m->windspeed) |
1293 | if (m->windspeed) |
1302 | fprintf (fp, "windspeed %d\n", m->windspeed); |
1294 | fprintf (freezer, "windspeed %d\n", m->windspeed); |
1303 | if (m->winddir) |
1295 | if (m->winddir) |
1304 | fprintf (fp, "winddir %d\n", m->winddir); |
1296 | fprintf (freezer, "winddir %d\n", m->winddir); |
1305 | if (m->sky) |
1297 | if (m->sky) |
1306 | fprintf (fp, "sky %d\n", m->sky); |
1298 | fprintf (freezer, "sky %d\n", m->sky); |
1307 | if (m->nosmooth) |
1299 | if (m->nosmooth) |
1308 | fprintf (fp, "nosmooth %d\n", m->nosmooth); |
1300 | fprintf (freezer, "nosmooth %d\n", m->nosmooth); |
1309 | |
1301 | |
1310 | /* Save any tiling information, except on overlays */ |
1302 | /* Save any tiling information, except on overlays */ |
1311 | if (flag != 2) |
1303 | if (flag != 2) |
1312 | for (i = 0; i < 4; i++) |
1304 | for (i = 0; i < 4; i++) |
1313 | if (m->tile_path[i]) |
1305 | if (m->tile_path[i]) |
1314 | fprintf (fp, "tile_path_%d %s\n", i + 1, m->tile_path[i]); |
1306 | fprintf (freezer, "tile_path_%d %s\n", i + 1, m->tile_path[i]); |
1315 | |
1307 | |
1316 | fp.put (m); |
1308 | freezer.put (m); |
1317 | fprintf (fp, "end\n"); |
1309 | fprintf (freezer, "end\n"); |
1318 | |
1310 | |
1319 | /* In the game save unique items in the different file, but |
1311 | /* In the game save unique items in the different file, but |
1320 | * in the editor save them to the normal map file. |
1312 | * in the editor save them to the normal map file. |
1321 | * If unique map, save files in the proper destination (set by |
1313 | * If unique map, save files in the proper destination (set by |
1322 | * player) |
1314 | * player) |
1323 | */ |
1315 | */ |
1324 | if ((flag == 0 || flag == 2) && !m->unique && !m->templatemap) |
1316 | if ((flag == 0 || flag == 2) && !m->unique && !m->templatemap) |
1325 | { |
1317 | { |
|
|
1318 | object_freezer unique; |
|
|
1319 | |
|
|
1320 | if (flag == 2) |
|
|
1321 | save_objects (m, freezer, unique, 2); |
|
|
1322 | else |
|
|
1323 | save_objects (m, freezer, unique, 0); |
|
|
1324 | |
1326 | sprintf (buf, "%s.v00", create_items_path (m->path)); |
1325 | sprintf (buf, "%s.v00", create_items_path (m->path)); |
1327 | |
1326 | |
1328 | object_freezer fp2 (buf); |
1327 | unique.save (buf); |
1329 | |
|
|
1330 | if (flag == 2) |
|
|
1331 | save_objects (m, fp, fp2, 2); |
|
|
1332 | else |
|
|
1333 | save_objects (m, fp, fp2, 0); |
|
|
1334 | } |
1328 | } |
1335 | else |
1329 | else |
1336 | { /* save same file when not playing, like in editor */ |
1330 | { /* save same file when not playing, like in editor */ |
1337 | save_objects (m, fp, fp, 0); |
1331 | save_objects (m, freezer, freezer, 0); |
1338 | } |
1332 | } |
|
|
1333 | |
|
|
1334 | freezer.save (filename); |
1339 | |
1335 | |
1340 | return 0; |
1336 | return 0; |
1341 | } |
1337 | } |
1342 | |
1338 | |
1343 | |
1339 | |
… | |
… | |
1388 | clean_object(op); |
1384 | clean_object(op); |
1389 | remove_ob(op); |
1385 | remove_ob(op); |
1390 | free_object(op); |
1386 | free_object(op); |
1391 | } |
1387 | } |
1392 | } |
1388 | } |
1393 | #ifdef MANY_CORES |
|
|
1394 | /* I see periodic cores on metalforge where a map has been swapped out, but apparantly |
|
|
1395 | * an item on that map was not saved - look for that condition and die as appropriate - |
|
|
1396 | * this leaves more of the map data intact for better debugging. |
|
|
1397 | */ |
|
|
1398 | for (op=objects; op!=NULL; op=op->next) { |
|
|
1399 | if (!QUERY_FLAG(op, FLAG_REMOVED) && op->map == m) { |
|
|
1400 | LOG(llevDebug,"free_all_objects: object %s still on map after it should have been freed\n", op->name); |
|
|
1401 | abort(); |
|
|
1402 | } |
|
|
1403 | } |
|
|
1404 | #endif |
|
|
1405 | } |
1389 | } |
1406 | |
1390 | |
1407 | /* |
1391 | /* |
1408 | * Frees everything allocated by the given mapstructure. |
1392 | * Frees everything allocated by the given mapstructure. |
1409 | * don't free tmpname - our caller is left to do that |
1393 | * don't free tmpname - our caller is left to do that |
… | |
… | |
1489 | m->path); |
1473 | m->path); |
1490 | } |
1474 | } |
1491 | else |
1475 | else |
1492 | last->next = m->next; |
1476 | last->next = m->next; |
1493 | |
1477 | |
1494 | free (m); |
1478 | delete m; |
1495 | } |
1479 | } |
1496 | |
1480 | |
1497 | |
1481 | |
1498 | |
1482 | |
1499 | /* |
1483 | /* |