/*! \file loadbi3.cpp \brief Importing maps from Battle Isle */ /* This file is part of Advanced Strategic Command; http://www.asc-hq.de Copyright (C) 1994-2005 Martin Bickel and Marc Schellenberger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "loadbi3.h" #include "newfont.h" #include "basegfx.h" #include "typen.h" #include "buildingtype.h" #include "vehicletype.h" #include "misc.h" #include "stack.h" #include "palette.h" #include "gameoptions.h" #include "events.h" #include "graphicset.h" #include "spfst.h" #include "loaders.h" #include "dialog.h" #include "itemrepository.h" #include "textfile_evaluation.h" /*#ifdef convert/er #error The small editors should not need to use LoadBi3 #endif*/ #pragma pack(1) class timporterror : public ASCexception {}; int battleisleversion = -1; const int LIBFilesAnz = 11; struct TLIBFiles { char* Name; int FirstRecO; int RecSize; int DataInRecOfs; int DataSize; int Anzahl; }; TLIBFiles LIBFiles [ LIBFilesAnz ] = {{"part000.lib", 0xC, 0x240, 0, 0x240, 1335}, {"unit000.lib", 0x4, 0x240, 0, 0x240, 128}, // 128 f?r BI3 // 118 f?r BI2 Scenery {"layr000.lib", 0x4, 0x240, 0, 0x240, 24}, {"layr001.lib", 0x4, 0x240, 0, 0x240, 24}, {"layr002.lib", 0x4, 0x240, 0, 0x240, 24}, {"layr003.lib", 0x4, 0x240, 0, 0x240, 24}, {"layr004.lib", 0x4, 0x240, 0, 0x240, 24}, {"layr005.lib", 0x4, 0x240, 0, 0x240, 24}, {"layr006.lib", 0x4, 0x240, 0, 0x240, 24}, {"curs000.lib", 0xC, 0x25E,0x1A, 0x240, 12}, {"palt000.lib", 0xC, 0x300, 0, 0x300, 4 } , } ; int libs_to_load = 9; void check_bi3_dir ( void ) { loadbi3graphics(); } void checkbi3dir ( void ) { char temp[1000]; if ( !CGameOptions::Instance()->bi3.dir.getName() ) { readgameoptions(); /* if ( !gameoptions.bi3.dir.getName() ) { gameoptions.bi3.dir = new char [300]; gameoptions.bi3.dir[0] = 0; } */ } int notfound; do { notfound = 0; for ( int i = 0; i < libs_to_load ; i++ ) { if ( CGameOptions::Instance()->bi3.dir.getName() ) strcpy ( temp, CGameOptions::Instance()->bi3.dir.getName() ); else temp[0] = 0; strcat ( temp, LIBFiles[i].Name ); if ( !exist ( temp ) ) { if ( CGameOptions::Instance()->bi3.dir.getName() ) strcpy ( temp, CGameOptions::Instance()->bi3.dir.getName() ); else temp[0] = 0; strcat ( temp, "LIB" ); strcat ( temp, pathdelimitterstring ); strcat ( temp, LIBFiles[i].Name ); if ( !exist ( temp ) ) { printf("Battle Isle file %s not found !\n", temp ); notfound++; } } } if ( notfound ) { if ( !graphicinitialized ) { char bi3path[10000]; printf("Enter Battle Isle directory:\n" ); scanf ( "%s", bi3path ); if ( bi3path[ strlen ( bi3path )-1 ] != pathdelimitter ) strcat ( bi3path, pathdelimitterstring ); CGameOptions::Instance()->bi3.dir.setName ( bi3path ); CGameOptions::Instance()->setChanged(); } else { closegraphics(); printf("\nplease run ASC first to create a config file !\n"); exit(0); } } } while ( notfound ); /* enddo */ battleisleversion = 3; } const char* getbi3path ( void ) { return CGameOptions::Instance()->bi3.dir.getName(); } //! a table to translate a Battle Isle map into an ASC map class Bi3MapTranslationTable { public: //! The first entry is the picture number that is going to be replaced by the picture number of the second entry. vector< pair > terraintranslation; struct Terrain2id { int BIpic; int terrainid; int weather; void read ( tnstream& stream ) { int version = stream.readInt(); if ( version != 1 ) throw tinvalidversion( stream.getDeviceName(), 1, version ); BIpic = stream.readInt(); terrainid = stream.readInt(); weather = stream.readInt(); }; void write ( tnstream& stream ) const { stream.writeInt( 1 ); stream.writeInt( BIpic ); stream.writeInt( terrainid ); stream.writeInt( weather ); }; }; /** The first entry is the picture number that is going to be replaced by the terrain with the ID of the second number and the weather of the third number */ vector< Terrain2id > terrain2idTranslation; struct Terraincombixlat { int bigraph; int terrainid; int terrainweather; int objectid; void read ( tnstream& stream ) { stream.readInt(); bigraph = stream.readInt(); terrainid = stream.readInt(); terrainweather = stream.readInt(); objectid = stream.readInt(); }; void write ( tnstream& stream ) const { stream.writeInt( 1 ); stream.writeInt( bigraph ); stream.writeInt( terrainid ); stream.writeInt( terrainweather ); stream.writeInt( objectid ); }; }; //! This is a special translation for the fields that must be translated to a terrain AND an additional object vector terraincombixlat; struct Objecttranslataion { int BIpic; int objects[4]; int terrainID; int terrainWeather; void read ( tnstream& stream ) { stream.readInt(); BIpic = stream.readInt(); for ( int i = 0; i< 4; ++i ) objects[i] = stream.readInt(); terrainID = stream.readInt(); terrainWeather = stream.readInt(); }; void write ( tnstream& stream ) const { stream.writeInt( 1 ); stream.writeInt( BIpic ); for ( int i = 0; i< 4; ++i ) stream.writeInt( objects[i] ); stream.writeInt( terrainID ); stream.writeInt( terrainWeather ); }; }; /** These BI object pictures can be translated to up to four ASC objects. The first entry is again the BI picture number, the following four the pictures for the ASC objects. A -1 is used if the entry is not used. It does not matter if you use " -1, 1500, -1 , -1 " or " 1500, -1 , -1, -1" or any other order. */ vector objecttranslate ; /** These BI object pictures can be translated to ASC objects. The first entry is again the BI picture number, the second is the ID of the ASC object. */ vector< pair > object2IDtranslate; void runTextIO ( PropertyContainer& pc ); void read ( tnstream& stream ); void write ( tnstream& stream ) const; ASCString filename, location; }; void Bi3MapTranslationTable :: read ( tnstream& stream ) { int version = stream.readInt(); readClassContainer( terraintranslation, stream ); readClassContainer( terrain2idTranslation, stream ); readClassContainer( terraincombixlat, stream ); readClassContainer( objecttranslate, stream ); readClassContainer( object2IDtranslate, stream ); if ( version >= 2 ) { filename = stream.readString(); location = stream.readString(); } } void Bi3MapTranslationTable :: write ( tnstream& stream ) const { stream.writeInt ( 2 ); writeClassContainer ( terraintranslation, stream ); writeClassContainer ( terrain2idTranslation, stream ); writeClassContainer ( terraincombixlat, stream ); writeClassContainer ( objecttranslate, stream ); writeClassContainer ( object2IDtranslate, stream ); stream.writeString( filename ); stream.writeString( location ); } void Bi3MapTranslationTable :: runTextIO ( PropertyContainer& pc ) { vector _terraintranslation; pc.addIntegerArray ( "TerrainTranslation", _terraintranslation ); vector _terrain2idtrans; pc.addIntegerArray ( "Terrain2IDTranslation", _terrain2idtrans ); vector _terrainobjtranslation; pc.addIntegerArray ( "TerrainObjTranslation", _terrainobjtranslation ); vector _objecttranslation; if ( pc.find( "ObjectTranslation" )) pc.addIntegerArray ( "ObjectTranslation", _objecttranslation ); vector _object2IDtranslation; pc.addIntegerArray ( "Object2IDTranslation", _object2IDtranslation ); vector object3translation; if ( pc.find( "Object3Translation" )) pc.addIntegerArray ( "Object3Translation", object3translation ); pc.run(); if ( _terraintranslation.size() % 2 ) fatalError ( "Bi3 map translation : terraintranslation - Invalid number of entries "); terraintranslation.clear(); for ( int i = 0; i < _terraintranslation.size()/2; i++ ) terraintranslation.push_back ( make_pair( _terraintranslation[i*2], _terraintranslation[i*2+1] )); if ( _terrain2idtrans.size() % 3 ) fatalError ( "Bi3 map translation : terrain2idTranslation - Invalid number of entries "); terrain2idTranslation.clear(); for ( int i = 0; i < _terrain2idtrans.size()/3; i++ ) { Terrain2id t2i; t2i.BIpic = _terrain2idtrans[i*3]; t2i.terrainid = _terrain2idtrans[i*3+1]; t2i.weather = _terrain2idtrans[i*3+2]; terrain2idTranslation.push_back ( t2i ); } if ( _terrainobjtranslation.size() % 4 ) fatalError ( "Bi3 map translation : terrainobjtranslation - Invalid number of entries "); terraincombixlat.clear(); for ( int i = 0; i < _terrainobjtranslation.size()/4; i++ ) { Terraincombixlat tcx; tcx.bigraph = _terrainobjtranslation[i*4]; tcx.terrainid = _terrainobjtranslation[i*4+1]; tcx.terrainweather = _terrainobjtranslation[i*4+2]; tcx.objectid = _terrainobjtranslation[i*4+3]; terraincombixlat.push_back ( tcx ); } if ( _objecttranslation.size() % 5 ) fatalError ( "Bi3 map translation : objecttranslation - Invalid number of entries "); objecttranslate.clear(); for ( int i = 0; i < _objecttranslation.size()/5; i++ ) { Objecttranslataion ot; ot.BIpic = _objecttranslation[i*5]; for ( int j = 0; j < 4; j++ ) ot.objects[j] = _objecttranslation[i*5 + 1 + j]; ot.terrainID = -1; ot.terrainWeather = 0; objecttranslate.push_back ( ot ); } if ( object3translation.size() % 7 ) fatalError ( "Bi3 map translation : object3translation - Invalid number of entries "); for ( int i = 0; i < object3translation.size()/7; i++ ) { Objecttranslataion ot; ot.BIpic = object3translation[i*7]; for ( int j = 0; j < 4; j++ ) ot.objects[j] = object3translation[i*7 + 1 + j]; ot.terrainID = object3translation[i*7 + 5]; ot.terrainWeather = object3translation[i*7 + 6]; objecttranslate.push_back ( ot ); } if ( _object2IDtranslation.size() % 2 ) fatalError ( "Bi3 map translation : object2IDtranslation - Invalid number of entries "); object2IDtranslate.clear(); for ( int i = 0; i < _object2IDtranslation.size()/2; i++ ) object2IDtranslate.push_back ( make_pair ( _object2IDtranslation[i*2], _object2IDtranslation[i*2+1] )); } PointerVector bi3ImportTables; void BI3TranslationTableLoader::read ( tnstream& stream ) { stream.readInt(); readPointerContainer ( bi3ImportTables, stream ); } void BI3TranslationTableLoader::write ( tnstream& stream ) { stream.writeInt( 1 ); writePointerContainer ( bi3ImportTables, stream ); } ASCString BI3TranslationTableLoader::getTypeName() { return "bi3maptranslation"; } void BI3TranslationTableLoader::readTextFiles( PropertyReadingContainer& prc, const ASCString& fileName, const ASCString& location ) { Bi3MapTranslationTable* bmtt = new Bi3MapTranslationTable; bmtt->runTextIO ( prc ); bmtt->filename = fileName; bmtt->location = location; bi3ImportTables.push_back ( bmtt ); } const int fuelfactor = 120; const int materialfactor = 390; const int energyfactor = 390; char* HeadID = "MSSN"; char* ACTNID = "ACTN"; char* SHOPID = "SHOP"; char* MAPID = "MAP\0"; char* MISSID = "MISS"; class tloadBImap { Bi3MapTranslationTable* translationTable; struct THeader { char ID[4]; // { 'MSSN' } int MissPos; int MapPos ; int ShopPos; int ACTNPos; Uint16 DFNum ; int DFPos[32] ; // { Pos nach DFXX } int DFLength[32]; // { +4B von DFXX } }; struct TACTN { char ID[4]; Uint16 XSize, YSize; }; typedef Uint16 TStdProdRec[64]; typedef char TAllianzen[6]; struct TMISSPart { char ID[4]; Uint16 Stuff1 [3]; Uint16 NextMiss; char StartWeather; char WhoPlays; // { jeder Mensch/Computer ein Bit } char PlayType; // { jeder Computer ein Bit } char Recs2Win; // { Wieviel Gewinnrecords aus map erf llt werden m ssen, damit man gewinnt (f r jeden player gleich) } char Stuff2[3]; char Landscape; TAllianzen Allianz; // { Wer mit wem } Uint16 Stuff3[65]; TStdProdRec StdProd; Uint16 Stuff4[24]; }; struct TMAPHead { char ID[4]; }; struct TFileMap { Uint16 What1; Uint16 Round, Move; char Player, What2; Uint16 Stuff2; Uint16 Zero1; Uint16 Nr1; Uint16 Nr2; Uint16 Nr3; Uint16 Zero2[11]; }; struct TSHOPHead { char ID[4]; Uint16 Num; }; typedef int TVehContent[8]; typedef TVehContent *PVehContent; union TShopContent { Uint16 XY[4][4]; Uint16 All[16]; TVehContent Veh; }; typedef TShopContent *PShopContent; typedef Uint16 TProduceRec[4]; struct TFileShop { Uint16 ID; Uint16 Pos1; union { struct { Uint16 ShopType; Uint16 Stuff06; // { Zero } Uint16 Name; Uint16 Pos2; Uint16 E, M; char EP, MP ; TShopContent Content; Uint16 ShopType2; TProduceRec Produce; Uint16 Stuff60 ; // { Zero } Uint16 Prior; Uint16 Owner; Uint16 Stuff66[7]; // { Zero } } a; struct { char Zero2[6]; Uint16 W0A; char Zero3[6]; Uint16 W48; Uint16 W4A; char Zero4[2]; Uint16 W4E; } b; char raw[76]; }; }; dynamic_array names; int namenum; bool fakemap; protected: int xoffset, yoffset; TerrainType::Weather* defaultterraintype; public: void LoadFromFile( const char* path, const char* AFileName, TerrainType::Weather* trrn, string* errorOutput ); tloadBImap ( Bi3MapTranslationTable* _translationTable ) : translationTable ( _translationTable ) { xoffset = 0; yoffset = 0; fakemap = false; }; void ____fakeMap____ ( void ) { fakemap = true; }; virtual ~tloadBImap() {}; private: tn_file_buf_stream* MissFile; THeader Header; struct TTextItem { int a; int b; char name[1000]; }; dynamic_array ShopNameList; void LoadTXTFile ( char* filename ); // int TPWMtextfile; void ReadMISSPart(void); void ReadACTNPart(void); void ReadSHOPPart(void); void ReadShopNames( char *txtdata, unsigned long txtsize ); pvehicle getunit ( int typ, int col ); pvehicletype getvehicletype ( int typ ); char* GetStr ( int a, int b ); int convcol ( int c ); TMISSPart OrgMissRec; void GetTXTName ( const char* path, const char* filename, char* buf ); protected: char* missing; virtual void preparemap ( int x, int y ) = 0; virtual pfield getfield ( int x, int y ); }; class ImportBiMap : public tloadBImap { protected: virtual void preparemap ( int x, int y ); public: ImportBiMap ( Bi3MapTranslationTable* _translationTable ) : tloadBImap ( _translationTable ) {}; }; class InsertBiMap : public tloadBImap { protected: virtual void preparemap ( int x, int y ); virtual pfield getfield ( int x, int y ); public: InsertBiMap ( int x, int y, Bi3MapTranslationTable* _translationTable ) : tloadBImap ( _translationTable ) { xoffset = x; yoffset = y; }; }; pfield tloadBImap :: getfield ( int x, int y ) { return ::getfield ( x, y ); } pfield InsertBiMap :: getfield ( int x, int y ) { return ::getfield ( xoffset + x, yoffset + y ); } void tloadBImap :: ReadMISSPart(void) { MissFile->seek ( Header.MissPos ); MissFile->readdata2 ( OrgMissRec ); if ( strncmp ( OrgMissRec.ID, MISSID, 4) ) { strcat ( missing, "\nFatal error: No Battle Isle mission; invalid MissID\n" ); throw timporterror (); } /* int I; StdProd = OrgMissRec.StdProd; for (I = 0; I <= 63; I++) StdProd[I] = StdProd[I] & 0x03; PlayerType = OrgMissRec.PlayType & 0x3F; Allianz = OrgMissRec.Allianz; for (I = 0; I <= 5; I++) Allianz[I] = Allianz[I] & 0x3F; Recs2Win = OrgMissRec.Recs2Win; StartWeather = OrgMissRec.StartWeather; if ( StartWeather < 0 || StartWeather > 4 ) StartWeather = 0; NextMiss = OrgMissRec.NextMiss; Landscape = OrgMissRec.Landscape; */ } int tloadBImap :: convcol ( int c ) { int cl = log2 ( c ); if ( cl == 6 ) return 8; else if ( cl < 2 ) cl = 1 - cl; return cl; } const int bi3unitnum = 74; int translateunits[ bi3unitnum ][2] = { {1201,26}, {1270,26}, {1202,13}, {1200,6}, {1203,-1}, {1204,16}, {1205,17}, {1206,4}, {1207,65}, {1208,-1}, {1209,7}, {1210,66}, {1211,2}, {1212,3}, {1213,17}, {1214,51}, {1215,17}, {1216,2}, {1217,10}, {1218,11}, {1219,16}, {1220,61}, {1221,49},{1222,56}, {1276,-1}, {1223,25}, {1224,72}, {1225,57},{1226,58}, {1227,7}, {1228,59}, {1241,9}, {1242,22},{1244,19}, {1243,29}, {1245,55}, {1246,19}, {1271,21},{1247,52}, {1248,31}, {1251,15}, {1252,15}, {1256,39},{1257,42}, {1258,47}, {1259,14}, {1260,36}, {1261,34},{1262,47}, {1263,37}, {1264,38}, {1265,5}, {1229,18},{1277,-1}, {1249,-1}, {1230,1}, {1231,66}, {1266, 5},{1232,64}, {1233,-1}, {1234,4}, {1235,4}, {1267,35},{1250,29}}; pvehicletype tloadBImap :: getvehicletype ( int tp ) { for ( int j = 0; j < vehicleTypeRepository.getNum(); j++ ) { pvehicletype tnk = vehicleTypeRepository.getObject_byPos ( j ); if ( tnk ) if ( tnk->bipicture > 0 ) if ( tnk->bipicture == 1340 + tp * 2 ) return tnk; } if ( tp < bi3unitnum ) for ( int i = 0; i < 2; i++ ) if ( translateunits[tp][i] > 0 ) { pvehicletype tnk = vehicleTypeRepository.getObject_byID ( translateunits[tp][i] ); if ( tnk ) return tnk; } return NULL; } pvehicle tloadBImap :: getunit ( int tp, int col ) { if ( tp != 0xffff && tp != 0xff && col != 0xff ) { pvehicletype vt = getvehicletype ( tp ); if ( vt ) { Vehicle* eht = new Vehicle ( vt, actmap, col ); eht->fillMagically(); return eht; } } return NULL; } void ImportBiMap :: preparemap ( int x, int y ) { generatemap ( defaultterraintype, x, y ); actmap->setgameparameter( cgp_movefrominvalidfields, 1); actmap->setgameparameter( cgp_forbid_building_construction, 1); } void InsertBiMap :: preparemap ( int x, int y ) { if ( yoffset & 1 ) { yoffset--; strcat ( missing, "y position for map insertion must be even; current position decreased\n"); } int xp = xoffset; int yp = yoffset; if ( xp + x > actmap->xsize ) { int dx = xp + x - actmap->xsize; strcat ( missing, "map had to be resized in X direction\n"); int r = actmap->resize ( 0, 0, 0, dx ); if ( r ) { strcat ( missing, "Resizing failed !!\n"); throw timporterror(); } } if ( yp + y > actmap->ysize ) { int dy = yp + y - actmap->ysize; strcat ( missing, "map had to be resized in Y direction\n"); int r = actmap->resize ( 0, dy, 0, 0 ); if ( r ) { strcat ( missing, "Resizing failed !!\n"); throw timporterror(); } } for ( int b = 0; b < y; b++ ) for ( int a = 0; a < x; a++ ) getfield ( a, b ) -> deleteeverything(); } void stu_height ( pvehicle vehicle ) { char l; pfield fld = getfield ( vehicle->xpos, vehicle->ypos ); vehicle->height = chfahrend; for (l=chsatellit; l> chfahrend ; ) { if (vehicle->typ->height & l ) vehicle->height = l; l>>=1; } /* endfor */ for (l=chtiefgetaucht; l<= chschwimmend ; ) { if (vehicle->typ->height & l ) if (vehicle->typ->terrainaccess.accessible ( fld->bdt ) > 0 ) vehicle->height = l; l<<=1; } if (vehicle->typ->height & chfahrend) if (vehicle->typ->terrainaccess.accessible ( fld->bdt ) > 0 ) vehicle->height = chfahrend; vehicle->setMovement ( vehicle->typ->movement[log2( vehicle->height )] ); } void tloadBImap :: ReadACTNPart(void) { struct { int X, Y; } Size; TACTN ACTNHead; MissFile->seek ( Header.ACTNPos ); MissFile->readdata2( ACTNHead ); if ( strncmp ( ACTNHead.ID ,ACTNID,4 )) { strcat ( missing, "\nFatal error: No Battle Isle mission; invalid ACTNID\n" ); throw timporterror (); } Size.X = ACTNHead.XSize; Size.Y = ACTNHead.YSize; if ( Size.Y & 1 ) Size.Y++; preparemap ( Size.X / 2, Size.Y * 2 ); for ( int i = 0; i < 6; i++ ) if ( OrgMissRec.WhoPlays & (1<< i)) actmap->player[ convcol ( 1 << i) ].stat = Player::tplayerstat( (OrgMissRec.PlayType>>i) & 1); else actmap->player[convcol ( 1 << i) ].stat = Player::off; /* Terrain */ int Y, X; int missnum = 0; dynamic_array miss; Uint16* Line = new Uint16[Size.X]; for (Y = 0; Y < Size.Y ; Y++) { MissFile->readdata( Line, Size.X * 2); for (X = 0; X < Size.X ; X++) { for ( int tr = 0; tr < translationTable->terraintranslation.size(); tr++ ) if ( Line[X] == translationTable->terraintranslation[tr].first ) Line[X] = translationTable->terraintranslation[tr].second; int found = 0; pfield fld = getfield ( X / 2, Y * 2 + (X & 1) ); fld->tempw = Line[X]; fld->temp3 = 0; for ( int i = 0; i < translationTable->terrain2idTranslation.size(); i++ ) { if ( Line[X] == translationTable->terrain2idTranslation[i].BIpic ) { pterraintype trrn = terrainTypeRepository.getObject_byID ( translationTable->terrain2idTranslation[i].terrainid ); int w = translationTable->terrain2idTranslation[i].weather; if ( trrn ) if ( trrn->weather[w] ) { fld->typ = trrn->weather[w]; fld->setparams(); found = 1; } } } if ( !found ) for ( int j = 0; j < translationTable->terraincombixlat.size(); j++ ) if ( Line[X] == translationTable->terraincombixlat[j].bigraph ) { pterraintype trrn = terrainTypeRepository.getObject_byID ( translationTable->terraincombixlat[j].terrainid ); if ( trrn ) { fld->typ = trrn->weather[translationTable->terraincombixlat[j].terrainweather]; pobjecttype obj = NULL; if ( translationTable->terraincombixlat[j].objectid > 0 ) obj = objectTypeRepository.getObject_byID ( translationTable->terraincombixlat[j].objectid ); if ( obj ) fld->addobject ( obj, -1, 1 ); fld->setparams(); found = 1; } } if ( !found ) for ( int i = 0; i < terrainTypeRepository.getNum(); i++ ) { pterraintype trrn = terrainTypeRepository.getObject_byPos ( i ); if ( trrn ) for ( int j = 0; j < cwettertypennum; j++ ) if ( trrn->weather[j] ) if ( trrn->weather[j]->bi_pict == Line[X] ) { fld->typ = trrn->weather[j]; fld->setparams(); found = 1; } } if ( !found ) { int fnd = 0; for ( int k = 0; k < missnum; k++ ) if ( miss[k] == Line[X] ) fnd = 1; if ( !fnd ) miss[missnum++] = Line[X]; } } } if ( missnum ) { strcat ( missing, "The following terrain fields could not be found: " ); for ( int k = 0; k < missnum; k++ ) { strcat ( missing, strrr ( miss[k] )); strcat ( missing, ", "); } strcat ( missing, "\n\n"); } missnum = 0; // Objekte for (Y = 0; Y < Size.Y ; Y++) { MissFile->readdata( Line, Size.X * 2 ); for (X = 0; X < Size.X ; X++) { int found = 0; int newx = X / 2; int newy = Y * 2 + (X & 1); if ( Line[X] != 0xffff ) getfield ( newx, newy )->tempw = Line[X]; int xl = 0; int xlt[5]; int trrID = -1; int trrWeather = 0; xlt[0] = Line[X]; for ( int b = 0; b < translationTable->objecttranslate.size(); b++ ) if ( translationTable->objecttranslate[b].BIpic == Line[X] ) { for ( int c = 1; c < 5; c++ ) if ( translationTable->objecttranslate[b].objects[c] != -1 ) xlt[xl++] = translationTable->objecttranslate[b].objects[c]; trrID = translationTable->objecttranslate[b].terrainID; trrWeather = translationTable->objecttranslate[b].terrainWeather; } if ( xl == 0 ) { for ( int c = 0; c < translationTable->terraintranslation.size(); c++ ) if ( translationTable->terraintranslation[c].first == Line[X] ) xlt[xl++] = translationTable->terraintranslation[c].second; if ( xl == 0 ) xl = 1; } for ( int m = 0; m < xl; m++ ) { int found_without_force = 0; for ( int pass = 0; pass < 2 && !found_without_force; pass++ ) { for ( int i = 0; i < translationTable->object2IDtranslate.size(); i++ ) if ( xlt[m] == translationTable->object2IDtranslate[i].first ) { pobjecttype obj = objectTypeRepository.getObject_byID ( translationTable->object2IDtranslate[i].second ); if ( obj ) { pfield fld = getfield ( newx, newy ); if ( pass == 1 || obj->getFieldModification(fld->getweather()).terrainaccess.accessible ( fld->bdt )) { fld -> addobject ( obj, 0, true ); found |= 1; if ( pass == 0 ) found_without_force = 1; } } } if ( !(found & 1) ) for ( int i = 0; i < objectTypeRepository.getNum(); i++ ) { pobjecttype obj = objectTypeRepository.getObject_byPos ( i ); if ( obj ) for ( int ww = 0; ww < cwettertypennum; ww++ ) if ( obj->weather.test(ww) ) for ( unsigned int j = 0; j < obj->weatherPicture[ww].images.size(); j++ ) if ( obj->weatherPicture[ww].bi3pic[j] == xlt[m] && !(found & 2) && !( getActiveGraphicSet()->getMode(xlt[m]) & 256) ) { pfield fld = getfield ( newx, newy ); if ( pass == 1 || obj->getFieldModification(fld->getweather()).terrainaccess.accessible ( fld->bdt )) { fld -> addobject ( obj, 0, true ); found |= 1; if ( pass == 0 ) found_without_force = 1; } } } } } if ( trrID >= 0 ) { pterraintype trrn = terrainTypeRepository.getObject_byID ( trrID ); if ( trrn ) { if ( !trrn->weather[trrWeather] ) trrWeather = 0; if ( trrn->weather[trrWeather] ) { pfield fld = getfield ( newx, newy ); fld->typ = trrn->weather[trrWeather]; fld->setparams(); } } } if ( !found && Line[X] != 0xffff ) { if ( fakemap ) { pobjecttype o = new ObjectType; *o = *objectTypeRepository.getObject_byID ( 44 ); int id = 1000000; while ( objectTypeRepository.getObject_byID ( id )) id++; o->id = id; o->weather = 1; o->weatherPicture[0].resize(1); loadbi3pict_double ( Line[X], &o->weatherPicture[0].images[0] ); o->weatherPicture[0].bi3pic[0] = Line[X]; // addobjecttype ( o ); // getfield ( newx, newy )->addobject ( o, 0, true ); } else { getfield ( newx, newy )->temp3 = 1; int fnd = 0; for ( int k = 0; k < missnum; k++ ) if ( miss[k] == Line[X] ) fnd = 1; if ( !fnd ) if ( Line[X] < 44 || Line[X] > 88 ) miss[missnum++] = Line[X]; } } } } /* if ( missnum ) { strcat ( missing, "The following objects could not be found: " ); for ( int k = 0; k < missnum; k++ ) { strcat ( missing, strrr ( miss[k] )); strcat ( missing, ", "); } strcat ( missing, "\n\n"); } */ for (Y = 0; Y < Size.Y ; Y++) { MissFile->readdata ( Line, Size.X * 2 ); for (X = 0; X < Size.X ; X++) { int tp = Line[X] & 255; int cl = convcol(Line[X] >> 8); pvehicle eht = getunit ( tp, cl ); if ( eht ) { pfield fld = getfield ( X / 2, Y * 2 + (X & 1) ); fld->vehicle = eht; fld->vehicle->xpos = xoffset + X / 2; fld->vehicle->ypos = yoffset + Y * 2 + (X & 1); stu_height ( fld->vehicle ); } } } delete[] Line; } struct blds { pbuildingtype bld; int pictnum; int terrainmatch; int objectmatch; } ; void tloadBImap :: ReadSHOPPart( void ) { TSHOPHead SHOPHead; TFileShop FileShop; // PVehContent PVC; int firstmissingbuilding = 1; MissFile->seek ( Header.ShopPos ); MissFile->readdata2 ( SHOPHead ); if ( strncmp ( SHOPHead.ID, SHOPID, 4 )) { strcat ( missing, "\nFatal error: No Battle Isle mission; invalid ShopID\n" ); throw timporterror (); } int ShopNum = 0; // int VehContNum = 0; // int AINum = 0; for ( int I = 0; I < SHOPHead.Num ; I++ ) { MissFile->readdata2 ( FileShop ); if ( FileShop.ID == 1) { // wenn kein ki punkt if (FileShop.a.ShopType == 32) { // Vehicle int IsVehCont = false; for ( int J = 0; J < 8; J++ ) if ( FileShop.a.Content.Veh[J] != 0xFFFF ) IsVehCont = true; if ( IsVehCont ) { int Y = FileShop.Pos1 / 64; int X = FileShop.Pos1 % 64; pfield fld = getfield ( X / 2, Y * 2 + (X & 1) ); int nm = 0; if ( fld->vehicle ) for ( int j = 0; j < 8; j++ ) if ( FileShop.a.Content.Veh[j] >= 0 ) { pvehicle eht = getunit ( FileShop.a.Content.Veh[j], fld->vehicle->color/8 ); if ( eht ) { eht->xpos = xoffset + X / 2; eht->ypos = yoffset + Y * 2 + (X & 1); fld->vehicle->loading[nm++] = eht; } } } } else { int Y = FileShop.Pos1 / 64; int X = FileShop.Pos1 % 64; int newx = X / 2; int newy = Y * 2 + (X & 1); pfield fld = getfield ( newx, newy ); dynamic_array bldlist; int bldlistnum = 0; for ( int i = 0; i < buildingTypeRepository.getNum(); i++ ) { pbuildingtype bld = buildingTypeRepository.getObject_byPos ( i ); if ( bld ) for ( int w = 0; w < cwettertypennum; w++ ) for ( int p = 0; p < maxbuildingpicnum; p++ ) if ( bld->w_picture[w][p][ bld->entry.x ] [ bld->entry.y ] ) if ( bld->bi_picture[w][p][ bld->entry.x ] [ bld->entry.y ] == fld->tempw ) { bldlist[ bldlistnum ].bld = bld; int cnt = 0; int terrainmatch = 0; int objmatch = 0; bool fail = false; for ( int m = 0; m < 4; m++ ) for ( int n = 0; n < 6; n++ ) if ( bld->getpicture( BuildingType::LocalCoordinate(m , n) ) ) { MapCoordinate pos = bld->getFieldCoordinate ( MapCoordinate(newx, newy), BuildingType::LocalCoordinate(m, n) ); pfield fld2 = getfield ( pos.x, pos.y ); if ( !fld2 ) fail = true; else { if ( bld->terrainaccess.accessible ( fld2->bdt ) > 0 ) terrainmatch++; if ( bld->bi_picture[w][p][m][n] == fld2->tempw ) objmatch++; } cnt++; } if ( !fail ) { bldlist[ bldlistnum ].pictnum = cnt; bldlist[ bldlistnum ].terrainmatch = terrainmatch; bldlist[ bldlistnum ].objectmatch = objmatch; bldlistnum++; } } } int found = 0; if ( bldlistnum ) { for ( int j = 0; j < bldlistnum-1; ) if ( ( bldlist[ j ].objectmatch < bldlist[ j+1 ].objectmatch ) || ( bldlist[ j ].objectmatch == bldlist[ j+1 ].objectmatch && bldlist[ j ].terrainmatch < bldlist[ j+1 ].terrainmatch) ) { blds tmp = bldlist[ j ]; bldlist[ j ] = bldlist[ j+1 ]; bldlist[ j+1 ] = tmp; if ( j > 0 ) j--; } else j++; int actpos = 0; while ( !found && actpos < bldlistnum ) { pbuildingtype bld = bldlist[actpos].bld; for ( int w = 0; w < cwettertypennum; w++ ) for ( int p = 0; p < maxbuildingpicnum; p++ ) if ( !found ) { int match = 1; for ( int m = 0; m < 4; m++ ) for ( int n = 0; n < 6; n++ ) if ( bld->w_picture[w][p][ m ] [ n ] ) if ( bld->getpicture( BuildingType::LocalCoordinate(m , n) ) ) { MapCoordinate pos = bld->getFieldCoordinate ( MapCoordinate(newx, newy), BuildingType::LocalCoordinate(m, n) ); pfield fld2 = getfield ( pos.x, pos.y ); if ( fld2->tempw != bld->bi_picture[w][p][ m ] [ n ] ) match = 0; } if ( match ) found = 1; } actpos++; } actpos--; if ( found ) { putbuilding ( MapCoordinate(xoffset + newx, yoffset + newy), 0, bldlist[actpos].bld, bldlist[actpos].bld->construction_steps - 1, 1 ); if ( fld->building ) { for ( int m = 0; m < 4; m++ ) for ( int n = 0; n < 6; n++ ) if ( fld->building->getpicture( BuildingType::LocalCoordinate(m , n) ) ) { fld->building->getField ( BuildingType::LocalCoordinate(m, n) )->temp3 = 0; } /* if ( field->object ) for ( int o = 0; o < field->object->objnum; o++ ) field->removeobject ( field->object->object[o]->typ ); } */ found = 255; } else found = 254; } } if ( fld->building ) { // if ( battleisleversion == 3 ) fld->building->name = GetStr( ShopNum + 2,16); /* bi3 macht das so */ /* else ArrShop.NameStr = GetStr(FileShop.Name, 16); // bi2 wahrscheinlich so */ int newcol = convcol ( FileShop.a.Owner ); if ( newcol != fld->building->color/8 ) fld->building->convert ( newcol ); int unitnum = 0; for ( int j = 0; j < 16; j++ ) { pvehicle eht = getunit ( FileShop.a.Content.All[j], fld->building->color/8 ); if ( eht ) { fld->building->loading[unitnum++] = eht; eht->xpos = newx; eht->ypos = newy; } } int prodnum = 0; for ( int k= 0; k < 4; k++ ) { pvehicletype vt = getvehicletype ( FileShop.a.Produce[k] ); if ( vt ) { int fnd = 0; for ( int l = 0; l < prodnum; l++ ) if ( fld->building->production[l] == vt ) fnd++; if ( !fnd ) if ( fld->building->typ->vehicleFit( vt )) fld->building->production [ prodnum++ ] = vt; } } for ( int l = 0; l < 64; l++ ) if ( OrgMissRec.StdProd[l] & 3 ) { pvehicletype vt = getvehicletype ( l ); if ( vt ) { int fnd = 0; for ( int l = 0; l < prodnum; l++ ) if ( fld->building->production[l] == vt ) fnd++; if ( !fnd ) if ( prodnum < 32 ) if ( fld->building->typ->vehicleFit( vt )) fld->building->production [ prodnum++ ] = vt; } } fld->building->bi_resourceplus.energy = energyfactor * FileShop.a.EP; fld->building->bi_resourceplus.material = materialfactor * FileShop.a.MP; fld->building->bi_resourceplus.fuel = fuelfactor * FileShop.a.EP; fld->building->actstorage.energy = energyfactor * FileShop.a.E; fld->building->actstorage.material = materialfactor * FileShop.a.M; fld->building->actstorage.fuel = fuelfactor * FileShop.a.E; } else { if ( found == 254 ) { char tmp[100]; int obj = fld->tempw; sprintf( tmp, "The building at position %d / %d using pic #%d could not be set\n", newx, newy, obj ); strcat ( missing, tmp ); } else { if ( firstmissingbuilding ) { strcat ( missing, "The buildings at the following coordinates could not be found:\n " ); firstmissingbuilding = 0; } char tmp[100]; int obj = fld->tempw; sprintf( tmp, "%d / %d using pic #%d\n", newx, newy, obj ); strcat ( missing, tmp ); } } ShopNum++; } } } // if ( TPWMtextfile ) // strcat ( missing, "\nThe names of the buildings could not be read because the text file is TPWM encoded. Please decode it first if you want to keep the names of the shops !\n"); int missnum = 0; dynamic_array miss; for ( int y = 0; y < actmap->ysize; y++ ) for ( int x = 0; x < actmap->xsize; x++ ) if ( ::getfield(x,y)->temp3 ) { int m = ::getfield(x,y)->tempw; if ( m > 0 && m != 0xffff ) { int fnd = 0; for ( int k = 0; k < missnum; k++ ) if ( miss[k] == m ) fnd = 1; if ( !fnd ) miss[missnum++] = m; } } if ( missnum ) { strcat ( missing, "The following objects could not be found: " ); for ( int k = 0; k < missnum; k++ ) { strcat ( missing, strrr ( miss[k] )); strcat ( missing, ", "); } strcat ( missing, "\n\n"); } } char* tloadBImap :: GetStr( int a, int b ) { // if ( TPWMtextfile ) // return NULL; // else for ( int i = 0; i <= ShopNameList.getlength(); i++ ) if ( ShopNameList[i].a == a && ShopNameList[i].b == b ) return strdup ( ShopNameList[i].name ); return NULL; } /* TPTC: TOCONV.PAS(303): Warning: Nested function, tok=SplitName Boolean SplitName(char * S, char * Name, Uint16 * R1, Uint16 * R2) { Integer Code; Result = false; strcpy(S,Trim(S)); if (strcmp(S,"") != 0) { if (S[0] != '#') return; val(copy(S,2,4),R1,&Code); if (Code != 0) return; if (S[5] != ':') return; val(copy(S,7,4),R2,&Code); if (Code != 0) return; if (S[10] != '{') return; if (S[strlen(S)-1] != '}') return; strcpy(S,copy(S,12,strlen(S) - 12)); // Delete(S, 1, 11); // Delete(S, Length(S), 1); strcpy(Name,S); sbld(Result,"%b",true); } } */ void tloadBImap :: ReadShopNames( char* databuf, unsigned long datasize ) { unsigned long dptr=0; char buf[ 1000]; int c; do { do { c = databuf[dptr++]; } while ( c != '#' && dptr '9' ) return; buf[i] = c; } buf[4] = 0; int a1 = atoi ( buf ); if ( databuf[dptr++] != ':' ) return; for ( i = 0; i < 4; i++ ) { c = databuf[dptr++]; if ( c < '0' || c > '9' ) return; buf[i] = c; } buf[4] = 0; int a2 = atoi ( buf ); if ( databuf[dptr++] != '{' ) return; i = 0; do { c = databuf[dptr++]; buf[i++] = c; } while ( c != '}' && dptr>7)&1)+((code>>6)&1)+((code>>5)&1)+((code>>4)&1)+((code>>3)&1)+((code>>2)&1)+((code>>1)&1)+((code>>0)&1); fread(&inbuf, 8+bitsset, 1, fp); for (int i=0; (i<8)&&(outptr>i))==0) { // straight copy txtbuffer[outptr]=inbuf[inptr]; outptr++; inptr++; } else { // repeat char d0,d1; d0=inbuf[inptr]; inptr++; d1=inbuf[inptr]; inptr++; int blklen=(d0&0xf)+3; int blkofs=((d0&0xf0)<<4)+d1; for (int j=0; (j 0) and (P<> 0) then begin SavePlayerNames:= true; S:= Copy(LevelDescription, P, Length(LevelDescription)-P+1); Delete(LevelDescription, P, Length(LevelDescription)-P+1); Delete(S, 1, 1); for I:= 0 to 6 do begin P:= Pos('|', S); if P= 0 then P:= Length(S)+ 1; FPlayers[I].Name:= Copy(S, 1, P-1); Delete(S, 1, P); P:= Pos('|', S); if P= 0 then P:= Length(S)+ 1; try FPlayers[I].Color:= StrToInt(Copy(S, 1, P-1)); except FPlayers[I].Color:= 0; end; Delete(S, 1, P); end; end else SavePlayerNames:= false; */ } void tloadBImap :: LoadFromFile( const char* path, const char* AFileName, TerrainType::Weather* trrn, string* errorOutput ) { defaultterraintype = trrn; char temp[4000]; missing = temp; missing[0] = 0; namenum = 0; // PShopNameItem PSNI; char TXTName[1000]; bool error = false; try { GetTXTName( path, AFileName, TXTName ); LoadTXTFile(TXTName); char completefilename[1000]; strcpy ( completefilename, path ); strcat ( completefilename, "mis" ); strcat ( completefilename, pathdelimitterstring ); strcat ( completefilename, AFileName ); tn_file_buf_stream stream ( completefilename, tnstream::reading ); MissFile = &stream; MissFile->readdata2( Header ); if ( strncmp ( Header.ID, HeadID, 4 )) { strcat ( missing, "\nFatal error: No Battle Isle mission; invalid HeadID\n" ); throw timporterror (); } ReadMISSPart(); ReadACTNPart(); ReadSHOPPart(); /* ReadMAPPart(); LoadDFs(); UnPackDF(AktDFNum); */ if ( GetStr ( 1, 24 ) ) actmap->maptitle = GetStr ( 1, 24 ); else actmap->maptitle.erase(); if ( actmap->maptitle.empty() ) actmap->maptitle = "imported BI map"; } /* endtry */ catch ( tfileerror err ) { strcat ( missing, "\nA fatal error occured while accessing the file " ); strcat ( missing, err.getFileName().c_str() ); strcat ( missing, "\n" ); error = true; } /* endcatch */ catch ( ASCexception ) { strcat ( missing, "\nA fatal error occured" ); error = true; } /* endcatch */ if ( !error ) calculateallobjects(); if ( missing[0] ) { if ( errorOutput ) (*errorOutput)=missing; else { tviewanytext vat; vat.init ( "warning", missing ); vat.run(); vat.done(); } } } ASCString defaultImportTranslationTable; void setDefaultBI3ImportTranslationTable( const ASCString& filename ) { defaultImportTranslationTable = filename; } Bi3MapTranslationTable* chooseImportTable ( ) { if ( bi3ImportTables.size() == 0) fatalError ( "No BI3 map translation tables present!"); if ( bi3ImportTables.size() == 1) return bi3ImportTables[0]; if ( defaultImportTranslationTable.empty() ) { vector strings; for ( int i = 0; i < bi3ImportTables.size(); i++ ) strings.push_back ( bi3ImportTables[i]->filename ); int t = chooseString ( "Select Import Table", strings ); if ( t != 255 ) return bi3ImportTables[ t ]; else return bi3ImportTables[0]; } else { for ( int i = 0; i < bi3ImportTables.size(); i++ ) if ( bi3ImportTables[i]->filename.compare_ci ( defaultImportTranslationTable ) == 0 ) return bi3ImportTables[i]; fatalError ( "default BI3 import Table " +defaultImportTranslationTable + " not found !"); // never executed... return bi3ImportTables[0]; } } void importbattleislemap ( const char* path, const char* filename, TerrainType::Weather* trrn, string* errorOutput, bool fakemap ) { pmap oldmap = actmap; actmap = NULL; activateGraphicSet ( 1 ); try { ImportBiMap lbim ( chooseImportTable ( ) ); if ( fakemap ) lbim.____fakeMap____(); lbim.LoadFromFile ( path, filename, trrn, errorOutput ); actmap->_resourcemode = 1; actmap->cleartemps ( 7 ); } catch ( ASCexception ) { delete actmap; actmap = oldmap; throw; } delete oldmap; } void insertbattleislemap ( int x, int y, const char* path, const char* filename ) { activateGraphicSet ( 1 ); InsertBiMap lbim ( x, y, chooseImportTable ( ) ); lbim.LoadFromFile ( path, filename, NULL, NULL ); actmap->_resourcemode = 1; actmap->cleartemps ( 7 ); } #pragma pack()