terraintype.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           terraintype.cpp  -  description
00003                              -------------------
00004     begin                : Fri Jul 27 2001
00005     copyright            : (C) 2001 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 // #include "basegfx.h"
00019 #include "terraintype.h"
00020 #include "gameoptions.h"
00021 #include "graphicset.h"
00022 #include "sgstream.h"
00023 #include "textfileparser.h"
00024 #include "textfiletags.h"
00025 #include "textfile_evaluation.h"
00026 #include "overviewmapimage.h"
00027 #include "graphics/blitter.h"
00028 #include "fieldimageloader.h"
00029 
00030 const char*  terrainProperty[terrainPropertyNum+1]  = {"shallow water"       ,  // 0
00031                                              "normal lowland",
00032                                              "swamp",
00033                                              "forest",
00034                                              "high mountains",                  // 4
00035                                              "road",
00036                                              "railroad",
00037                                              "entry of building (not to be used for terrain)" ,
00038                                              "harbour",
00039                                              "runway"  ,
00040                                              "pipeline",                        // 10
00041                                              "buried pipeline",
00042                                              "water",
00043                                              "deep water",
00044                                              "hard sand",
00045                                              "soft sand",
00046                                              "track possible",
00047                                              "small rocks",
00048                                              "mud",
00049                                              "snow",
00050                                              "deep snow",
00051                                              "mountains",
00052                                              "very shallow water",
00053                                              "large rocks",
00054                                              "lava",
00055                                              "ditch",
00056                                              "hillside",
00057                                              "turret foundation",
00058                                              "morass",
00059                                              "Installation",
00060                                              "pack ice",
00061                                              "river",
00062                                              "frozen water",
00063                                              "bridge",
00064                                              "lava barrier",
00065                                              "spaceport",
00066                                              "beacon",
00067                                              "fire",
00068                                              NULL };
00069 
00070 
00071 
00072 
00073 void TerrainAccess::read ( tnstream& stream ) {
00074    terrain.read ( stream );
00075    terrain.reset( 7 );
00076    terrainreq.read ( stream );
00077    terrainnot.read ( stream );
00078    terrainnot.reset( 7 );
00079    terrainkill.read ( stream );
00080 
00081    for ( int a = 0; a < 10; a++ )
00082        stream.readInt( ); //dummy
00083 };
00084 
00085 void TerrainAccess::write ( tnstream& stream ) const {
00086    terrain.write ( stream );
00087    terrainreq.write ( stream );
00088    terrainnot.write ( stream );
00089    terrainkill.write ( stream );
00090 
00091    for ( int a = 0; a < 10; a++ )
00092        stream.writeInt( 0 ); //dummy
00093 };
00094 
00095 void TerrainAccess::runTextIO ( PropertyContainer& pc )
00096 {
00097    pc.addTagArray ( "terrain_any", terrain, terrainPropertyNum, terrainProperties );
00098    pc.addTagArray ( "terrain_all", terrainreq, terrainPropertyNum, terrainProperties );
00099    pc.addTagArray ( "terrain_not", terrainnot, terrainPropertyNum, terrainProperties );
00100    pc.addTagArray ( "terrain_kill", terrainkill, terrainPropertyNum, terrainProperties );
00101 }
00102 
00103 void TerrainBits::appendToString( ASCString& text ) const
00104 {
00105    for (int i = 0; i < terrainPropertyNum ; i++) {
00106       TerrainBits bts;
00107       bts.set ( i );
00108 
00109       if ( (*this & bts).any() ) {
00110          text += "- " ;
00111          text += terrainProperty[i];
00112          text += "\n";
00113       }
00114    } /* endfor */
00115 }
00116 
00117 
00118 
00119 
00120 TerrainType::MoveMalus::MoveMalus()
00121 {
00122    resize( cmovemalitypenum);
00123    for ( int i = 0; i <  cmovemalitypenum; i++ )
00124       at(i) = 100;
00125 }
00126 
00127 TerrainType::TerrainType()
00128 {
00129    id = -1;
00130    for ( int i = 0; i < cwettertypennum; i++ )
00131       weather[i] = NULL;
00132 
00133 }
00134 
00135 
00136 void      TerrainType::Weather::paint ( Surface& s, SPoint pos )
00137 {
00138    Surface* img;
00139    if ( bi_pict == -1 )
00140       img = &image;
00141    else 
00142       img = &GraphicSetManager::Instance().getPic( bi_pict);
00143 
00144    megaBlitter<ColorTransform_None, 
00145                ColorMerger_AlphaOverwrite, 
00146                SourcePixelSelector_Plain,
00147                TargetPixelSelector_All>
00148             (*img,s,pos,nullParam,nullParam,nullParam,nullParam);
00149 }
00150 
00151 
00152 const OverviewMapImage* TerrainType::Weather::getQuickView()
00153 {
00154    if  ( bi_pict >= 0 ) {
00155       return GraphicSetManager::Instance().getQuickView( bi_pict );
00156    } else {
00157       if (!quickView ) {
00158          quickView = new OverviewMapImage( image );
00159       }
00160       return quickView;
00161    }
00162 }
00163 
00164 TerrainType::Weather::~Weather()
00165 { 
00166    delete quickView; 
00167 }
00168 
00169 
00170 const int terrain_version = 6;
00171 
00172 
00173 void TerrainType::MoveMalus::read( tnstream& stream, int defaultValue, int moveMalusCount )
00174 {
00175    clear();
00176 
00177    int version;
00178    if ( moveMalusCount <= 0 ) {
00179       version = stream.readInt();
00180       moveMalusCount = stream.readInt();
00181    } else
00182       version = 0;
00183 
00184    #ifndef converter
00185     int mmcount = moveMalusCount;
00186     if (mmcount < moveMalusCount )
00187        mmcount = moveMalusCount;
00188    #else
00189     int mmcount = moveMalusCount ;
00190    #endif
00191 
00192    for ( int j=0; j< mmcount ; j++ ) {
00193       if (j < moveMalusCount ) {
00194          int i;
00195          if ( version < 2 )
00196             i = stream.readChar();
00197          else
00198             i = stream.readInt();
00199          push_back ( i );
00200       } else
00201          if ( j == 0 )
00202             push_back ( defaultValue );
00203          else
00204             push_back ( at(0) );
00205    }
00206 }
00207 
00208 void TerrainType::MoveMalus::write ( tnstream& stream ) const
00209 {
00210   stream.writeInt(2);
00211   stream.writeInt( size() );
00212   for ( int m = 0; m < size(); m++ )
00213      stream.writeInt ( at(m) );
00214 }
00215 
00216 void TerrainType::Weather::read ( tnstream& stream )
00217 {
00218    read( stream, terrain_version );
00219 }
00220 
00221 
00222 void TerrainType::Weather::read ( tnstream& stream, int version )
00223 {
00224    bool loadImage = true;
00225    if (version <=2 ) {
00226       loadImage = stream.readInt();
00227 
00228       for ( int j = 1; j < 8; j++ )
00229          stream.readInt(); // pgbt->picture[j]
00230 
00231       for ( int j = 0; j < 8; j++ )
00232          stream.readInt(); // pgbt->direcpict[j] = (void*)
00233    }
00234 
00235    if ( version == 1 ) {
00236       stream.readInt(); //dummy1
00237       defensebonus = stream.readWord();
00238       attackbonus = stream.readWord();
00239       basicjamming = stream.readChar();
00240    } else {
00241       defensebonus = stream.readInt();
00242       attackbonus = stream.readInt();
00243       basicjamming = stream.readInt();
00244    }
00245    int move_maluscount = stream.readChar();
00246    stream.readInt(); // pgbt->movemalus = (char*)
00247    stream.readInt(); // pgbt->terraintype
00248    stream.readInt(); // bool readQuickView
00249 
00250    art.read ( stream );
00251 
00252    bi_pict = stream.readInt();
00253    for ( int j = 1; j < 6; j++ )
00254       stream.readInt(); //pgbt->bi_picture[j] =
00255 
00256    move_malus.read( stream, minmalq, move_maluscount );
00257 
00258    if ( version >= 5 )
00259       originalImageFilename = stream.readString();
00260    
00261 /*
00262    for ( j=0; j<8 ;j++ )
00263       if ( pgbt->picture[j] )
00264          if ( pgbt->bi_picture[j] == -1 ) {
00265             pgbt->picture[j] = asc_malloc ( fieldsize );
00266             stream.readdata ( pgbt->picture[j], fieldsize );
00267             } else
00268                loadbi3pict_double ( pgbt->bi_picture[j],
00269                                     &pgbt->picture[j],
00270                                     CGameOptions::Instance()->bi3.interpolate.terrain );
00271 
00272 */
00273    if ( loadImage )
00274       if ( bi_pict == -1 )
00275          image.read ( stream );
00276 }
00277 
00278 void TerrainType::Weather::write ( tnstream& stream ) const
00279 {
00280    stream.writeInt ( defensebonus );
00281    stream.writeInt ( attackbonus );
00282    stream.writeInt ( basicjamming );
00283    stream.writeChar ( 0 ); // was: movemalus count
00284    stream.writeInt ( 1 );
00285    stream.writeInt ( 1 );
00286    stream.writeInt ( 0); // was: quickview
00287    art.write ( stream );
00288 
00289 
00290    stream.writeInt ( bi_pict );
00291    for ( int m = 1; m< 6; m++ )
00292       stream.writeInt ( -1 );
00293 
00294    move_malus.write ( stream );
00295 
00296    stream.writeString( originalImageFilename );
00297    
00298    if ( bi_pict == -1 )
00299       image.write ( stream );
00300 }
00301 
00302 
00303 void TerrainType::read( tnstream& stream )
00304 {
00305    int version = stream.readInt();
00306    if ( version > terrain_version || (version < 5 && version !=1) ) 
00307       throw tinvalidversion ( stream.getDeviceName(), terrain_version, version );
00308       
00309    stream.readInt(); 
00310    id   = stream.readInt();
00311 
00312    bool ___loadWeather[cwettertypennum];
00313    for ( int ww = 0; ww < cwettertypennum; ww++ )
00314       ___loadWeather[ww] = stream.readInt();
00315 
00316    for ( int nf = 0; nf < 8; nf++ )
00317       stream.readInt(); // neighbouringfield[nf]
00318 
00319    name = stream.readString();
00320 
00321    for ( int i=0; i<cwettertypennum ;i++ ) {
00322       if ( ___loadWeather[i] ) {
00323          weather[i] = new TerrainType::Weather ( this );
00324          weather[i]->read( stream, version );
00325       } else
00326          weather[i] = NULL;
00327 
00328    } /* endfor */
00329 
00330    if ( version >= 6 )
00331       readClassContainer( secondaryIDs, stream );
00332 }
00333 
00334 
00335 void TerrainType::write ( tnstream& stream ) const
00336 {
00337    stream.writeInt ( terrain_version );
00338    stream.writeInt ( !name.empty() );
00339    stream.writeInt ( id );
00340    for ( int m = 0; m < cwettertypennum; m++ )
00341       stream.writeInt ( weather[m] != NULL );
00342 
00343    for ( int m = 0; m < 8; m++ )
00344       stream.writeInt ( 0 ); // bbt->neighbouringfield[nf]
00345 
00346    stream.writeString( name );
00347    for ( int i = 0; i < cwettertypennum ; i++ ) 
00348       if ( weather[i] ) 
00349          weather[i]->write( stream );
00350 
00351    writeClassContainer( secondaryIDs, stream );
00352 
00353    /*
00354    stream.writeString(filename);
00355    stream.writeString(location);
00356    */
00357 }
00358 
00359 
00360 int TerrainType::getMemoryFootprint() const
00361 {
00362    int size = sizeof(*this);
00363    
00364    for ( int w = 0; w < cwettertypennum; ++w )
00365       if ( weather[w] ) 
00366          size += weather[w]->getMemoryFootprint();
00367       
00368    return size;
00369 }
00370 
00371 int TerrainType::Weather::getMemoryFootprint() const
00372 {
00373    int size = sizeof(*this);
00374    size += image.getMemoryFootprint();
00375    if ( quickView )
00376       size += quickView->getMemoryFootprint();
00377    return size;
00378 }
00379 
00380 
00381 TerrainType::~TerrainType()
00382 {
00383    for ( int i = 0; i< cwettertypennum; ++i) {
00384       delete weather[i];
00385       weather[i] = NULL;
00386    }
00387 }
00388 
00389 
00390 TerrainAccess :: TerrainAccess ( void )
00391 {
00392    terrain.flip();
00393 }
00394 
00395 int TerrainAccess :: accessible ( const TerrainBits& bts ) const
00396 {
00397    if (     (terrain & bts).any()
00398          && (terrainreq & bts) == terrainreq
00399          && (terrainnot & bts ).none()
00400       ) return 1;
00401    else
00402       if ( (terrainkill & bts).any() )
00403          return -1;
00404       else
00405          return 0;
00406 }
00407 
00408 
00409 void TerrainBits::setInt ( int terrain1, int terrain2 )
00410 {
00411    reset();
00412    for ( int i = 0; i < 32; i++ )
00413       if ( terrain1 & ( 1 << i ))
00414          set(i);
00415 
00416    for ( int i = 0; i < 32; i++ )
00417       if ( terrain2 & ( 1 << i ))
00418          set(32+i);
00419 }
00420 
00421 void TerrainBits::read ( tnstream& stream )
00422 {
00423      int terrain1 = stream.readInt();
00424      int terrain2 = stream.readInt();
00425      setInt ( terrain1, terrain2 );
00426   };
00427 
00428 void TerrainBits::write ( tnstream& stream ) const
00429 {
00430      int terrain1 = 0;
00431      int terrain2 = 0;
00432      for ( int i = 0; i < 32; i++ )
00433         if ( test(i) )
00434            terrain1 |=   1 << i ;
00435 
00436      for ( int i = 0; i < 32; i++ )
00437         if ( test(32+i) )
00438            terrain2 |=   1 << i ;
00439 
00440      stream.writeInt( terrain1 );
00441      stream.writeInt( terrain2 );
00442 }
00443 
00444 
00445 
00446 
00447 void TerrainType :: runTextIO ( PropertyContainer& pc )
00448 {
00449    pc.addBreakpoint(); 
00450   
00451    
00452    BitSet weatherBits;
00453    for ( int i = 0; i < cwettertypennum; i++ )
00454       if ( weather[i] )
00455          weatherBits.set(i);
00456 
00457    pc.addString( "Name", name );
00458    pc.addInteger( "ID", id );
00459 
00460    if ( pc.find( "SecondaryIDs") || !pc.isReading())
00461       pc.addIntegerArray("SecondaryIDs", secondaryIDs );
00462 
00463 
00464    pc.addTagArray( "Weather", weatherBits, cwettertypennum, weatherTags );
00465 
00466    for ( int i = 0; i < cwettertypennum; i++ )
00467       if ( weatherBits.test(i) ) {
00468 
00469          if ( pc.isReading() )
00470             weather[i] = new TerrainType::Weather ( this );
00471 
00472          pc.openBracket  ( weatherTags[i] );
00473          weather[i]->runTextIO ( pc );
00474          pc.closeBracket (  );
00475       }
00476 
00477 }
00478 
00479 void TerrainType::Weather::runTextIO ( PropertyContainer& pc )
00480 {
00481    bool bi3pics = false;
00482 
00483    if ( !pc.isReading() )
00484       if ( bi_pict >= 0 )
00485          bi3pics = true;
00486 
00487    pc.addBool  ( "UseGFXpics", bi3pics, false );
00488    if ( !bi3pics ) {
00489       bi_pict = -1;
00490       int w = cwettertypennum-1;
00491       for ( int i = 0; i < cwettertypennum-1; i++ )
00492          if ( terraintype->weather[i] == this )
00493             w = i;
00494 
00495       ASCString s = extractFileName_withoutSuffix ( terraintype->filename );
00496       if ( s.empty() ) {
00497          s = "terrain";
00498          s += strrr(terraintype->id);
00499       }
00500       s += weatherAbbrev[w];
00501       pc.addImage ( "picture", image, s, true );
00502       
00503       if ( pc.isReading() ) {
00504          originalImageFilename = s;
00505       } else {
00506          pc.addString( "OriginalImageFilename", originalImageFilename );
00507       }
00508       
00509       // applyFieldMask( image );
00510 
00511       if ( pc.isReading() ) {
00512          int operations;
00513          pc.addNamedInteger("GraphicOperations", operations, graphicOperationNum, graphicOperations, 0 );
00514          if ( operations == 1 )  
00515             snowify( image );
00516          else
00517             if ( operations == 2 )
00518                snowify( image, false );
00519       }
00520 
00521    } else {
00522       pc.addInteger ( "GFX_Picture", bi_pict );
00523       if  ( bi_pict < 0 )
00524          fatalError ( "invalid BI-image " );
00525    }
00526    
00527    pc.addInteger ( "DefenseBonus", defensebonus, 0 );
00528    pc.addInteger ( "AttackBonus",  attackbonus, 0 );
00529    pc.addInteger ( "BasicJamming", basicjamming, 0 );
00530    pc.addDFloatArray ( "MoveMalus", move_malus );
00531    while ( move_malus.size() < cmovemalitypenum ) 
00532      if ( move_malus.size() == 0 )
00533         move_malus.push_back ( minmalq );
00534      else
00535         move_malus.push_back ( move_malus[0] );
00536 
00537 
00538    pc.addTagArray ( "TerrainProperties", art, terrainPropertyNum, terrainProperties );
00539 }
00540 
00541 
00542 
00543 
00544 TerrainBits getTerrainBitType ( TerrainBitTypes tbt )
00545 {
00546    TerrainBits tb;
00547    switch ( tbt ) {
00548       case cbwater0 : tb.setInt( 1<<22 ); break;
00549       case cbwater1 : tb.setInt( 1 );   break;
00550       case cbwater2 : tb.setInt( 4096 ); break;
00551       case cbwater3 : tb.setInt( 8192 ); break;
00552       case cbwater  : tb.setInt (  (1<<22)  // very shallow water
00553                                  | (1<< 0)  // shallow water
00554                                  | (1<<12)  // water
00555                                  | (1<<13)  // deep water
00556                                  | (1<<31)  // river
00557                                  ); break;
00558       case cbstreet : tb.setInt ( 32, 0 ); break;
00559       case cbrailroad : tb.setInt ( 64, 0 ); break;
00560       case cbbuildingentry : tb.setInt ( 128, 0 ); break;
00561       case cbharbour     : tb.setInt ( 256, 0 ); break;
00562       case cbrunway      : tb.setInt ( 512, 0 ); break;
00563       case cbpipeline    : tb.setInt ( 1024, 0 ); break;
00564       case cbpowerline   : tb.setInt ( 2048, 0 ); break;
00565       case cbfahrspur    : tb.setInt ( 1<<16, 0 ); break;
00566       case cbfestland    : tb.flip(); tb ^= getTerrainBitType( cbwater ); break;
00567       case cbsnow1       : tb.setInt ( 1<<19, 0 ); break;
00568       case cbsnow2       : tb.setInt ( 1<<20, 0 ); break;
00569       case cbhillside    : tb.setInt ( 1<<26, 0 ); break;
00570       case cbsmallrocks  : tb.setInt ( 1<<17, 0 ); break;
00571       case cblargerocks  : tb.setInt ( 1<<23, 0 ); break;
00572       case cbfrozenwater : tb.setInt ( 0, 1 ); break;
00573       case cbicebreaking : tb |= getTerrainBitType( cbfrozenwater )
00574                               | getTerrainBitType( cbsnow1 )
00575                               | getTerrainBitType(cbsnow2 );
00576       case cbriver       : tb.setInt(  1 << 31, 0 ); break;
00577 
00578    };
00579    return tb;
00580 }
00581 
00582 
00583 ASCString TerrainAccess :: toString( bool brief ) const
00584 {
00585    ASCString text;
00586 
00587    text += "Terrain properties of which one must be available:\n" ;
00588    terrain.appendToString( text );
00589 
00590    if ( !( brief && terrainreq.none() )) {
00591       text += "\n\nTerrain properties that must all be set:\n" ;
00592       terrainreq.appendToString( text );
00593    }
00594 
00595    if ( !( brief && terrainnot.none() )) {
00596       text += "\n\nTerrain properties that must not be set:\n" ;
00597       terrainnot.appendToString( text );
00598    }
00599 
00600    if ( !( brief && terrainkill.none() )) {
00601       text += "\n\nTerrain properties that are fatal:\n" ;
00602       terrainkill.appendToString( text );
00603    }
00604 
00605    return text;
00606 }

Generated on Mon May 21 01:26:38 2012 for Advanced Strategic Command by  doxygen 1.5.1