00001
00002
00003
00004
00005
00006
00007
00008
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <algorithm>
00023
00024 #include "vehicletype.h"
00025 #include "buildingtype.h"
00026 #include "graphicset.h"
00027 #include "gameoptions.h"
00028 #include "textfiletags.h"
00029 #include "stringtokenizer.h"
00030 #include "textfile_evaluation.h"
00031 #include "graphics/surface.h"
00032
00033 #include "errors.h"
00034 #include "sgstream.h"
00035 #include "graphics/blitter.h"
00036 #include "graphics/ColorTransform_PlayerColor.h"
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 BuildingType :: BuildingType ( void )
00069 {
00070 for ( int x = 0; x < 4; x++ )
00071 for ( int y = 0; y < 6; y++ ) {
00072 field_Exists[x][y] = false;
00073 for ( int w = 0; w < cwettertypennum; ++w )
00074 for ( int c = 0; c < maxbuildingpicnum; ++c )
00075 bi_picture[w][c][x][y] = -1;
00076 }
00077
00078 buildingNotRemovable = false;
00079
00080 static const float matrix[] = { 1, 0, 0,
00081 0, 1, 0,
00082 0, 0, 1 };
00083
00084 productionEfficiency = ResourceMatrix( matrix );
00085
00086 }
00087
00088
00089 int BuildingType :: getMemoryFootprint() const
00090 {
00091 int size = sizeof(*this);
00092
00093 for ( int i = 0; i < cwettertypennum; ++i )
00094 for ( int j = 0; j < maxbuildingpicnum; ++j )
00095 for ( int k = 0; k < 4; ++k )
00096 for ( int l = 0; l < 6; ++l )
00097 size += w_picture[i][j][k][l].getMemoryFootprint() - sizeof( Surface );
00098 return size;
00099 }
00100
00101
00102 int BuildingType :: getBIPicture( const LocalCoordinate& localCoordinate, int weather , int constructionStep ) const
00103 {
00104 return bi_picture [weather][constructionStep][localCoordinate.x][localCoordinate.y];
00105 }
00106
00107
00108 const Surface& BuildingType :: getPicture ( const LocalCoordinate& localCoordinate, int weather, int constructionStep ) const
00109 {
00110 if( constructionStep >= construction_steps )
00111 constructionStep = construction_steps-1;
00112
00113 if ( !weatherBits.test(weather))
00114 weather = 0;
00115
00116 if ( bi_picture [weather][constructionStep][localCoordinate.x][localCoordinate.y] <= 0 )
00117 return w_picture[weather][constructionStep][localCoordinate.x][localCoordinate.y];
00118 else
00119 return GraphicSetManager::Instance().getPic(bi_picture [weather][constructionStep][localCoordinate.x][localCoordinate.y]);
00120
00121 }
00122
00123 void BuildingType::paint ( Surface& s, SPoint pos, const PlayerColor& player, int weather, int constructionStep ) const
00124 {
00125 for ( int x = 0; x < 4; x++ )
00126 for ( int y = 0; y < 6; y++ )
00127 if ( fieldExists(LocalCoordinate(x,y) ))
00128 paintSingleField(s,pos,LocalCoordinate(x,y),player,weather,constructionStep);
00129
00130 }
00131
00132 void BuildingType::paint ( Surface& s, SPoint pos ) const
00133 {
00134 for ( int x = 0; x < 4; x++ )
00135 for ( int y = 0; y < 6; y++ )
00136 if ( fieldExists(LocalCoordinate(x,y) ))
00137 paintSingleField(s,pos,LocalCoordinate(x,y));
00138
00139 }
00140
00141
00142 void BuildingType:: paintSingleField ( Surface& s, SPoint pos, const LocalCoordinate& localCoordinate, const PlayerColor& player, int weather, int constructionStep ) const
00143 {
00144 megaBlitter<ColorTransform_PlayerCol,
00145 ColorMerger_AlphaOverwrite,
00146 SourcePixelSelector_Plain,
00147 TargetPixelSelector_All>
00148 ( getPicture(localCoordinate,weather,constructionStep),
00149 s,
00150 SPoint( pos.x + localCoordinate.x * fielddistx + ( localCoordinate.y & 1 ) * fielddisthalfx, pos.y + localCoordinate.y * fielddisty),
00151 player,
00152 nullParam, nullParam, nullParam );
00153
00154
00155 }
00156
00157 void BuildingType:: paintSingleField ( Surface& s, SPoint pos, const LocalCoordinate& localCoordinate, int weather, int constructionStep ) const
00158 {
00159 megaBlitter<ColorTransform_None,
00160 ColorMerger_AlphaOverwrite,
00161 SourcePixelSelector_Plain,
00162 TargetPixelSelector_All>
00163 ( getPicture(localCoordinate,weather,constructionStep),
00164 s,
00165 SPoint( pos.x + localCoordinate.x * fielddistx + ( localCoordinate.y & 1 ) * fielddisthalfx, pos.y + localCoordinate.y * fielddisty),
00166 nullParam, nullParam, nullParam, nullParam );
00167
00168
00169 }
00170
00171
00172
00173 MapCoordinate BuildingType :: getFieldCoordinate ( const MapCoordinate& entryOnMap, const LocalCoordinate& localCoordinates ) const
00174 {
00175 int orgx = entryOnMap.x - entry.x - (entry.y & ~entryOnMap.y & 1 );
00176 int orgy = entryOnMap.y - entry.y;
00177
00178 int dx = orgy & 1;
00179
00180 int yy = orgy + localCoordinates.y;
00181 int xx = orgx + localCoordinates.x + (dx & ~yy);
00182 MapCoordinate mc ( xx, yy );
00183 return mc;
00184 }
00185
00186 BuildingType::LocalCoordinate BuildingType::getLocalCoordinate( const MapCoordinate& entryOnMap, const MapCoordinate& field ) const
00187 {
00188 int homex = entryOnMap.x - entry.x;
00189 int homey = entryOnMap.y - entry.y;
00190
00191 if ( (entry.y & 1) && !(entryOnMap.y & 1))
00192 homex -= 1;
00193
00194
00195 int ly = field.y - homey;
00196 int lx = field.x - homex;
00197 if ( (ly & 1) && (homey & 1 ))
00198 lx -= 1;
00199
00200 if ( lx >= 0 && lx < 4 && ly >= 0 && ly < 6 && fieldExists(LocalCoordinate(lx,ly)))
00201 return LocalCoordinate(lx,ly);
00202 else
00203 return LocalCoordinate();
00204 }
00205
00206
00207
00208 const int building_version = 14;
00209
00210
00211 void BuildingType :: read ( tnstream& stream )
00212 {
00213 int version = stream.readInt();
00214 if ( version <= building_version && version >= 1) {
00215
00216 bool picsAvail[ cwettertypennum ][ maxbuildingpicnum ][4][6];
00217
00218 for ( int v = 0; v < cwettertypennum; v++ )
00219 for ( int w = 0; w < maxbuildingpicnum; w++ )
00220 for ( int x = 0; x < 4; x++ )
00221 for ( int y = 0; y < 6 ; y++ ) {
00222 picsAvail[v][w][x][y] = stream.readInt( );
00223 if ( picsAvail[v][w][x][y] ) {
00224 field_Exists[x][y] = true;
00225 weatherBits.set(v);
00226 }
00227 }
00228
00229
00230 for ( int v = 0; v < cwettertypennum; v++ )
00231 for ( int w = 0; w < maxbuildingpicnum; w++ )
00232 for ( int x = 0; x < 4; x++ )
00233 for ( int y = 0; y < 6 ; y++ ) {
00234 int i = stream.readInt( );
00235 bi_picture[v][w][x][y] = i;
00236 if ( i > 0 ) {
00237 field_Exists[x][y] = true;
00238 weatherBits.set(v);
00239 }
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 entry.x = stream.readInt( );
00254 entry.y = stream.readInt( );
00255
00256 stream.readInt( );
00257 stream.readInt( );
00258 stream.readInt( );
00259 stream.readInt( );
00260
00261 id = stream.readInt( );
00262 bool __loadName = stream.readInt( );
00263 _armor = stream.readInt( );
00264 jamming = stream.readInt( );
00265 view = stream.readInt( );
00266 stream.readInt( );
00267 stream.readChar( );
00268 stream.readChar( );
00269 productionCost.material = stream.readInt( );
00270 productionCost.fuel = stream.readInt( );
00271 if ( version <= 9 ) {
00272 int special = stream.readInt( );
00273 convertOldFunctions( special, stream.getLocation() );
00274 }
00275
00276 technologylevel = stream.readChar( );
00277 stream.readChar( );
00278
00279 terrainaccess.read ( stream );
00280
00281 construction_steps = stream.readInt( );
00282 maxresearchpoints = stream.readInt( );
00283 asc_mode_tank.energy = stream.readInt( );
00284 asc_mode_tank.material = stream.readInt( );
00285 asc_mode_tank.fuel = stream.readInt( );
00286 maxplus.energy = stream.readInt( );
00287 maxplus.material = stream.readInt( );
00288 maxplus.fuel = stream.readInt( );
00289 efficiencyfuel = stream.readInt( );
00290 efficiencymaterial = stream.readInt( );
00291 stream.readInt( );
00292 stream.readInt( );
00293
00294 bi_mode_tank.energy = stream.readInt( );
00295 bi_mode_tank.material = stream.readInt( );
00296 bi_mode_tank.fuel = stream.readInt( );
00297
00298 if ( version >= 5 ) {
00299 defaultProduction.energy = stream.readInt( );
00300 defaultProduction.material = stream.readInt( );
00301 defaultProduction.fuel = stream.readInt( );
00302 }
00303
00304
00305 height = 1 << getFirstBit ( stream.readInt() );
00306 stream.readInt( );
00307 externalloadheight = stream.readInt( );
00308
00309 if ( version >= 3)
00310 stream.readInt();
00311
00312
00313 if ( version >= 2 ) {
00314 if ( version <= 11 ) {
00315 for ( int x = 0; x < 4; x++ )
00316 for ( int y = 0; y < 6; y++ ) {
00317 int id = stream.readInt();
00318 if ( id > 0 )
00319 destructionObjects.insert( make_pair(LocalCoordinate(x,y), id));
00320 }
00321 }
00322 } else {
00323 for ( int w = 0; w < 9; w++ )
00324 stream.readInt( );
00325 destructionObjects.clear();
00326 }
00327
00328 if ( __loadName )
00329 name = stream.readString();
00330
00331 for ( int k = 0; k < maxbuildingpicnum ; k++)
00332 for ( int j = 0; j <= 5; j++)
00333 for ( int i = 0; i <= 3; i++)
00334 for ( int w = 0; w < cwettertypennum; w++ )
00335 if ( picsAvail[w][k][i][j] )
00336 if ( bi_picture[w][k][i][j] == -1 )
00337 w_picture[w][k][i][j].read(stream );
00338
00339
00340
00341 if ( version >= 4 )
00342 ContainerBaseType::read ( stream );
00343
00344 if ( version >= 6 )
00345 nominalresearchpoints = stream.readInt();
00346
00347 if ( version >= 7 ) {
00348 techDependency.read( stream );
00349 defaultMaxResearchpoints = stream.readInt();
00350 }
00351
00352 if ( version >= 8 )
00353 infotext = stream.readString();
00354
00355 if ( version >= 11 )
00356 buildingNotRemovable = stream.readInt();
00357
00358 if ( version >= 12 ) {
00359 int num = stream.readInt();
00360 for ( int i = 0; i < num; ++i ) {
00361 int x = stream.readInt();
00362 int y = stream.readInt();
00363 int id = stream.readInt();
00364 destructionObjects.insert( make_pair( LocalCoordinate(x,y),id));
00365 }
00366 }
00367
00368 if ( version >= 13 )
00369 for ( int w = 0; w < cwettertypennum; ++w )
00370 originalImageFilename[w] = stream.readString();
00371
00372 if ( version >= 14 )
00373 description = stream.readString();
00374 } else
00375 throw tinvalidversion ( stream.getLocation(), building_version, version );
00376 }
00377
00378 void BuildingType :: write ( tnstream& stream ) const
00379 {
00380 stream.writeInt ( building_version );
00381
00382 for ( int v = 0; v < cwettertypennum; v++ )
00383 for ( int w = 0; w < maxbuildingpicnum; w++ )
00384 for ( int x = 0; x < 4; x++ )
00385 for ( int y = 0; y < 6 ; y++ ) {
00386 stream.writeInt ( w_picture[v][w][x][y].valid() );
00387 }
00388
00389 for ( int v = 0; v < cwettertypennum; v++ )
00390 for ( int w = 0; w < maxbuildingpicnum; w++ )
00391 for ( int x = 0; x < 4; x++ )
00392 for ( int y = 0; y < 6 ; y++ )
00393 stream.writeInt ( bi_picture[v][w][x][y] );
00394
00395
00396
00397
00398
00399
00400
00401
00402 stream.writeInt ( entry.x );
00403 stream.writeInt ( entry.y );
00404 stream.writeInt ( -1 );
00405 stream.writeInt ( -1 );
00406 stream.writeInt ( -1 );
00407 stream.writeInt ( -1 );
00408
00409 stream.writeInt ( id );
00410 stream.writeInt ( !name.empty() );
00411 stream.writeInt ( _armor );
00412 stream.writeInt ( jamming );
00413 stream.writeInt ( view );
00414 stream.writeInt ( 0 );
00415 stream.writeChar ( 0);
00416 stream.writeChar ( 0 );
00417 stream.writeInt ( productionCost.material );
00418 stream.writeInt ( productionCost.fuel );
00419 stream.writeChar ( technologylevel );
00420 stream.writeChar ( 0 );
00421
00422 terrainaccess.write ( stream );
00423
00424 stream.writeInt ( construction_steps );
00425 stream.writeInt ( maxresearchpoints );
00426 stream.writeInt ( asc_mode_tank.energy );
00427 stream.writeInt ( asc_mode_tank.material );
00428 stream.writeInt ( asc_mode_tank.fuel );
00429
00430 stream.writeInt ( maxplus.energy );
00431 stream.writeInt ( maxplus.material );
00432 stream.writeInt ( maxplus.fuel );
00433 stream.writeInt ( efficiencyfuel );
00434 stream.writeInt ( efficiencymaterial );
00435 stream.writeInt ( 1 );
00436 stream.writeInt ( 1 );
00437
00438 stream.writeInt ( bi_mode_tank.energy );
00439 stream.writeInt ( bi_mode_tank.material );
00440 stream.writeInt ( bi_mode_tank.fuel );
00441
00442 stream.writeInt ( defaultProduction.energy );
00443 stream.writeInt ( defaultProduction.material );
00444 stream.writeInt ( defaultProduction.fuel );
00445
00446 stream.writeInt ( height );
00447 stream.writeInt ( 0 );
00448 stream.writeInt ( externalloadheight );
00449
00450 stream.writeInt ( 0 );
00451
00452 if ( !name.empty() )
00453 stream.writeString ( name );
00454
00455 for (int k = 0; k < maxbuildingpicnum; k++)
00456 for (int j = 0; j <= 5; j++)
00457 for (int i = 0; i <= 3; i++)
00458 for ( int w = 0; w < cwettertypennum; w++ )
00459 if ( w_picture[w][k][i][j].valid() )
00460 if ( bi_picture[w][k][i][j] == -1 )
00461 w_picture[w][k][i][j].write(stream);
00462
00463 ContainerBaseType::write ( stream );
00464
00465 stream.writeInt( nominalresearchpoints );
00466
00467 techDependency.write ( stream );
00468 stream.writeInt( defaultMaxResearchpoints );
00469
00470 stream.writeString ( infotext );
00471 stream.writeInt( buildingNotRemovable );
00472
00473 stream.writeInt( destructionObjects.size());
00474 for ( DestructionObjects::const_iterator i = destructionObjects.begin(); i != destructionObjects.end(); ++i) {
00475 stream.writeInt( i->first.x);
00476 stream.writeInt( i->first.y);
00477 stream.writeInt( i->second);
00478 }
00479
00480 for ( int w = 0; w < cwettertypennum; ++w )
00481 stream.writeString( originalImageFilename[w] );
00482
00483 stream.writeString( description );
00484 }
00485
00486
00487 ASCString BuildingType :: LocalCoordinate :: toString ( ) const
00488 {
00489 ASCString s;
00490 s += 'A'+x;
00491 s += '1'+y;
00492 return s;
00493 }
00494
00495 class InvalidString : public ASCexception {};
00496
00497 BuildingType :: LocalCoordinate :: LocalCoordinate ( const ASCString& s )
00498 {
00499 ASCString s2 = s;
00500 s2.toUpper();
00501 if ( s2.length() < 2 ) {
00502 x = -1;
00503 y = -1;
00504 throw InvalidString();
00505 } else {
00506 x = s2[0] - 'A';
00507 y = s2[1] - '1';
00508 if ( x < 0 || x > 5 || y < 0 || y > 7 )
00509 throw InvalidString();
00510 }
00511 }
00512
00513
00514 void BuildingType :: runTextIO ( PropertyContainer& pc )
00515 {
00516 try {
00517
00518 pc.addBreakpoint();
00519
00520 ContainerBaseType::runTextIO ( pc );
00521
00522 pc.addInteger ( "ConstructionStages", construction_steps );
00523
00524 for ( int i = 0; i < cwettertypennum; i++ )
00525 for ( int x = 0; x < 4; x++ )
00526 for ( int y = 0; y < 6; y++ )
00527 if ( w_picture[i][0][x][y].valid() )
00528 weatherBits.set(i);
00529
00530 pc.addTagArray( "Weather", weatherBits, cwettertypennum, weatherTags );
00531
00532
00533 ASCString fieldNames;
00534 for ( int a = 0; a < 4; a++ )
00535 for ( int b = 0; b < 6; b++ )
00536 if ( w_picture[0][0][a][b].valid() || bi_picture[0][0][a][b] > 0 ) {
00537 fieldNames += LocalCoordinate( a, b).toString();
00538 fieldNames += " ";
00539 }
00540
00541 pc.addString( "Fields", fieldNames );
00542
00543 typedef vector<LocalCoordinate> Fields;
00544 Fields fields;
00545 StringTokenizer st ( fieldNames );
00546 ASCString t = st.getNextToken();
00547 while ( !t.empty() ) {
00548 LocalCoordinate lc ( t );
00549 fields.push_back ( lc );
00550 t = st.getNextToken();
00551 field_Exists[lc.x][lc.y] = true;
00552 }
00553
00554
00555
00556
00557 bool bi3pics = false;
00558
00559 for ( int i = 0; i < 4; i++ )
00560 for ( int j = 0; j < 6; j++ )
00561 if ( bi_picture[0][0][i][j] >= 0 )
00562 bi3pics = true;
00563
00564 pc.addBool ( "UseGFXpics", bi3pics );
00565
00566 if ( bi3pics ) {
00567 pc.openBracket ( "GFXpictures");
00568 for ( int w = 0; w < cwettertypennum; w++ )
00569 if ( weatherBits.test(w) ) {
00570 pc.openBracket (weatherTags[w] );
00571
00572 for ( int c = 0; c < construction_steps; c++ ) {
00573 pc.openBracket ( ASCString("Stage")+strrr(c+1) );
00574
00575 for ( Fields::iterator i = fields.begin(); i != fields.end(); i++ )
00576 pc.addInteger ( i->toString(), bi_picture[w][c][i->x][i->y] );
00577
00578
00579 pc.closeBracket();
00580 }
00581 pc.closeBracket();
00582
00583 }
00584 pc.closeBracket();
00585 } else {
00586 pc.openBracket ( "Pictures");
00587 if ( !pc.isReading() ) {
00588 for ( int w = 0; w < cwettertypennum; w++ )
00589 if ( weatherBits.test(w) ) {
00590 Surface s = Surface::createSurface( construction_steps*500, 250, 32, 0 );
00591 for ( int c = 0; c < construction_steps; c++ )
00592 for ( int x = 0; x < 4; x++ )
00593 for ( int y = 0; y < 6; y++ )
00594 if ( w_picture[w][c][x][y].valid() )
00595 megaBlitter<ColorTransform_None,
00596 ColorMerger_AlphaOverwrite,
00597 SourcePixelSelector_Plain,
00598 TargetPixelSelector_All>
00599 ( w_picture[w][c][x][y],
00600 s,
00601 SPoint( 500*c + x * fielddistx + (y&1)*fielddisthalfx, y * fielddisty),
00602 nullParam, nullParam, nullParam, nullParam );
00603 ASCString file = extractFileName_withoutSuffix ( filename )+weatherAbbrev[w]+".png";
00604 pc.addImage ( weatherTags[w], s, file, false );
00605 pc.addString( ASCString(weatherTags[w]) + "_OriginalImageFilename", originalImageFilename[w] );
00606 }
00607 } else {
00608 for ( int w = 0; w < cwettertypennum; w++ )
00609 if ( weatherBits.test(w) ) {
00610 ASCString fileName = extractFileName_withoutSuffix ( filename )+weatherAbbrev[w]+".png";
00611 Surface s;
00612 pc.addImage ( weatherTags[w], s, fileName, false );
00613 originalImageFilename[w] = fileName;
00614
00615
00616
00617
00618 int depth = s.GetPixelFormat().BitsPerPixel();
00619 for ( int c = 0; c < construction_steps; c++ )
00620 for ( Fields::iterator i = fields.begin(); i != fields.end(); i++ ) {
00621 Surface& img = w_picture[w][c][i->x][i->y];
00622 img = Surface::createSurface(fieldsizex,fieldsizey,depth);
00623 int xx = 500*c + i->x * fielddistx + (i->y&1)*fielddisthalfx;
00624 int yy = i->y * fielddisty;
00625 if ( depth == 8 ) {
00626 img.Blit( s, SDLmm::SRect(SPoint(xx,yy),fieldsizex,fieldsizey), SPoint(0,0));
00627 applyFieldMask(img);
00628 } else {
00629 MegaBlitter<4,4,ColorTransform_None,ColorMerger_PlainOverwrite,SourcePixelSelector_Rectangle> blitter;
00630 blitter.setSrcRectangle( SDLmm::SRect(SPoint(xx,yy),fieldsizex,fieldsizey) );
00631 blitter.blit( s, img, SPoint(0,0) );
00632 applyFieldMask(img,0,0,false);
00633 }
00634 }
00635
00636 }
00637
00638 }
00639 pc.closeBracket();
00640 }
00641
00642 bool rubble = destructionObjects.size() > 0;
00643 pc.addBool ( "RubbleObjects", rubble );
00644 if ( rubble ) {
00645 if ( pc.isReading() )
00646 destructionObjects.clear();
00647
00648 pc.openBracket ( "Rubble");
00649 for ( Fields::iterator i = fields.begin(); i != fields.end(); i++ ) {
00650 vector<int> ids;
00651 typedef DestructionObjects::const_iterator J;
00652 pair<J,J> b = destructionObjects.equal_range(*i);
00653 for ( J j = b.first; j != b.second; ++j)
00654 ids.push_back(j->second);
00655 pc.addIntegerArray ( i->toString(), ids );
00656
00657 if ( pc.isReading() ) {
00658 for ( vector<int>::iterator j = ids.begin(); j != ids.end(); ++j )
00659 destructionObjects.insert(make_pair(*i, *j));
00660 }
00661 }
00662 pc.closeBracket();
00663 }
00664
00665
00666 ASCString entryString = entry.toString();
00667 pc.addString ( "Entry", entryString );
00668 if ( pc.isReading() ) {
00669 StringTokenizer st ( entryString );
00670 entry = LocalCoordinate ( st.getNextToken() );
00671 }
00672 if ( !fieldExists( entry ))
00673 pc.error( "Building " + name + " has invalid entrance position!" );
00674
00675 pc.addInteger( "Armor", _armor );
00676
00677 if ( pc.find( "Features" ) || !pc.isReading())
00678 pc.addTagArray ( "Features", features, functionNum, containerFunctionTags );
00679 else {
00680 int special = 0;
00681 pc.addTagInteger ( "Functions", special, cbuildingfunctionnum, buildingFunctionTags );
00682 convertOldFunctions( special, pc.getFileName() );
00683 }
00684 pc.addInteger ( "Techlevel", technologylevel );
00685
00686 pc.openBracket("TerrainAccess" );
00687 terrainaccess.runTextIO ( pc );
00688 pc.closeBracket();
00689
00690
00691 pc.openBracket ( "ConstructionCost" );
00692 productionCost.runTextIO ( pc );
00693 pc.closeBracket ();
00694
00695 pc.addTagInteger( "Height", height, choehenstufennum, heightTags );
00696
00697 pc.addTagInteger( "ExternalLoading", externalloadheight, choehenstufennum, heightTags );
00698
00699 pc.addBool ( "NotRemovable", buildingNotRemovable, false );
00700
00701 techDependency.runTextIO( pc, ASCString("b")+strrr(id) );
00702
00703 }
00704 catch ( InvalidString ) {
00705 pc.error ( "Could not parse building field coordinate");
00706 }
00707 }
00708
00709 void BuildingType::convertOldFunctions( int abilities, const ASCString& location )
00710 {
00711 features.reset();
00712 if ( abilities & 1 ) warningMessage ( location + ": The HQ function for buildings is not supported any more");
00713 if ( abilities & 2 ) features.set( TrainingCenter );
00714 if ( abilities & (1 << 3) ) features.set( InternalVehicleProduction );
00715 if ( abilities & (1 << 4) ) features.set( AmmoProduction );
00716 if ( abilities & (1 << 8) ) features.set( InternalUnitRepair );
00717 if ( abilities & (1 << 9) ) features.set( RecycleUnits );
00718 if ( abilities & (1 << 10) ) features.set( Research );
00719 if ( abilities & (1 << 11) ) features.set( Sonar );
00720 if ( abilities & (1 << 12) ) features.set( WindPowerPlant );
00721 if ( abilities & (1 << 13) ) features.set( SolarPowerPlant );
00722 if ( abilities & (1 << 14) ) features.set( MatterConverter );
00723 if ( abilities & (1 << 15) ) features.set( MiningStation );
00724 if ( abilities & (1 << 16) ) {
00725 features.set( ExternalMaterialTransfer );
00726 features.set( ExternalFuelTransfer );
00727 features.set( ExternalAmmoTransfer );
00728 }
00729 if ( abilities & (1 << 17) ) features.set( ProduceNonLeavableUnits );
00730 if ( abilities & (1 << 18) ) features.set( ResourceSink );
00731 if ( abilities & (1 << 19) ) {
00732 features.set( ExternalMaterialTransfer );
00733 features.set( ExternalFuelTransfer );
00734 }
00735 if ( abilities & (1 << 20) ) features.set( ExternalAmmoTransfer );
00736 if ( abilities & (1 << 21) ) features.set( NoObjectChaining );
00737 if ( abilities & (1 << 22) ) features.set( SelfDestructOnConquer );
00738 if ( abilities & (1 << 23) ) features.set( SatelliteView );
00739 }
00740