00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "containerbasetype.h"
00019 #include "textfiletags.h"
00020 #include "textfile_evaluation.h"
00021 #include "vehicletype.h"
00022 #include "graphics/blitter.h"
00023
00024
00025 const char* ccontainerfunctions[ContainerBaseType::functionNum+1] =
00026 { "training",
00027 "internal vehicle production",
00028 "ammunition production",
00029 "internal unit repair",
00030 "recycling",
00031 "research",
00032 "sonar",
00033 "view satellites",
00034 "view mines",
00035 "wind power plant",
00036 "solar power plant",
00037 "matter converter",
00038 "mining station",
00039 "construct units that cannot move out",
00040 "resource sink",
00041 "external energy transfer",
00042 "external material transfer",
00043 "external fuel transfer",
00044 "external ammo transfer",
00045 "external repair",
00046 "no object chaining",
00047 "self destruct on conquer",
00048 "paratrooper",
00049 "mine-layer",
00050 "cruiser landing",
00051 "conquer buildings",
00052 "move after attack",
00053 "external vehicle production",
00054 "construct specific buildings",
00055 "icebreaker",
00056 "cannot be refuelled in air",
00057 "makes tracks",
00058 "search for mineral resources automatically",
00059 "no reactionfire",
00060 "auto repair",
00061 "Kamikaze only",
00062 "immune to mines",
00063 "jams only own field",
00064 "move with reaction fire on",
00065 "only move to and from transports",
00066 "AutoHarvestObjects",
00067 "No customization of production",
00068 "Manual self-destruct",
00069 "No removal of mines",
00070 NULL };
00071
00072
00073 ContainerBaseType :: ContainerBaseType ()
00074 {
00075 maxLoadableUnits = 0;
00076 maxLoadableUnitSize = 0;
00077 maxLoadableWeight = maxint;
00078 vehicleCategoriesStorable = -1;
00079 id = 0;
00080 jamming = 0;
00081 view = 0;
00082 efficiencyfuel = 1024;
00083 efficiencymaterial = 1024;
00084
00085 maxresearchpoints = 0;
00086 defaultMaxResearchpoints = 0;
00087 nominalresearchpoints = 0;
00088 vehicleCategoriesProduceable = 0xfffffff;
00089 autoHarvest.range = 0;
00090 autoHarvest.maxFieldsPerTurn = maxint;
00091 minFieldRepairDamage = 0;
00092 }
00093
00094 bool ContainerBaseType::hasFunction( ContainerFunctions function ) const
00095 {
00096 int f = int(function);
00097 return features.test( f );
00098 }
00099
00100 bool ContainerBaseType::hasAnyFunction( BitSet functions ) const
00101 {
00102 bool result = (features & functions).any();
00103 return result;
00104 }
00105
00106 void ContainerBaseType::setFunction( ContainerFunctions function )
00107 {
00108 features.set( int(function) );
00109 }
00110
00111
00112
00113
00114 const char* ContainerBaseType::getFunctionName( ContainerFunctions function )
00115 {
00116 if ( function < functionNum )
00117 return ccontainerfunctions[function];
00118 else
00119 return NULL;
00120 }
00121
00122
00123 ContainerBaseType::TransportationIO::TransportationIO()
00124 {
00125 mode = 0;
00126 height_abs = 0;
00127 height_rel = 0;
00128 container_height = 0;
00129 vehicleCategoriesLoadable = -1;
00130 dockingHeight_abs = 0;
00131 dockingHeight_rel = 0;
00132 disableAttack = false;
00133 movecost = -1;
00134 }
00135
00136
00137 void ContainerBaseType :: TransportationIO :: runTextIO ( PropertyContainer& pc )
00138 {
00139 pc.addTagInteger( "Mode", mode, entranceModeNum, entranceModes );
00140 pc.addTagInteger( "UnitHeightAbs", height_abs, choehenstufennum, heightTags );
00141 pc.addInteger( "UnitHeightRel", height_rel, -100 );
00142 pc.addTagInteger( "ContainerHeight", container_height, choehenstufennum, heightTags );
00143 pc.addTagInteger( "CategoriesNOT", vehicleCategoriesLoadable, cmovemalitypenum, unitCategoryTags, true );
00144 pc.addTagInteger( "DockingHeightAbs", dockingHeight_abs, choehenstufennum, heightTags, 0 );
00145 pc.addInteger( "DockingHeightRel", dockingHeight_rel, -100 );
00146 if ( pc.find( "RequireUnitFunction" )) {
00147 int r = 0;
00148 pc.addTagInteger( "RequireUnitFunction", r, VehicleType::legacyVehicleFunctionNum, vehicleAbilities, 0 );
00149 requiresUnitFeature = VehicleType::convertOldFunctions(r, pc.getFileName() );
00150 } else
00151 if ( pc.find( "RequiresUnitFeature" ) || !pc.isReading() )
00152 pc.addTagArray( "RequiresUnitFeature", requiresUnitFeature, ContainerBaseType::functionNum, containerFunctionTags );
00153 else
00154 requiresUnitFeature.reset();
00155
00156 pc.addBool( "DisableAttack", disableAttack, false );
00157 pc.addInteger( "MoveCost", movecost, -1 );
00158 if ( movecost < 10 && movecost >= 0 )
00159 fatalError ( "MoveCost for TransportationIO is lower than 10! file: " + pc.getFileName() );
00160 }
00161
00162
00163 void ContainerBaseType :: runTextIO ( PropertyContainer& pc )
00164 {
00165 pc.addBreakpoint();
00166 pc.openBracket ( "Transportation" );
00167 int num = entranceSystems.size();
00168 pc.addInteger ( "EntranceSystemNum", num, 0 );
00169 entranceSystems.resize(num);
00170 for ( int i = 0; i < num; i++ ) {
00171 pc.openBracket ( ASCString("EntranceSystem") + strrr(i) );
00172 entranceSystems[i].runTextIO( pc );
00173 pc.closeBracket();
00174 }
00175 pc.addInteger ( "MaxLoadableUnits", maxLoadableUnits, 0 );
00176
00177 pc.addInteger ( "MaxLoadableUnitSize", maxLoadableUnitSize, maxint );
00178 pc.addInteger ( "MaxLoadableMass", maxLoadableWeight, maxint );
00179 pc.addTagInteger( "CategoriesNOT", vehicleCategoriesStorable, cmovemalitypenum, unitCategoryTags, -1, true );
00180 pc.closeBracket();
00181
00182 pc.addString( "Name", name );
00183 pc.addString( "Description", description, "" );
00184 pc.addString( "Infotext", infotext, "" );
00185
00186 while ( infotext.find ( "#CRT#" ) != ASCString::npos )
00187 infotext.replace ( infotext.find ( "#CRT#" ), 5, "\n" );
00188 while ( infotext.find ( "#crt#" ) != ASCString::npos )
00189 infotext.replace ( infotext.find ( "#crt#" ), 5, "\n" );
00190 while ( infotext.find ( "\r" ) != ASCString::npos )
00191 infotext.replace ( infotext.find ( "\r" ), 1, "" );
00192
00193 pc.addInteger( "ID", id );
00194
00195 if ( pc.find( "SecondaryIDs") || !pc.isReading())
00196 pc.addIntegerArray("SecondaryIDs", secondaryIDs );
00197
00198 pc.addInteger( "View", view );
00199 if ( view > maxViewRange )
00200 view = maxViewRange;
00201
00202 pc.addInteger( "Jamming", jamming, 0 );
00203 pc.addString( "InfoImage", infoImageFilename, "" );
00204 pc.addString( "InfoImageSmall", infoImageSmallFilename, "" );
00205
00206 pc.openBracket ( "MaxResourceProduction" );
00207 maxplus.runTextIO ( pc, Resources(0,0,0) );
00208 pc.closeBracket ();
00209
00210 pc.openBracket ( "ResourceExtractionEfficiency");
00211 pc.addInteger( "Material", efficiencymaterial, 1024 );
00212 pc.addInteger( "Fuel", efficiencyfuel, 1024 );
00213 pc.closeBracket ();
00214
00215 pc.openBracket ( "StorageCapacity" );
00216 pc.openBracket( "BImode" );
00217 bi_mode_tank.runTextIO ( pc, Resources(0,0,0) );
00218 pc.closeBracket();
00219 pc.openBracket ( "ASCmode" );
00220 asc_mode_tank.runTextIO ( pc, Resources(0,0,0) );
00221 pc.closeBracket();
00222 pc.closeBracket ();
00223
00224 pc.addInteger ( "MaxResearch", maxresearchpoints, 0 );
00225 pc.addInteger ( "NominalResearch", nominalresearchpoints, maxresearchpoints/2 );
00226 pc.addInteger ( "MaxResearchpointsDefault", defaultMaxResearchpoints, maxresearchpoints );
00227
00228 pc.openBracket( "DefaultProduction" );
00229 defaultProduction.runTextIO ( pc, Resources(0,0,0) );
00230 pc.closeBracket();
00231
00232 pc.addTagInteger( "CategoriesProduceable", vehicleCategoriesProduceable, cmovemalitypenum, unitCategoryTags, -1 );
00233
00234 pc.openBracket( "AutoHarvestObjects" );
00235 pc.addIntRangeArray( "objects", autoHarvest.objectsHarvestable, false );
00236 pc.addIntRangeArray( "objectGroups", autoHarvest.objectGroupsHarvestable, false );
00237 pc.addInteger( "Range", autoHarvest.range, 0 );
00238 pc.addInteger( "MaxFieldsPerTurn", autoHarvest.maxFieldsPerTurn, maxint);
00239 pc.closeBracket();
00240
00241
00242 pc.openBracket ( "Construction" );
00243 pc.addIntRangeArray ( "VehiclesInternally", vehiclesInternallyProduceable, false );
00244 productionEfficiency.runTextIO("ProductionEfficiency", pc, productionEfficiency );
00245 pc.closeBracket();
00246
00247 pc.addInteger("minFieldRepairDamage", minFieldRepairDamage , 0 );
00248 }
00249
00250
00251 bool ContainerBaseType :: vehicleFit ( const VehicleType* fzt ) const
00252 {
00253 if ( maxLoadableUnits > 0 )
00254 if ( maxLoadableWeight > 0 )
00255 if ( vehicleCategoriesStorable & (1<<fzt->movemalustyp) )
00256 if ( maxLoadableUnitSize >= fzt->maxsize() )
00257 return true;
00258
00259 return false;
00260 }
00261
00262 int ContainerBaseType :: vehicleUnloadable ( const VehicleType* vehicleType, int carrierHeight ) const
00263 {
00264 int height = 0;
00265
00266 int carrierBinHeight = 1 << carrierHeight;
00267
00268 if ( vehicleFit ( vehicleType ))
00269 for ( ContainerBaseType::EntranceSystems::const_iterator i = entranceSystems.begin(); i != entranceSystems.end(); i++ )
00270 if ( i->mode & ContainerBaseType::TransportationIO::Out )
00271 if ( (i->container_height & carrierBinHeight) || (i->container_height == 0))
00272 if ( i->vehicleCategoriesLoadable & (1<<vehicleType->movemalustyp))
00273 if ( vehicleType->hasAnyFunction(i->requiresUnitFeature) || i->requiresUnitFeature.none() ) {
00274 if ( i->height_abs != 0 && i->height_rel != -100 ) {
00275 int h = 0;
00276 for ( int hh = 0; hh < 8; ++hh)
00277 if ( getheightdelta(carrierHeight, hh) == i->height_rel )
00278 h += 1 << hh;
00279 height |= i->height_abs & h;
00280 } else
00281 if ( i->height_rel != -100 )
00282 height |= 1 << (carrierHeight + i->height_rel) ;
00283 else
00284 height |= i->height_abs ;
00285 }
00286 return height & vehicleType->height;
00287 }
00288
00289
00290 const int containerBaseTypeVersion = 8;
00291
00292
00293 void ContainerBaseType :: read ( tnstream& stream )
00294 {
00295 int version = stream.readInt();
00296 if ( version > containerBaseTypeVersion || version < 1 ) {
00297 ASCString s = "invalid version for reading ContainerBaseType: ";
00298 s += strrr ( version );
00299 throw ASCmsgException ( s );
00300 }
00301 maxLoadableUnits = stream.readInt();
00302 maxLoadableUnitSize = stream.readInt();
00303 maxLoadableWeight = stream.readInt();
00304 vehicleCategoriesStorable = stream.readInt();
00305 int num = stream.readInt();
00306 entranceSystems.resize(num);
00307 for ( int i = 0; i < num; i++ )
00308 entranceSystems[i].read( stream );
00309
00310 if ( version >= 2 )
00311 infoImageFilename = stream.readString();
00312
00313 if ( version >= 3 )
00314 stream.readBitset( features );
00315
00316 if ( version >= 4 )
00317 vehicleCategoriesProduceable = stream.readInt();
00318
00319 if ( version >= 5 )
00320 readClassContainer( secondaryIDs, stream );
00321
00322 if ( version >= 6 ) {
00323 autoHarvest.range = stream.readInt();
00324 readClassContainer( autoHarvest.objectsHarvestable, stream );
00325 readClassContainer( autoHarvest.objectGroupsHarvestable, stream );
00326 autoHarvest.maxFieldsPerTurn = stream.readInt();
00327
00328 readClassContainer( vehiclesInternallyProduceable, stream );
00329 productionEfficiency.read( stream );
00330 }
00331 if ( version >= 7 )
00332 infoImageSmallFilename = stream.readString();
00333
00334 if ( version >= 8 )
00335 minFieldRepairDamage = stream.readInt();
00336 else
00337 minFieldRepairDamage = 0;
00338 }
00339
00340 void ContainerBaseType :: write ( tnstream& stream ) const
00341 {
00342 stream.writeInt( containerBaseTypeVersion );
00343 stream.writeInt( maxLoadableUnits );
00344 stream.writeInt( maxLoadableUnitSize );
00345 stream.writeInt( maxLoadableWeight );
00346 stream.writeInt( vehicleCategoriesStorable );
00347 stream.writeInt( entranceSystems.size() );
00348 for ( int i = 0; i < entranceSystems.size(); i++ )
00349 entranceSystems[i].write( stream );
00350 stream.writeString( infoImageFilename );
00351 stream.writeBitset( features );
00352 stream.writeInt( vehicleCategoriesProduceable );
00353 writeClassContainer( secondaryIDs, stream );
00354
00355 stream.writeInt( autoHarvest.range );
00356 writeClassContainer( autoHarvest.objectsHarvestable, stream );
00357 writeClassContainer( autoHarvest.objectGroupsHarvestable, stream );
00358 stream.writeInt( autoHarvest.maxFieldsPerTurn );
00359
00360 writeClassContainer( vehiclesInternallyProduceable, stream );
00361 productionEfficiency.write( stream );
00362 stream.writeString( infoImageSmallFilename );
00363 stream.writeInt( minFieldRepairDamage );
00364 }
00365
00366 const int containerBaseTypeTransportVersion = 3;
00367
00368
00369 void ContainerBaseType :: TransportationIO :: read ( tnstream& stream )
00370 {
00371 int version = stream.readInt();
00372 if ( version > containerBaseTypeTransportVersion || version < 1 ) {
00373 ASCString s = "invalid version for reading ContainerBaseTypeTransportation: ";
00374 s += strrr ( version );
00375 throw ASCmsgException ( s );
00376 }
00377 mode = stream.readInt();
00378 height_abs = stream.readInt();
00379 height_rel = stream.readInt();
00380 container_height = stream.readInt();
00381 vehicleCategoriesLoadable = stream.readInt();
00382 dockingHeight_abs = stream.readInt();
00383 dockingHeight_rel = stream.readInt();
00384 if ( version <= 2 ) {
00385 int r = stream.readInt();
00386 requiresUnitFeature = VehicleType::convertOldFunctions(r, stream.getLocation());
00387 } else
00388 stream.readBitset( requiresUnitFeature );
00389
00390 disableAttack = stream.readInt();
00391 if ( version >= 2 )
00392 movecost = stream.readInt();
00393 else
00394 movecost = -1;
00395
00396 }
00397
00398 void ContainerBaseType :: TransportationIO :: write ( tnstream& stream ) const
00399 {
00400 stream.writeInt ( containerBaseTypeTransportVersion );
00401 stream.writeInt ( mode );
00402 stream.writeInt ( height_abs );
00403 stream.writeInt ( height_rel );
00404 stream.writeInt ( container_height );
00405 stream.writeInt ( vehicleCategoriesLoadable );
00406 stream.writeInt ( dockingHeight_abs );
00407 stream.writeInt ( dockingHeight_rel );
00408 stream.writeBitset ( requiresUnitFeature );
00409 stream.writeInt ( disableAttack );
00410 stream.writeInt ( movecost );
00411 }
00412
00413
00414 Resources ContainerBaseType::getStorageCapacity( int mode ) const
00415 {
00416 if ( mode == 1 )
00417 return bi_mode_tank;
00418 else
00419 return asc_mode_tank;
00420 }
00421
00422