00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <algorithm>
00029 #include <cstring>
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032
00033 #include "typen.h"
00034 #include "misc.h"
00035 #include "buildingtype.h"
00036 #include "vehicletype.h"
00037 #include "spfst.h"
00038 #include "loaders.h"
00039 #include "dlg_box.h"
00040 #include "dlg_box.h"
00041 #include "dialog.h"
00042 #include "sgstream.h"
00043 #include "attack.h"
00044 #include "errors.h"
00045 #include "strtmesg.h"
00046 #include "textfileparser.h"
00047 #include "itemrepository.h"
00048 #include "prehistoricevents.h"
00049 #include "gamemap.h"
00050 #include "gameeventsystem.h"
00051 #include "graphicset.h"
00052 #include "gameoptions.h"
00053 #include "lua/luarunner.h"
00054 #include "lua/luastate.h"
00055 #include "packagemanager.h"
00056 #include "i18n.h"
00057 #include "mapimageexport.h"
00058
00059 #ifdef sgmain
00060 # include "ai/ai.h"
00061 #endif
00062
00063
00064
00065 const int actsavegameversion = 0xff63;
00066 const int minsavegameversion = 0xff31;
00067 const int actmapversion = 0xfe51;
00068 const int minmapversion = 0xfe24;
00069 const int actnetworkversion = 0x0032;
00070 const int minnetworkversion = 0x0004;
00071 const int actreplayversion = 0x0003;
00072 const int minreplayversion = 0x0001;
00073
00074
00075 const int fileterminator = 0xa01a;
00076
00077
00078 const char* savegameextension = "*.sav";
00079 const char* mapextension = "*.map";
00080 const char* tournamentextension = ".ascpbm";
00081
00082 bool suppressMapTriggerExecution = true;
00083
00084 void seteventtriggers( GameMap* actmap )
00085 {
00086 if ( !suppressMapTriggerExecution )
00087 for ( GameMap::Events::iterator i = actmap->events.begin(); i != actmap->events.end(); ++i )
00088 (*i)->arm();
00089
00090 for ( int i = 0; i < 8; i++ )
00091 actmap->player[i].queuedEvents = 1;
00092 }
00093
00094
00095
00096 #define csm_typid32 1
00097 #define csm_direction 2
00098 #define csm_vehicle 4
00099 #define csm_building 8
00100 #define csm_height 32
00101 #define csm_cnt2 64
00102 #define csm_b3 128
00103
00104 #define csm_material 1
00105 #define csm_fuel 2
00106 #define csm_visible 4
00107 #define csm_weather 16
00108 #define csm_object 64
00109 #define csm_b4 128
00110
00111 #define csm_resources 1
00112 #define csm_connection 2 // b4
00113 #define csm_newobject 4 // b4
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 void tspfldloaders::readdissections ( void )
00127 {
00128 for (int i = 0; i < 8; i ++ ) {
00129 if ( spfld->player[ i ].__dissectionsToLoad ) {
00130 int k;
00131 do {
00132 Player::Dissection du;
00133 stream->readInt();
00134 stream->readInt();
00135
00136 du.orgpoints = stream->readInt();
00137 du.points = stream->readInt();
00138 du.num = stream->readInt();
00139
00140 k = stream->readInt();
00141
00142 int j = stream->readInt();
00143 du.fzt = vehicleTypeRepository.getObject_byID ( j );
00144 if ( !du.fzt )
00145 throw InvalidID ( "vehicle", j );
00146
00147 j = stream->readInt();
00148 du.tech = technologyRepository.getObject_byID ( j );
00149 if ( !du.tech )
00150 throw InvalidID ( "technology", j );
00151
00152 spfld->player[ i ].dissections.push_back ( du );
00153 } while ( k );
00154 }
00155 }
00156 }
00157
00158 void tspfldloaders::writedissections ( void )
00159 {
00160 for (int i = 0; i < 8; i ++ ) {
00161 Player::DissectionContainer::iterator di = spfld->player[i].dissections.begin();
00162 while ( di != spfld->player[i].dissections.end() ) {
00163 stream->writeInt ( 1 );
00164 stream->writeInt ( 1 );
00165 stream->writeInt ( di->orgpoints );
00166 stream->writeInt ( di->points );
00167 stream->writeInt ( di->num );
00168
00169 di++;
00170 if ( di != spfld->player[i].dissections.end() )
00171 stream->writeInt ( 1 );
00172 else
00173 stream->writeInt ( 0 );
00174
00175 stream->writeInt ( di->fzt->id );
00176 stream->writeInt ( di->tech->id );
00177 }
00178 }
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 const int messageVersion = 0xabcdf1;
00188 const int messageMinVersion = 0xabcdef;
00189
00190 void tspfldloaders:: writemessages ( void )
00191 {
00192 stream->writeInt ( messageVersion );
00193
00194 int id = 0;
00195 for ( MessageContainer::iterator mi = spfld->messages.begin(); mi != spfld->messages.end(); ) {
00196 id++;
00197 (*mi)->id = id;
00198
00199 stream->writeInt ( (*mi)->from );
00200 stream->writeInt ( (*mi)->to );
00201 stream->writeInt ( (*mi)->cc );
00202 stream->writeInt ( (unsigned int) (*mi)->time );
00203 stream->writeInt ( 1 );
00204 stream->writeInt ( (*mi)->id );
00205 stream->writeInt ( (*mi)->gametime.turn() );
00206 stream->writeInt ( (*mi)->gametime.move() );
00207 stream->writeInt( (*mi)->reminder );
00208
00209
00210 ASCString& t = (*mi)->text;
00211
00212 mi++;
00213 stream->writeInt ( mi != spfld->messages.end() ? 1 : 0 );
00214
00215 stream->writeString ( t );
00216 }
00217
00218 for ( int i = 0; i < 8; i++ )
00219 writemessagelist ( spfld->player[ i ].oldmessage );
00220
00221 for ( int i = 0; i < 8; i++ )
00222 writemessagelist ( spfld->player[ i ].unreadmessage );
00223
00224 for ( int i = 0; i < 8; i++ )
00225 writemessagelist ( spfld->player[ i ].sentmessage );
00226
00227 writemessagelist ( spfld->unsentmessage );
00228
00229 stream->writeInt ( messageVersion );
00230
00231 stream->writeString ( spfld->gameJournal );
00232 stream->writeString ( spfld->newJournal );
00233 }
00234
00235
00236 void tspfldloaders:: writemessagelist( MessagePntrContainer& lst )
00237 {
00238 for ( MessagePntrContainer::iterator i = lst.begin(); i != lst.end(); i++ )
00239 stream->writeInt ( (*i)->id );
00240 stream->writeInt ( 0 );
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 void tspfldloaders:: readmessagelist( MessagePntrContainer& lst )
00254 {
00255 int i = stream->readInt();
00256
00257 while ( i ) {
00258
00259 MessageContainer::iterator mi = spfld->messages.end();
00260 for ( MessageContainer::iterator mi2 = spfld->messages.begin(); mi2 != spfld->messages.end(); mi2++ )
00261 if ( (*mi2)->id == i )
00262 mi = mi2;
00263
00264 if ( mi == spfld->messages.end())
00265 warningMessage( "message list corrupted !\nplease report this bug!\nthe game will continue, but some messages will probably be missing\nand other instabilities may occur.");
00266 lst.push_back ( *mi );
00267 i = stream->readInt();
00268 }
00269 }
00270
00271
00272 void tspfldloaders:: readmessages ( void )
00273 {
00274 int magic = stream->readInt();
00275 assertOrThrow( magic >= messageMinVersion && magic <= messageVersion );
00276
00277 while ( spfld->__loadmessages ) {
00278 Message* msg = new Message ( spfld );
00279
00280 msg->from = stream->readInt();
00281 msg->to = stream->readInt();
00282 if ( magic >= 0xabcdf0 )
00283 msg->cc = stream->readInt();
00284 else
00285 msg->cc = 0;
00286
00287 msg->time = stream->readInt();
00288 bool msgtext = stream->readInt();
00289 msg->id = stream->readInt();
00290 int t = stream->readInt();
00291 int m = stream->readInt();
00292 msg->gametime.set ( t, m );
00293
00294 if ( magic >= 0xabcdf1 )
00295 msg->reminder = stream->readInt();
00296 else
00297 msg->reminder = false;
00298
00299 spfld->__loadmessages = stream->readInt();
00300
00301 if ( msgtext )
00302 msg->text = stream->readString( true );
00303
00304 }
00305
00306 for ( int i = 0; i < 8; i++ )
00307 if ( spfld->player[ i ].__loadoldmessage )
00308 readmessagelist ( spfld->player[ i ].oldmessage );
00309
00310 for ( int i = 0; i < 8; i++ )
00311 if ( spfld->player[ i ].__loadunreadmessage )
00312 readmessagelist ( spfld->player[ i ].unreadmessage );
00313
00314 for ( int i = 0; i < 8; i++ )
00315 if ( spfld->player[ i ].__loadsentmessage )
00316 readmessagelist ( spfld->player[ i ].sentmessage );
00317
00318 if ( spfld->__loadunsentmessage )
00319 readmessagelist ( spfld->unsentmessage );
00320
00321 stream->readInt();
00322
00323 if ( spfld->___loadJournal )
00324 spfld->gameJournal = stream->readString();
00325
00326 if ( spfld->___loadNewJournal )
00327 spfld->newJournal = stream->readString();
00328 }
00329
00330
00331
00332
00333
00334
00335 void tspfldloaders::readoldevents ( void )
00336 {
00337 if ( spfld->loadOldEvents ) {
00338 int num = stream->readInt();
00339 while ( num ) {
00340 for ( int i = 0; i < num; i++ )
00341 stream->readInt();
00342 for ( int i = 0; i < num; i++ )
00343 stream->readInt();
00344
00345 num = stream->readInt();
00346 }
00347 }
00348 }
00349
00350 void checkForUniqueUnitIDs( GameMap* gamemap )
00351 {
00352 map<int,int> units;
00353 for ( int p = 0; p < gamemap->getPlayerCount(); ++p )
00354 for ( Player::VehicleList::iterator i = gamemap->getPlayer(p).vehicleList.begin(); i != gamemap->getPlayer(p).vehicleList.end(); ++i )
00355 if ( units[(*i)->networkid]++ > 0 ) {
00356 warningMessage("unit with duplicate network ids: " + ASCString::toString( (*i)->networkid ) + "\nThis will lead to replay errors during the next turn." );
00357 (*i)->networkid = gamemap->idManager.getNewNetworkID();;
00358 }
00359 }
00360
00361
00362
00363
00364
00365 void tspfldloaders::writemap ( void )
00366 {
00367 checkForUniqueUnitIDs( spfld );
00368 if ( !spfld )
00369 displaymessage ( "tspfldloaders::writemap ; no map to write ! ",2);
00370
00371 spfld->write ( *stream );
00372 }
00373
00374
00375 void tmaploaders::initmap ( void )
00376 {
00377 spfld->game_parameter = NULL;
00378 }
00379
00380
00381 void tgameloaders::initmap ( void )
00382 {
00383 spfld->game_parameter = NULL;
00384 }
00385
00386
00387 void tspfldloaders::readmap ( void )
00388 {
00389 spfld = new GameMap;
00390
00391 spfld->read ( *stream );
00392 }
00393
00394
00395
00396 void tgameloaders :: writeAI ( )
00397 {
00398 #ifdef sgmain
00399 int a = 0;
00400 for ( int i = 0; i< 8; i++ )
00401 if ( spfld->player[i].ai )
00402 a += 1 << i;
00403
00404 stream->writeInt ( a );
00405
00406 for ( int i = 0; i < 8; i++ )
00407 if ( spfld->player[i].ai )
00408 spfld->player[i].ai->write( *stream );
00409 #else
00410 stream->writeInt(0);
00411 #endif
00412 }
00413
00414 void tgameloaders :: readAI ( )
00415 {
00416 #ifdef sgmain
00417 int a = stream->readInt();
00418 for ( int i = 0; i< 8; i++ )
00419 if ( a & ( 1 << i ) ) {
00420 AI* ai = new AI ( spfld, i );
00421 ai->read ( *stream );
00422 spfld->player[i].ai = ai;
00423 } else {
00424 spfld->player[i].ai = NULL;
00425 }
00426 #else
00427 for ( int i = 0; i< 9; i++ )
00428 spfld->player[i].ai = NULL;
00429 #endif
00430 }
00431
00432
00433
00434
00435
00436
00437 extern void readLegacyNetworkData ( tnstream& stream );
00438
00439
00440 void tspfldloaders::readLegacyNetwork ( void )
00441 {
00442 if ( spfld->___loadLegacyNetwork )
00443 readLegacyNetworkData( *stream );
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453 const int objectstreamversion = 4;
00454
00455 void tspfldloaders::writefields ( void )
00456 {
00457 int l = 0;
00458 int cnt1 = spfld->xsize * spfld->ysize;
00459 int cnt2;
00460
00461 do {
00462 cnt2 = 0;
00463 MapField* fld = &spfld->field[l];
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 char b1 = 0;
00482 char b3 = 0;
00483 char b4 = 0;
00484
00485 if (fld->typ->terraintype->id > 255)
00486 b1 |= csm_typid32;
00487 if (fld->vehicle != NULL)
00488 b1 |= csm_vehicle;
00489 if ( (fld->bdt & getTerrainBitType( cbbuildingentry )).any() )
00490 b1 |= csm_building;
00491
00492
00493 if (cnt2 > 0)
00494 b1 |= csm_cnt2;
00495
00496 if (fld->material > 0)
00497 b3 |= csm_material;
00498 if (fld->fuel > 0)
00499 b3 |= csm_fuel;
00500
00501 if (fld->typ != fld->typ->terraintype->weather[0])
00502 b3 |= csm_weather;
00503 if (fld->visible)
00504 b3 |= csm_visible;
00505 if ( !fld->objects.empty() || !fld->mines.empty() )
00506 b4 |= csm_newobject;
00507
00508 if ( fld->resourceview )
00509 b4 |= csm_resources;
00510
00511 if ( fld->connection )
00512 b4 |= csm_connection;
00513
00514 if ( b4 )
00515 b3 |= csm_b4;
00516
00517 if ( b3 )
00518 b1 |= csm_b3;
00519
00520 stream->writeChar( b1 );
00521
00522 if (b1 & csm_b3 )
00523 stream->writeChar ( b3 );
00524
00525 if (b3 & csm_b4 )
00526 stream->writeChar ( b4 );
00527
00528 if (b1 & csm_cnt2 )
00529 stream->writeInt ( cnt2 );
00530
00531 if (b3 & csm_weather ) {
00532 int k = 1;
00533 while ( fld->typ != fld->typ->terraintype->weather[k] && k < cwettertypennum ) {
00534 k++;
00535 }
00536
00537 if ( k == cwettertypennum ) {
00538 k = 0;
00539 displaymessage ( "invalid terrain ( weather not found ) at position %d \n",1,l );
00540 }
00541 stream->writeInt ( k );
00542 }
00543
00544 if (b1 & csm_typid32 )
00545 stream->writeInt ( fld->typ->terraintype->id );
00546 else
00547 stream->writeChar ( fld->typ->terraintype->id );
00548
00549 if (b1 & csm_vehicle )
00550 fld->vehicle->write ( *stream );
00551
00552
00553 if (b1 & csm_building )
00554 fld->building->write ( *stream );
00555
00556 if (b3 & csm_material )
00557 stream->writeChar ( fld->material );
00558
00559 if (b3 & csm_fuel )
00560 stream->writeChar ( fld->fuel );
00561
00562 if (b3 & csm_visible )
00563 stream->writeWord ( fld->visible );
00564
00565 if ( b4 & csm_newobject ) {
00566 stream->writeInt ( objectstreamversion );
00567
00568 stream->writeInt ( fld->mines.size() );
00569 for ( MapField::MineContainer::iterator m = fld->mines.begin(); m != fld->mines.end(); m++ ) {
00570 stream->writeInt ( m->type );
00571 stream->writeInt ( m->strength );
00572 stream->writeInt ( m->lifetimer );
00573 stream->writeInt ( m->player );
00574 stream->writeInt ( m->identifier );
00575 }
00576
00577 stream->writeInt ( fld->objects.size() );
00578
00579 for ( MapField::ObjectContainer::iterator o = fld->objects.begin(); o != fld->objects.end(); o++ ) {
00580 stream->writeInt ( 1 );
00581 stream->writeInt ( o->damage );
00582 stream->writeInt ( o->dir );
00583 stream->writeInt ( o->lifetimer );
00584 for ( int i = 0; i < 4; i++ )
00585 stream->writeInt ( 0 );
00586 stream->writeInt ( o->typ->id );
00587 stream->writeInt( o->remainingGrowthTime );
00588 }
00589 }
00590
00591 if (b4 & csm_resources ) {
00592 stream->writeChar ( fld->resourceview->visible );
00593 for ( int i = 0; i < 8; i++ )
00594 stream->writeChar ( fld->resourceview->fuelvisible[i] );
00595 for ( int i = 0; i < 8; i++ )
00596 stream->writeChar ( fld->resourceview->materialvisible[i] );
00597 }
00598
00599 if ( b4 & csm_connection )
00600 stream->writeInt ( fld->connection );
00601
00602 l += 1 + cnt2;
00603 } while (l < cnt1);
00604 }
00605
00606
00607
00608
00609
00610 void tspfldloaders::readfields ( void )
00611 {
00612 int cnt2 = 0;
00613 int cnt1 = spfld->xsize * spfld->ysize;
00614
00615 assertOrThrow( cnt1 > 0 );
00616 assertOrThrow( spfld->xsize > 0 );
00617 assertOrThrow( spfld->ysize > 0 );
00618
00619 spfld->allocateFields ( spfld->xsize , spfld->ysize );
00620
00621 if (spfld->field == NULL)
00622 displaymessage ( "Could not allocate memory for map ",2);
00623
00624 int l = 0;
00625 MapField* lfld = NULL;
00626
00627 do {
00628 MapField* fld2;
00629
00630 if (cnt2 == 0) {
00631
00632 fld2 = & spfld->field[l];
00633
00634 fld2->bdt.setInt ( 0 , 0 );
00635
00636 char b1, b3, b4;
00637 b1 = stream->readChar();
00638
00639 if (b1 & csm_b3 )
00640 b3 = stream->readChar();
00641 else
00642 b3 = 0;
00643
00644 if (b3 & csm_b4 )
00645 b4 = stream->readChar();
00646 else
00647 b4 = 0;
00648
00649 if (b1 & csm_cnt2 )
00650 cnt2 = stream->readInt();
00651 else
00652 cnt2 = 0;
00653
00654 int weather;
00655 if (b3 & csm_weather )
00656 weather = stream->readInt();
00657 else
00658 weather = 0;
00659
00660 assertOrThrow( weather >= 0 && weather < cwettertypennum );
00661
00662 int k;
00663
00664 if (b1 & csm_typid32 )
00665 k = stream->readInt();
00666 else
00667 k = stream->readChar();
00668
00669 pterraintype trn = terrainTypeRepository.getObject_byID ( k );
00670 if ( !trn )
00671 throw InvalidID ( "terrain", k );
00672
00673 fld2->typ = trn->weather[weather];
00674 if ( !fld2->typ ) {
00675 fld2->typ = trn->weather[0];
00676 if ( !fld2->typ )
00677 throw InvalidID ( "terrain", k );
00678 }
00679
00680 if (b1 & csm_direction )
00681 stream->readChar();
00682
00683
00684 if (b1 & csm_vehicle ) {
00685 fld2->vehicle = Vehicle::newFromStream ( spfld, *stream );
00686 fld2->vehicle->setnewposition ( l%spfld->xsize, l/spfld->xsize );
00687 }
00688
00689 if (b1 & csm_building ) {
00690 fld2->building = Building::newFromStream ( spfld, *stream );
00691 fld2->bdt |= getTerrainBitType(cbbuildingentry);
00692 }
00693
00694 if (b3 & csm_material)
00695 fld2->material = stream->readChar();
00696 else
00697 fld2->material = 0;
00698
00699 if (b3 & csm_fuel)
00700 fld2->fuel = stream->readChar();
00701 else
00702 fld2->fuel = 0;
00703
00704 if (b3 & csm_visible)
00705 fld2->visible = stream->readWord();
00706 else
00707 fld2->visible = 0;
00708
00709 bool tempobjects[16];
00710 int tempobjectNum = 0;
00711
00712 if (b3 & csm_object ) {
00713
00714 char minetype = stream->readChar();
00715 char minestrength = stream->readChar();
00716 if ( minetype >> 4 ) {
00717 Mine m( MineTypes((minetype >> 1) & 7), minestrength, minetype >> 4, spfld );
00718 fld2->mines.push_back ( m );
00719 }
00720
00721 tempobjectNum = stream->readInt();
00722
00723 for ( int i = 0; i < 16; i++ )
00724 tempobjects[i] = stream->readInt();
00725 }
00726
00727 int objectversion = 1;
00728 if ( b4 & csm_newobject ) {
00729 objectversion = stream->readInt();
00730
00731 if ( objectversion < 1 || objectversion > objectstreamversion )
00732 throw tinvalidversion ( "object", objectstreamversion, objectversion );
00733
00734 int minenum = stream->readInt();
00735
00736 for ( int i = 0; i < minenum; i++ ) {
00737 MineTypes type = MineTypes(stream->readInt());
00738 int strength = stream->readInt();
00739 int minetime = stream->readInt();
00740 int player = stream->readInt();
00741 if ( player < 0 || player > 7 )
00742 player = 0;
00743
00744 assertOrThrow( strength >= 0 );
00745 assertOrThrow( type > 0 && type <= 4 );
00746
00747 int id;
00748 if ( objectversion >= 4 )
00749 id = stream->readInt();
00750 else
00751 id = spfld->idManager.getNewNetworkID();
00752
00753 Mine m ( type, strength, player, spfld, id );
00754 if ( objectversion == 1 ) {
00755 int endtime = minetime;
00756 int lifetime = spfld->getgameparameter( GameParameter(cgp_antipersonnelmine_lifetime + m.type - 1));
00757 if ( lifetime > 0 && endtime > 0 )
00758 m.lifetimer = endtime - spfld->time.turn() + spfld->getgameparameter( GameParameter(cgp_antipersonnelmine_lifetime + m.type - 1));
00759 else if ( lifetime > 0 )
00760 m.lifetimer = lifetime;
00761 else
00762 m.lifetimer = -1;
00763 } else
00764 m.lifetimer = minetime;
00765 fld2->mines.push_back ( m );
00766 }
00767
00768 tempobjectNum = stream->readInt();
00769 }
00770
00771 if ( (b3 & csm_object) || (b4 & csm_newobject )) {
00772 for ( int n = 0; n < tempobjectNum; n++ ) {
00773 Object o;
00774 stream->readInt();
00775 o.damage = stream->readInt();
00776 assertOrThrow( o.damage >= 0 );
00777 o.dir = stream->readInt();
00778 if ( objectversion >= 2 )
00779 o.lifetimer = stream->readInt();
00780 else
00781 stream->readInt();
00782
00783 for ( int i = 0; i < 4; i++ )
00784 stream->readInt();
00785
00786 int id = stream->readInt();
00787 o.typ = objectTypeRepository.getObject_byID ( id );
00788
00789 if ( !o.typ )
00790 throw InvalidID ( "object", id );
00791
00792 if ( objectversion >= 3 )
00793 o.remainingGrowthTime = stream->readInt();
00794
00795 if ( objectversion == 1 )
00796 o.lifetimer = o.typ->lifetime;
00797
00798
00799 fld2->objects.push_back ( o );
00800 }
00801 fld2->sortobjects();
00802 }
00803
00804 if (b4 & csm_resources ) {
00805 fld2->resourceview = new MapField::Resourceview;
00806 fld2->resourceview->visible = stream->readChar();
00807 for ( int i = 0; i < 8; i++ )
00808 fld2->resourceview->fuelvisible[i] = stream->readChar();
00809 for ( int i = 0; i < 8; i++ )
00810 fld2->resourceview->materialvisible[i] = stream->readChar();
00811 }
00812
00813 if ( b4 & csm_connection )
00814 fld2->connection = stream->readInt();
00815
00816 if (b1 & csm_cnt2 )
00817 lfld = fld2;
00818
00819 } else {
00820 spfld->field[l].typ = lfld->typ;
00821 spfld->field[l].fuel = lfld->material;
00822 spfld->field[l].visible = lfld->visible;
00823 spfld->field[l].tempw = 0;
00824 spfld->field[l].connection = lfld->connection;
00825 for ( int i = 0; i < 8; i++ )
00826 spfld->field[l].view[i] = lfld->view[i];
00827 cnt2--;
00828 }
00829 l++ ;
00830 } while (l < cnt1);
00831
00832 spfld->overviewMapHolder.connect();
00833
00834 }
00835
00836
00837
00838
00839
00840
00841
00842 void tspfldloaders::chainitems ( GameMap* actmap )
00843 {
00844 int i = 0;
00845 for (int y = 0; y < actmap->ysize; y++)
00846 for (int x = 0; x < actmap->xsize; x++) {
00847 MapField* fld = &actmap->field[i];
00848 fld->setparams();
00849 i++;
00850 }
00851 }
00852
00853
00854
00855
00856
00857
00858
00859 SigC::Signal1<void,GameMap*> tspfldloaders::mapLoaded;
00860
00861
00862 tspfldloaders::tspfldloaders ( void )
00863 {
00864 spfld = NULL;
00865 }
00866
00867
00868 tspfldloaders::~tspfldloaders ( void )
00869 {
00870 delete spfld;
00871 spfld = NULL;
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 int tmaploaders::savemap( const ASCString& name, GameMap* gamemap )
00892 {
00893 #ifdef logging
00894 logtofile ( "loaders / tmaploaders::savemap / started " );
00895 #endif
00896
00897 tnfilestream filestream ( name, tnstream::writing );
00898
00899 stream = &filestream;
00900
00901 spfld = gamemap;
00902
00903
00904
00905
00906
00907 {
00908 stream->writepchar ( getFullVersionString() );
00909 stream->writeWord ( fileterminator );
00910 stream->writeInt ( actmapversion );
00911
00912 writemap ( );
00913 }
00914
00915 writefields ();
00916 #ifdef WEATHERGENERATOR
00917 spfld->weatherSystem->write(filestream);
00918 #endif
00919 stream->writeInt ( actmapversion );
00920
00921 spfld = NULL;
00922
00923 return 0;
00924 }
00925
00926
00927
00928 void weatherSystemRequired()
00929 {
00930 throw ASCmsgException( "This file can not be loaded, since it contains data of the discontinued weather generator");
00931 }
00932
00933
00934 GameMap* tmaploaders::_loadmap( const ASCString& name )
00935 {
00936 displayLogMessage ( 4, "loading map %s ... ", name.c_str() );
00937
00938 tnfilestream filestream ( name, tnstream::reading);
00939
00940 stream = &filestream;
00941
00942 char* description = NULL;
00943
00944 stream->readpchar ( &description );
00945 delete[] description;
00946
00947 int w = stream->readWord();
00948
00949 if ( w != fileterminator )
00950 throw tinvalidversion ( name, fileterminator, w );
00951
00952
00953 int version = stream->readInt();
00954
00955 if ( version > actmapversion || version < minmapversion )
00956 throw tinvalidversion ( name, actmapversion, version );
00957
00958
00959 displayLogMessage ( 8, "map, ");
00960 readmap ();
00961
00962 if ( version <= 0xfe27 ) {
00963 displayLogMessage ( 8, "eventsToCome, ");
00964 readOldEventLists ( stream, false, spfld );
00965 }
00966
00967 displayLogMessage ( 8, "fields, ");
00968 readfields ();
00969
00970
00971 if(version == 0xfe50)
00972 weatherSystemRequired();
00973
00974 version = stream->readInt();
00975 if (version > actmapversion || version < minmapversion )
00976 throw tinvalidversion ( name, actmapversion, version );
00977
00978
00979 displayLogMessage ( 8, "chainItems, ");
00980 chainitems ( spfld );
00981
00982 for ( int sp = spfld->getPlayerCount()-1; sp >= 0; sp--)
00983 if ( spfld->player[sp].exist() )
00984 spfld->actplayer = sp;
00985
00986 displayLogMessage ( 8, "setEventTriggers, ");
00987 seteventtriggers( spfld );
00988
00989 displayLogMessage ( 8, "calculateallobjects ");
00990 calculateallobjects( spfld );
00991
00992
00993 displayLogMessage ( 8, "init for playing, ");
00994
00995 spfld->time.set ( 1, 0 );
00996 spfld->levelfinished = false;
00997 spfld->preferredFileNames.mapname[0] = name ;
00998 checkForUniqueUnitIDs( spfld );
00999 spfld->startGame();
01000
01001 displayLogMessage ( 4, "done\n");
01002
01003 GameMap* m = spfld;
01004 spfld = NULL;
01005
01006 mapLoaded( m );
01007
01008 return m;
01009 }
01010
01011
01012 GameMap* eventLocalizationMap = NULL;
01013
01014
01015
01016 void loadLocalizedMessageFile( GameMap* map, const ASCString& filename )
01017 {
01018 eventLocalizationMap = map;
01019
01020 LuaState state;
01021 LuaRunner runner( state );
01022 runner.runFile( filename );
01023 if ( !runner.getErrors().empty() )
01024 errorMessage( runner.getErrors() );
01025
01026 eventLocalizationMap = NULL;
01027 }
01028
01029 void loadLocalizedMessages( GameMap* map, const ASCString& name )
01030 {
01031 Locale locale;
01032 ASCString filename = locale.getLocalizedFile( name );
01033 if( !filename.empty() && exist( filename ) )
01034 loadLocalizedMessageFile( map, filename );
01035
01036 }
01037
01038 GameMap* tmaploaders::loadmap ( const ASCString& name )
01039 {
01040 tmaploaders gl;
01041 GameMap* map = gl._loadmap ( name );
01042 #ifdef sgmain
01043 loadLocalizedMessages( map, name );
01044 #endif
01045 return map;
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 void tsavegameloaders::savegame( tnstream* strm, GameMap* gamemap, bool writeReplays )
01060 {
01061 PackageManager::storeData( gamemap );
01062
01063 stream = strm;
01064 spfld = gamemap;
01065
01066 stream->writepchar( getFullVersionString() );
01067 stream->writeWord( fileterminator );
01068
01069 stream->writeInt( actsavegameversion );
01070
01071
01072 writemaptostream( spfld , 100, 100, *stream);
01073
01074 stream->writeString( gamemap->maptitle );
01075 stream->writeString( gamemap->getCurrentPlayer().getName() );
01076 stream->writeInt( gamemap->time.turn() );
01077
01078 writemap ();
01079
01080 writemessages();
01081
01082 writefields ( );
01083
01084 writedissections();
01085
01086 if ( writeReplays && spfld->replayinfo ) {
01087 stream->writeInt( 1 );
01088 spfld->replayinfo->write(*stream);
01089 } else
01090 stream->writeInt( 0 );
01091
01092 writeAI();
01093
01094
01095
01096 stream->writeInt( actsavegameversion );
01097
01098 spfld = NULL;
01099 }
01100
01101
01102 void tsavegameloaders::savegame( GameMap* gamemap, const ASCString& name)
01103 {
01104 tnfilestream filestream ( name, tnstream::writing );
01105 savegame ( &filestream, gamemap, true );
01106 }
01107
01108 GameFileInformation tsavegameloaders::loadMapimageFromFile( const ASCString& filename )
01109 {
01110 GameFileInformation gfi;
01111 try {
01112 tnfilestream stream( filename, tnstream::reading );
01113
01114 stream.readString();
01115
01116 int w = stream.readWord();
01117
01118 if ( w != fileterminator )
01119 throw tinvalidversion ( stream.getDeviceName(), fileterminator, w );
01120
01121 int version = stream.readInt();
01122
01123 if ( version >= 0xff63 ) {
01124 gfi.image = loadmapfromstream( stream );
01125 gfi.maptitle = stream.readString();
01126 gfi.playername = stream.readString();
01127 gfi.turn = stream.readInt();
01128 }
01129 } catch(...) {
01130 }
01131 return gfi;
01132 }
01133
01134 GameMap* tsavegameloaders::loadGameFromFile( const ASCString& filename )
01135 {
01136 tnfilestream filestream( filename, tnstream::reading );
01137 tsavegameloaders gl;
01138 return gl.loadgame( &filestream );
01139 }
01140
01141 GameMap* tsavegameloaders::loadgame( tnstream* strm )
01142 {
01143 stream = strm;
01144
01145 stream->readString();
01146
01147 int w = stream->readWord();
01148
01149 if ( w != fileterminator )
01150 throw tinvalidversion ( strm->getDeviceName(), fileterminator, w );
01151
01152 int version = stream->readInt();
01153
01154 if (version > actsavegameversion || version < minsavegameversion )
01155 throw tinvalidversion ( strm->getDeviceName(), actsavegameversion, version );
01156
01157 if ( version >= 0xff62 ) {
01158
01159 loadmapfromstream( *stream );
01160 }
01161
01162 if ( version >= 0xff63 ) {
01163
01164 stream->readString();
01165 stream->readString();
01166 stream->readInt();
01167 }
01168
01169 readmap ();
01170
01171 readLegacyNetwork ();
01172
01173 if ( version <= 0xff39 )
01174 for ( int i = 0; i < 8; i++ )
01175 spfld->player[i].research.read_techs ( *stream );
01176
01177 readmessages();
01178
01179 if ( version <= 0xff37 ) {
01180 readOldEventLists ( stream, true, spfld );
01181 readoldevents ();
01182 }
01183
01184 readfields ( );
01185
01186 if(version == 0xff60)
01187 weatherSystemRequired();
01188
01189 readdissections();
01190
01191 bool loadReplay = true;
01192 if ( version >= 0xff35 )
01193 if ( !stream->readInt() )
01194 loadReplay = false;
01195
01196 if ( loadReplay ) {
01197 spfld->replayinfo = new GameMap::ReplayInfo;
01198 spfld->replayinfo->read ( *stream );
01199 } else
01200 spfld->replayinfo = NULL;
01201
01202
01203 if ( version >= 0xff34 )
01204 readAI ();
01205
01206 version = stream->readInt();
01207 if (version > actsavegameversion || version < minsavegameversion )
01208 throw tinvalidversion ( strm->getDeviceName(), actsavegameversion, version );
01209
01210 chainitems ( spfld );
01211
01212 seteventtriggers( spfld );
01213
01214 calculateallobjects( spfld );
01215 checkForUniqueUnitIDs( spfld );
01216
01217 mapLoaded( spfld );
01218
01219
01220 GameMap* s = spfld;
01221 spfld = NULL;
01222 return s;
01223 }
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234 int tnetworkloaders::savenwgame( tnstream* strm, const GameMap* gamemap )
01235 {
01236
01237 PackageManager::storeData( gamemap );
01238
01239 spfld = const_cast<GameMap*>(gamemap);
01240
01241 stream = strm;
01242
01243 stream->writepchar ( getFullVersionString() );
01244 stream->writeWord ( fileterminator );
01245
01246 stream->writeInt ( actnetworkversion );
01247
01248 writemap ();
01249
01250 writemessages();
01251
01252 stream->writeInt ( actnetworkversion );
01253
01254 writefields ( );
01255
01256 writedissections();
01257
01258 if ( spfld->replayinfo )
01259 spfld->replayinfo->write ( *stream );
01260
01261
01262 writeAI();
01263
01264 stream->writeInt ( actnetworkversion );
01265
01266 spfld = NULL;
01267
01268 return 0;
01269 }
01270
01271
01272
01273
01274
01275 GameMap* tnetworkloaders::loadnwgame( tnstream* strm )
01276 {
01277 const char* name = "network game";
01278
01279 stream = strm;
01280
01281
01282 char* description = NULL;
01283 stream->readpchar ( &description );
01284 delete[] description;
01285
01286 int w = stream->readWord();
01287
01288 if ( w != fileterminator )
01289 throw tinvalidversion ( name, fileterminator, (int) w );
01290
01291
01292 int version = stream->readInt();
01293
01294 if (version > actnetworkversion || version < minnetworkversion )
01295 throw tinvalidversion ( name, actnetworkversion, version );
01296
01297 readmap ();
01298
01299 if ( version <= 0x11 )
01300 for ( int i = 0; i < 8; i++ )
01301 spfld->player[i].research.read_techs ( *stream );
01302
01303
01304
01305 if(version == 0x0030)
01306 weatherSystemRequired();
01307
01308
01309
01310
01311 readmessages();
01312 readLegacyNetwork ();
01313
01314 version = stream->readInt();
01315
01316 if (version > actnetworkversion || version < minnetworkversion )
01317 throw tinvalidversion ( name, actnetworkversion, version );
01318
01319
01320
01321 if ( version < 10 ) {
01322 readOldEventLists ( stream, true, spfld );
01323 readoldevents ();
01324 }
01325
01326 readfields ( );
01327
01328 readdissections();
01329
01330 if ( spfld->__loadreplayinfo ) {
01331 spfld->replayinfo = new GameMap::ReplayInfo;
01332 spfld->replayinfo->read ( *stream );
01333 }
01334
01335 if ( version > 8 )
01336 readAI();
01337
01338 #ifdef sgmain
01339 version = stream->readInt();
01340 if (version > actnetworkversion || version < minnetworkversion )
01341 throw tinvalidversion ( name, actnetworkversion, version );
01342 #endif
01343
01344 chainitems ( spfld );
01345
01346 seteventtriggers( spfld );
01347
01348 calculateallobjects( spfld );
01349
01350 checkForUniqueUnitIDs( spfld );
01351
01352 spfld->levelfinished = false;
01353
01354
01355 for ( int i = 0; i < 8; ++i)
01356 for ( Player::BuildingList::iterator b = spfld->player[i].buildingList.begin(); b != spfld->player[i].buildingList.end(); ++b )
01357 for ( int a = 0; a < waffenanzahl; ++a )
01358 if ( (*b)->ammo[a] > 32000 ) {
01359 ASCString s;
01360 s.format( "Player %s had %d ammo of type %s in the building at %d/%d", spfld->player[i].getName().c_str(), (*b)->ammo[a], cwaffentypen[a], (*b)->getEntry().x, (*b)->getEntry().y );
01361 new Message( s, spfld, 1 );
01362 (*b)->ammo[a] = 0;
01363 }
01364
01365
01366
01367 GameMap* spfldcopy = spfld;
01368 spfld = NULL;
01369
01370 mapLoaded( spfldcopy );
01371
01372
01373 return spfldcopy;
01374
01375 }
01376
01377
01378
01379
01380
01381
01382 ASCString getLuaQuote( bool open, int n )
01383 {
01384 ASCString s = open? "[[" : "]]";
01385 for ( int i =0; i < n; ++i )
01386 s.insert(1, "=" );
01387 return s;
01388 }
01389
01390 ASCString luaQuote( const ASCString& text )
01391 {
01392 int count = 0;
01393 while( text.find_first_of( getLuaQuote( true, count )) != ASCString::npos ||
01394 text.find_first_of( getLuaQuote( false, count )) != ASCString::npos )
01395 ++count;
01396
01397 return getLuaQuote( true, count) + text + getLuaQuote( false, count );
01398 }
01399
01400 void writeMessageFile( GameMap* gamemap, tnstream& stream )
01401 {
01402 stream.writeString( "map = asc.getLoadingMap() \n", false);
01403 for ( GameMap::Events::const_iterator i = gamemap->events.begin(); i != gamemap->events.end(); ++i ) {
01404 ASCString s = (*i)->action->getLocalizationString();
01405 if ( !s.empty() ) {
01406 stream.writeString ( "--- ===== Event " + ASCString::toString((*i)->id) + " ======= \n", false );
01407 stream.writeString ( "message = " + luaQuote( s ) + "\n", false );
01408 stream.writeString ( "asc.setLocalizedEventMessage( map, " + ASCString::toString((*i)->id) + ", message )\n\n", false);
01409 }
01410 }
01411
01412 for ( int p = 0; p <= gamemap->getPlayerCount(); ++p ) {
01413 Player& player = gamemap->getPlayer(p);
01414 for ( Player::BuildingList::const_iterator b = player.buildingList.begin(); b != player.buildingList.end(); ++b ) {
01415 if ( !(*b)->name.empty() ) {
01416 stream.writeString ( "--- ===== Building " + ASCString::toString((*b)->getIdentification()) + " ======= \n", false );
01417 ASCString f;
01418 f.format( "asc.setLocalizedContainerName( map, asc.MapCoordinate( %d, %d ), %s ) \n", (*b)->getPosition().x, (*b)->getPosition().y, + luaQuote( (*b)->name ).c_str() );
01419 stream.writeString ( f, false );
01420 }
01421 }
01422 }
01423 }
01424
01425
01426
01427 void savemap( const ASCString& name, GameMap* gamemap )
01428 {
01429
01430 #ifdef logging
01431 logtofile ( "loaders / savemap / started " );
01432 #endif
01433
01434 try {
01435 tmaploaders gl;
01436 gl.savemap ( name, gamemap );
01437
01438
01439 if ( CGameOptions::Instance()->saveEventMessagesExternal && gamemap->nativeMessageLanguage.length() ) {
01440 tn_file_buf_stream messages ( name + "." + gamemap->nativeMessageLanguage, tnstream::writing );
01441 writeMessageFile( gamemap, messages );
01442 }
01443
01444 }
01445
01446 catch ( tfileerror err ) {
01447 displaymessage( "file error writing map to filename %s ", 1, err.getFileName().c_str() );
01448 }
01449 catch ( ASCexception ) {
01450 displaymessage( "error writing map ", 1 );
01451 }
01452
01453 }
01454
01455 void savegame( const ASCString& name, GameMap* gamemap)
01456 {
01457 try {
01458 tsavegameloaders gl;
01459 gl.savegame ( gamemap, name);
01460 } catch ( tfileerror err) {
01461 displaymessage( "error writing map to filename %s ", 1, err.getFileName().c_str() );
01462 }
01463 catch ( ASCexception ) {
01464 displaymessage( "error writing map ", 1 );
01465 }
01466 }
01467
01468
01469 void savereplay( GameMap* gamemap, int num )
01470 {
01471 try {
01472 if ( !gamemap->replayinfo )
01473 fatalError ( "treplayloaders :: savereplay ; No replay activated !");
01474
01475 if ( gamemap->replayinfo->map[num] ) {
01476 delete gamemap->replayinfo->map[num];
01477 gamemap->replayinfo->map[num] = NULL;
01478 }
01479
01480 gamemap->replayinfo->map[num] = new MemoryStreamStorage;
01481 MemoryStream memstream ( gamemap->replayinfo->map[num], tnstream::writing );
01482
01483 memstream.writeInt( actreplayversion );
01484
01485 tsavegameloaders sgl;
01486 sgl.savegame ( &memstream, gamemap, false );
01487
01488 memstream.writeInt ( actreplayversion );
01489 } catch ( ASCexception ) {
01490 displaymessage( "error saving replay information", 1 );
01491 }
01492 }
01493
01494 GameMap* loadreplay( MemoryStreamStorage* streambuf )
01495 {
01496 GameMap* replaymap = NULL;
01497
01498 try {
01499 const char* name = "memorystream actmap->replayinfo";
01500 MemoryStream memstream ( streambuf, tnstream::reading );
01501
01502 int version = memstream.readInt();
01503 if (version > actreplayversion || version < minreplayversion )
01504 throw tinvalidversion ( name, actreplayversion, version );
01505
01506 tsavegameloaders sgl;
01507 replaymap = sgl.loadgame ( &memstream );
01508
01509 version = memstream.readInt();
01510 if (version > actreplayversion || version < minreplayversion ) {
01511 delete replaymap;
01512 throw tinvalidversion ( name, actreplayversion, version );
01513 }
01514
01515 } catch ( InvalidID err ) {
01516 displaymessage( err.getMessage().c_str(), 1 );
01517 replaymap = NULL;
01518 }
01519 catch ( tinvalidversion err ) {
01520 displaymessage( err.getMessage().c_str(), 1 );
01521 replaymap = NULL;
01522 }
01523 catch ( tfileerror err) {
01524 displaymessage( "error reading map filename %s ", 1, err.getFileName().c_str() );
01525 replaymap = NULL;
01526 }
01527 catch ( ASCexception ) {
01528 displaymessage( "error loading replay", 1 );
01529 replaymap = NULL;
01530 }
01531
01532 return replaymap;
01533 }
01534
01535
01536
01537
01538 GameMap* mapLoadingExceptionChecker( const ASCString& filename, MapLoadingFunction loader )
01539 {
01540 GameMap* m = NULL;
01541 try {
01542 m = loader( filename );
01543 } catch ( InvalidID err ) {
01544 displaymessage( err.getMessage().c_str(), 1 );
01545 return NULL;
01546 }
01547 catch ( tinvalidversion err ) {
01548 displaymessage( err.getMessage().c_str(), 1 );
01549 return NULL;
01550 }
01551 catch ( StreamCompressionError err ) {
01552 displaymessage( "The file %s is corrupted.\nPlease obtain a new copy of that file", 1, filename.c_str() );
01553 return NULL;
01554 } catch ( tfileerror err) {
01555 displaymessage( "error reading map filename %s ", 1, err.getFileName().c_str() );
01556 return NULL;
01557 }
01558 catch ( ASCmsgException msg ) {
01559 displaymessage( "error loading file\n" + msg.getMessage() , 1 );
01560 return NULL;
01561 }
01562 catch ( ASCexception ) {
01563 displaymessage( "error loading file", 1 );
01564 return NULL;
01565 }
01566
01567 return m;
01568 }
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578 bool validatemapfile ( const ASCString& filename )
01579 {
01580
01581 char* description = NULL;
01582
01583 try {
01584
01585 tnfilestream stream ( filename, tnstream::reading );
01586 stream.readpchar ( &description, 200 );
01587 if ( description ) {
01588 delete[] description ;
01589 description = NULL;
01590 }
01591
01592 int w = stream.readWord();
01593 if ( w != fileterminator )
01594 throw tinvalidversion ( filename, fileterminator, (int) w );
01595
01596 int version = stream.readInt();
01597
01598 if (version > actmapversion || version < minmapversion )
01599 throw tinvalidversion ( filename, actmapversion, version );
01600
01601 }
01602
01603 catch ( ... ) {
01604 return false;
01605 }
01606
01607 return true;
01608 }
01609
01610
01611
01612
01613
01614 bool validateemlfile ( const ASCString& filename )
01615 {
01616 char* description = NULL;
01617
01618 try {
01619
01620 tnfilestream stream ( filename, tnstream::reading );
01621 stream.readpchar ( &description, 200 );
01622 if ( description ) {
01623 delete[] description ;
01624 description = NULL;
01625 }
01626
01627 int w = stream.readWord();
01628 if ( w != fileterminator )
01629 throw tinvalidversion ( filename, fileterminator, (int) w );
01630
01631 int version = stream.readInt();
01632
01633 if (version > actnetworkversion || version < minnetworkversion )
01634 throw tinvalidversion ( filename, actnetworkversion, version );
01635
01636 }
01637
01638 catch ( ASCexception ) {
01639 return false;
01640 }
01641
01642
01643 return true;
01644 }
01645
01646
01647 bool validatesavfile ( const ASCString& filename )
01648 {
01649
01650 char* description = NULL;
01651
01652 try {
01653
01654 tnfilestream stream ( filename, tnstream::reading );
01655 stream.readpchar ( &description, 200 );
01656 if ( description ) {
01657 delete[] description ;
01658 description = NULL;
01659 }
01660
01661 int w = stream.readWord();
01662 if ( w != fileterminator )
01663 throw tinvalidversion ( filename, fileterminator, w );
01664
01665 int version = stream.readInt();
01666 if (version > actsavegameversion || version < minsavegameversion )
01667 throw tinvalidversion ( filename, actsavegameversion, version );
01668
01669 }
01670
01671 catch ( ASCexception ) {
01672 return false;
01673 }
01674
01675 return true;
01676 }
01677
01678
01679
01680
01681 MapConinuationInfo findNextCampaignMap( int id )
01682 {
01683 MapConinuationInfo mi;
01684
01685 tfindfile ff ( mapextension );
01686
01687 ASCString filename = ff.getnextname();
01688 while( !filename.empty() ) {
01689
01690 try {
01691 tnfilestream filestream ( filename, tnstream::reading );
01692 tmaploaders spfldloader;
01693 spfldloader.stream = &filestream;
01694
01695 CharBuf description;
01696
01697 spfldloader.stream->readpchar ( &description.buf );
01698
01699 int w = spfldloader.stream->readWord();
01700
01701 if ( w != fileterminator )
01702 throw tinvalidversion ( filename.c_str(), w, fileterminator );
01703
01704 int version = spfldloader.stream->readInt();
01705
01706 if (version > actmapversion || version < minmapversion )
01707 throw tinvalidversion ( filename.c_str(), version, actmapversion );
01708
01709 spfldloader.readmap ();
01710
01711 if ( spfldloader.spfld->campaign.avail && spfldloader.spfld->campaign.id == id ) {
01712 mi.title = spfldloader.spfld->maptitle;
01713 mi.codeword = spfldloader.spfld->codeWord;
01714 mi.filename = filename;
01715 return mi;
01716 }
01717 } catch ( ... ) {
01718 }
01719
01720 filename = ff.getnextname();
01721 }
01722
01723 return mi;
01724 }
01725
01726