Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

vehicletype.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           vehicletype.cpp  -  description
00003                              -------------------
00004     begin                : Fri Sep 29 2000
00005     copyright            : (C) 2000 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00014 /***************************************************************************
00015  *                                                                         *
00016  *   This program is free software; you can redistribute it and/or modify  *
00017  *   it under the terms of the GNU General Public License as published by  *
00018  *   the Free Software Foundation; either version 2 of the License, or     *
00019  *   (at your option) any later version.                                   *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 #include <algorithm>
00024 #include "global.h"
00025 #include "vehicletype.h"
00026 #include "sgstream.h"
00027 #include "graphicset.h"
00028 #include "terraintype.h"
00029 #include "objecttype.h"
00030 #include "textfileparser.h"
00031 #include "textfiletags.h"
00032 #include "textfile_evaluation.h"
00033 #include "graphics/blitter.h"
00034 #include "graphics/ColorTransform_PlayerColor.h"
00035 
00036 /*
00037 const char*  cvehiclefunctions[cvehiclefunctionsnum+1]  = {
00038                    "sonar",
00039                    "paratrooper",
00040                    "mine-layer",
00041                    "cruiser landing",
00042                    "repair vehicle",
00043                    "conquer buildings",
00044                    "move after attack",
00045                    "view satellites",
00046                    "construct ALL buildings",
00047                    "view mines",
00048                    "construct vehicles",
00049                    "construct specific buildings",
00050                    "refuel units",
00051                    "icebreaker",
00052                    "cannot be refuelled in air",
00053                    "refuels material",
00054                    "! (unused) !",
00055                    "makes tracks",
00056                    "drill for mineral resources manually",
00057                    "no reactionfire",
00058                    "auto repair",
00059                    "generator",
00060                    "search for mineral resources automatically",
00061                    "Kamikaze only",
00062                    "immune to mines",
00063                    "refuels energy",
00064                    "jams only own field",
00065                    "move with reaction fire on",
00066                    "only move to and from transports",
00067                    NULL };
00068 */
00069 const char*  cwaffentypen[cwaffentypennum]  =
00070    {"cruise missile", "mine",    "bomb",       "large missile", "small missile", "torpedo", "machine gun",
00071     "cannon",         "service", "ammunition refuel", "laser", "shootable", "object placement"
00072    };
00073 
00074 const int  cwaffenproduktionskosten[cwaffentypennum][3]    =
00075    { {
00076         1500,1500,1500
00077      }
00078      ,  // cruise missile
00079      {10, 10, 10},     // mine
00080      {40, 40, 40},     // bomb
00081      {200, 200, 200},     // big missile
00082      {50, 50, 50},     // small missile
00083      {20, 30, 40},     // torpedo
00084      {1, 1, 1},     // machine gun
00085      {5, 5, 1},     // cannon
00086      {0, 0, 0},     // service
00087      {0, 0, 0},     // ammo refuel
00088      {0, 0, 0},     // laser
00089      {0, 0, 0},     // shootable
00090      {0, 0, 0}
00091    }
00092    ;    // objectPlacement
00093 
00094 
00095    const bool  weaponAmmo[cwaffentypennum] = {
00096       true, true, true, true, true, true, true, true, false, false, false, false, false 
00097    };
00098    
00099 Vehicletype :: Vehicletype ( void )
00100 {
00101    recommendedAIJob = AiParameter::job_undefined;
00102 
00103    int i;
00104 
00105    armor = 0;
00106 
00107    height     = 0;
00108    cargoMovementDivisor = 2;
00109    wait = 0;
00110    fuelConsumption = 0;
00111 
00112    movement.resize(8);
00113    for ( i = 0; i < 8; i++ )
00114       movement[i] = 0;
00115    movemalustyp = 0;
00116 
00117    maxwindspeedonwater = 0;
00118    digrange = 0;
00119    initiative = 0;
00120 
00121    weight = 0;
00122    bipicture = -1;
00123 
00124    autorepairrate = 0;
00125 
00126    heightChangeMethodNum = 0;
00127 
00128    for ( i = 0; i < 8; i++ )
00129       aiparam[i] = NULL;
00130 
00131    
00132    static const float matrix[] = { 1, 0, 0,
00133                                  0, 1, 0,
00134                                  0, 0, 1 };
00135    
00136    productionEfficiency = ResourceMatrix( matrix );
00137    
00138    unitConstructionMoveCostPercentage = 50;
00139 }
00140 
00141 
00142 int Vehicletype::maxsize ( void ) const
00143 {
00144    return weight;
00145 }
00146 
00147 
00148 const int vehicle_version = 29;
00149 
00150 
00151 
00152 void Vehicletype::setupRemovableObjectsFromOldFileLayout ( )
00153 {
00154    for ( vector<IntRange>::iterator i = objectsBuildable.begin(); i != objectsBuildable.end();  )
00155       if ( i->to < 0 && i->from < 0 ) {
00156          int mi = min ( -i->from, -i->to );
00157          int ma = max ( -i->from, -i->to );
00158          objectsRemovable.push_back ( IntRange ( mi, ma ));
00159          i = objectsBuildable.erase ( i );
00160       } else {
00161          objectsRemovable.push_back ( *i );
00162          i++;
00163       }
00164 }
00165 
00166 void Vehicletype :: read ( tnstream& stream )
00167 {
00168    int version = stream.readInt();
00169    if ( version > vehicle_version || version < 1)
00170       throw tinvalidversion ( stream.getLocation(), vehicle_version, version );
00171 
00172    int   j;
00173 
00174    bool ___load_name = stream.readInt();
00175    bool ___load_description = stream.readInt();
00176    bool ___load_infotext = stream.readInt();
00177 
00178    if ( version <= 2 ) {
00179       weapons.count = stream.readChar();
00180       for ( j = 0; j< 8; j++ ) {
00181          weapons.weapon[j].set ( stream.readWord() );
00182          weapons.weapon[j].targ = stream.readChar();
00183          weapons.weapon[j].sourceheight = stream.readChar();
00184          weapons.weapon[j].maxdistance = stream.readWord();
00185          weapons.weapon[j].mindistance = stream.readWord();
00186          weapons.weapon[j].count = stream.readChar();
00187          weapons.weapon[j].maxstrength = stream.readChar();
00188          weapons.weapon[j].minstrength = stream.readChar();
00189          for ( int k = 0; k < 13; k++ )
00190             weapons.weapon[j].efficiency[k] = 100;
00191       }
00192    }
00193 
00194    if ( version <= 27 ) {
00195       productionCost.energy   = stream.readWord();
00196       productionCost.material = stream.readWord();
00197    } else
00198       productionCost.read( stream );
00199 
00200    armor = stream.readWord();
00201 
00202    bool picture[8];
00203    for ( j = 0; j < 8; j++ )
00204       if ( version <= 18 )
00205          picture[j] = stream.readInt();
00206       else
00207          picture[j] = false;
00208 
00209    height = stream.readChar();
00210    stream.readWord(); // was: researchID
00211    int _terrain = 0;
00212    int _terrainreq = 0;
00213    int _terrainkill = 0;
00214    if ( version <= 2 ) {
00215       _terrain = stream.readInt();
00216       _terrainreq = stream.readInt();
00217       _terrainkill = stream.readInt();
00218    }
00219    stream.readChar(); // steigung
00220    jamming = stream.readChar();
00221    view = stream.readWord();
00222    wait = stream.readChar();
00223 
00224    if ( version <= 2 )
00225       stream.readChar (); // dummy
00226 
00227    stream.readWord(); // dummy
00228    stream.readWord(); // dummy
00229    stream.readChar(); // dummy
00230    stream.readChar(); // dummy
00231    stream.readChar(); // dummy
00232    if ( version <= 18 )
00233       id = stream.readWord();
00234    else
00235       id = stream.readInt();
00236 
00237    if( version < 24 ) {
00238       bi_mode_tank.resource(2) = bi_mode_tank.resource(2) = stream.readInt();
00239       fuelConsumption = stream.readWord();
00240       bi_mode_tank.resource(0) = bi_mode_tank.resource(0) = stream.readInt();
00241       bi_mode_tank.resource(1) = bi_mode_tank.resource(1) = stream.readInt();
00242    } else
00243       fuelConsumption = stream.readInt();
00244    
00245    if ( version <= 22 ) {
00246       int functions = stream.readInt();
00247       features = convertOldFunctions ( functions, stream.getLocation() );
00248    }
00249 
00250    for ( j = 0; j < 8; j++ )
00251       if ( version <= 4 )
00252          movement[j] = stream.readChar();
00253       else
00254          movement[j] = stream.readInt();
00255 
00256 
00257    movemalustyp = stream.readChar();
00258    if ( movemalustyp >= cmovemalitypenum )
00259       movemalustyp = cmovemalitypenum -1;
00260 
00261    if ( version <= 2 )
00262       for ( j = 0; j < 9; j++ )
00263          stream.readWord( ); // dummy1
00264 
00265    bool ___load_classnames[8];
00266    if ( version <= 15 ) {
00267       stream.readChar(); // classnum
00268 
00269       for ( j = 0; j < 8; j++ )
00270          ___load_classnames[j] = stream.readInt();
00271 
00272       for ( j = 0; j < 8; j++ ) {
00273          int k;
00274          for ( k = 0; k < 8; k++ )
00275             stream.readWord();
00276 
00277          if ( version <= 2 )
00278             stream.readWord (  ); // dummy2
00279 
00280          stream.readWord();
00281          stream.readWord();
00282          for ( k = 0; k < 4; k++ )
00283             stream.readWord();
00284 
00285          stream.readChar();
00286          stream.readInt();
00287          if ( version <= 2 )
00288             stream.readChar( ); // dummy
00289       }
00290    }
00291 
00292    maxwindspeedonwater = stream.readChar();
00293    digrange = stream.readChar();
00294    initiative = stream.readInt();
00295    int _terrainnot = 0;
00296    if ( version <= 4 ) {
00297       _terrainnot = stream.readInt();
00298       stream.readInt(); // _terrainreq1
00299    }
00300    int objectsbuildablenum = stream.readInt();
00301    if ( version <= 4 )
00302       stream.readInt(); // objectsbuildableid = (int*)
00303 
00304    weight = stream.readInt();
00305 
00306    bool ___loadterrainaccess = false;
00307    if ( version <= 4 )
00308       ___loadterrainaccess = stream.readInt();
00309 
00310    bipicture = stream.readInt();
00311    int vehiclesbuildablenum = stream.readInt();
00312    if ( version <= 4 )
00313       stream.readInt(); // vehiclesbuildableid = (int*)
00314 
00315    if ( version <= 4 )
00316       stream.readInt(); // buildicon
00317 
00318    int buildingsbuildablenum = stream.readInt();
00319    if ( version <= 4 )
00320       stream.readInt(); // buildingsbuildable = (Vehicletype::tbuildrange*)
00321 
00322    bool load_weapons = stream.readInt();
00323    autorepairrate = stream.readInt();
00324    if ( version >= 15 )
00325       readClassContainer ( wreckageObject, stream );
00326    else
00327       if ( version >= 8 ) {
00328          wreckageObject.clear();
00329          wreckageObject.push_back ( stream.readInt() );
00330       }
00331 
00332 
00333    if ( version <= 2 )
00334       stream.readInt( ); // dummy
00335 
00336    if ( version >= 4 )
00337       stream.readInt(); // dummy
00338 
00339    if (___load_name)
00340       name = stream.readString( true );
00341 
00342    if (___load_description)
00343       description = stream.readString( true );
00344 
00345    if (___load_infotext)
00346       infotext = stream.readString ( true );
00347 
00348    int i;
00349    if ( version <= 15 )
00350       for ( i=0;i<8  ;i++ )
00351          if ( ___load_classnames[i] )
00352             stream.readString ( true );
00353 
00354    if ( hasFunction( AutoRepair ) )
00355       if ( !autorepairrate )
00356          autorepairrate =  10;
00357 
00358    if ( version <= 18 ) {
00359       if ( picture[0] )
00360          image.read ( stream );
00361 
00362       for ( int i=1;i<8  ;i++ ) {
00363          if ( picture[i] ) {
00364             Surface s;
00365             s.read ( stream );
00366             bipicture = 0;
00367          }
00368       }
00369    } else {
00370       image.read ( stream );
00371    }
00372 
00373 
00374    if ( objectsbuildablenum )
00375       for ( i = 0; i < objectsbuildablenum; i++ ) {
00376          int from = stream.readInt ( );
00377          int to;
00378          if ( version <= 4 )
00379             to = from;
00380          else
00381             to = stream.readInt();
00382 
00383          objectsBuildable.push_back ( IntRange ( from, to ));
00384       }
00385 
00386    if ( version >= 6 ) {
00387       int num = stream.readInt();
00388       for ( int i = 0; i < num; i++ ) {
00389          int from = stream.readInt();
00390          int to   = stream.readInt();
00391 
00392          objectsRemovable.push_back ( IntRange ( from, to ));
00393       }
00394    } else
00395       setupRemovableObjectsFromOldFileLayout();
00396 
00397    if ( version >= 8 ) {
00398       int num = stream.readInt();
00399       for ( int i = 0; i < num; i++ ) {
00400          int from = stream.readInt();
00401          int to   = stream.readInt();
00402 
00403          objectGroupsBuildable.push_back ( IntRange ( from, to ));
00404       }
00405 
00406       num = stream.readInt();
00407       for ( int i = 0; i < num; i++ ) {
00408          int from = stream.readInt();
00409          int to   = stream.readInt();
00410 
00411          objectGroupsRemovable.push_back ( IntRange ( from, to ));
00412       }
00413    }
00414 
00415    if ( vehiclesbuildablenum )
00416       for ( i = 0; i < vehiclesbuildablenum; i++ ) {
00417          int from = stream.readInt ( );
00418          int to;
00419          if ( version <= 4 )
00420             to = from;
00421          else
00422             to = stream.readInt();
00423 
00424          vehiclesBuildable.push_back ( IntRange ( from, to ));
00425       }
00426 
00427    if ( load_weapons && version > 1) {
00428       weapons.count = stream.readInt();
00429       for ( j = 0; j< 16; j++ ) {
00430          weapons.weapon[j].set ( stream.readInt() );
00431          weapons.weapon[j].targ = stream.readInt();
00432          weapons.weapon[j].sourceheight = stream.readInt();
00433          weapons.weapon[j].maxdistance = stream.readInt();
00434          weapons.weapon[j].mindistance = stream.readInt();
00435          weapons.weapon[j].count = stream.readInt();
00436          weapons.weapon[j].maxstrength = stream.readInt();
00437          weapons.weapon[j].minstrength = stream.readInt();
00438 
00439          if ( version >= 17 )
00440             weapons.weapon[j].reactionFireShots = stream.readInt();
00441 
00442          if ( version >= 22 )
00443             weapons.weapon[j].name = stream.readString();
00444 
00445          /*
00446          if ( weapons.weapon[j].getScalarWeaponType() == cwminen )
00447             if ( weapons.weapon[j].mindistance < 8 )
00448                warning ( ASCString("unit with id ") + strrr ( id ) + " has invalid mine weapon range ");
00449          */
00450 
00451          for ( int k = 0; k < 13; k++ )
00452             weapons.weapon[j].efficiency[k] = stream.readInt();
00453 
00454          if ( version <= 6 ) {
00455             int targets_not_hittable = stream.readInt();
00456             for ( int i = 0; i < cmovemalitypenum; i++ )
00457                if ( targets_not_hittable & ( 1 << i))
00458                   weapons.weapon[j].targetingAccuracy[i] = 0;
00459          } else {
00460             int num = stream.readInt();
00461             for ( int i = 0; i < num; i++ )
00462                weapons.weapon[j].targetingAccuracy[i] = stream.readInt();
00463          }
00464 
00465 
00466          if ( version <= 2 )
00467             for ( int l = 0; l < 9; l++ )
00468                stream.readInt(); // dummy
00469 
00470          if ( version >= 11 ) {
00471             weapons.weapon[j].laserRechargeRate = stream.readInt();
00472             weapons.weapon[j].laserRechargeCost.read( stream );
00473          }
00474          if ( version >= 20 )
00475             weapons.weapon[j].soundLabel = stream.readString();
00476 
00477       }
00478 
00479       if ( version <= 2 )
00480          for ( int m = 0; m< 10; m++ )
00481             stream.readInt(); // dummy
00482 
00483    }
00484 
00485    if ( ___loadterrainaccess || version >= 5 )
00486       terrainaccess.read ( stream );
00487    else {
00488       terrainaccess.terrain.setInt ( _terrain, 0 );
00489       terrainaccess.terrainreq.setInt ( _terrainreq, 0 );
00490       terrainaccess.terrainnot.setInt ( _terrainnot, 0 );
00491       terrainaccess.terrainkill.setInt ( _terrainkill, 0 );
00492    }
00493 
00494    if ( buildingsbuildablenum )
00495       for ( i = 0; i < buildingsbuildablenum; i++ ) {
00496          int from = stream.readInt();
00497          int to = stream.readInt();
00498          buildingsBuildable.push_back ( IntRange ( from, to ));
00499       }
00500 
00501 
00502    filename = stream.getDeviceName();
00503    location = stream.getLocation();
00504 
00505    if ( version >= 9 )
00506       ContainerBaseType::read ( stream );
00507 
00508    if ( version >= 10 ) {
00509       heightChangeMethodNum = stream.readInt();
00510       heightChangeMethod.resize(heightChangeMethodNum );
00511       for ( int i = 0; i < heightChangeMethodNum; i++ )
00512          heightChangeMethod[i].read( stream );
00513    } else
00514       heightChangeMethodNum = 0;
00515 
00516    if ( version >= 12 )
00517       techDependency.read( stream );
00518 
00519    if ( version >= 13 && version <= 24 ) {
00520       Surface s;
00521       s.read( stream );
00522    }
00523 
00524    if ( version >= 14 && version < 18)
00525       cargoMovementDivisor = stream.readInt();
00526    else
00527       if ( version >= 18 )
00528          cargoMovementDivisor = stream.readFloat();
00529 
00530    if ( version >= 20 ) {
00531       movementSoundLabel = stream.readString();
00532       killSoundLabel = stream.readString();
00533    }
00534 
00535    if ( version >= 22 )
00536       readClassContainer( guideSortHelp, stream );
00537 
00538    if ( version >= 24 ) {
00539       efficiencyfuel = stream.readInt( );
00540       efficiencymaterial = stream.readInt( );
00541       asc_mode_tank.read( stream );
00542       bi_mode_tank.read( stream );
00543 
00544 
00545       maxresearchpoints = stream.readInt();
00546       defaultMaxResearchpoints = stream.readInt();
00547       nominalresearchpoints = stream.readInt();
00548       maxplus.read( stream );
00549       defaultProduction.read( stream );
00550    }
00551 
00552    for ( int w = 0; w < weapons.count; ++w )
00553       if ( weapons.weapon[w].canRefuel() )
00554          setFunction( ExternalAmmoTransfer );
00555    
00556    if ( version >= 26 ) {
00557       jumpDrive.height = stream.readInt();
00558       jumpDrive.targetterrain.read( stream );
00559       jumpDrive.consumption.read( stream );
00560       jumpDrive.maxDistance = stream.readInt();
00561    }
00562 
00563    if ( version >= 27 ) {
00564       int num = stream.readInt();
00565       for ( int i = 0; i < num; i++ ) {
00566          int from = stream.readInt();
00567          int to   = stream.readInt();
00568          objectLayedByMovement.push_back ( IntRange ( from, to ));
00569       }
00570    }
00571    
00572    if ( version >= 29 )
00573       unitConstructionMoveCostPercentage = stream.readInt();
00574 }
00575 
00576 
00577 
00578 
00579 void Vehicletype:: write ( tnstream& stream ) const
00580 {
00581    int i,j;
00582 
00583    stream.writeInt ( vehicle_version );
00584 
00585    if ( !name.empty() )
00586       stream.writeInt( 1 );
00587    else
00588       stream.writeInt( 0 );
00589 
00590    if ( !description.empty() )
00591       stream.writeInt( 1 );
00592    else
00593       stream.writeInt( 0 );
00594 
00595    if ( !infotext.empty() )
00596       stream.writeInt( 1 );
00597    else
00598       stream.writeInt( 0 );
00599 
00600    productionCost.write( stream );
00601    stream.writeWord( armor );
00602    stream.writeChar( height );
00603    stream.writeWord(0); // researchid
00604    stream.writeChar(0); // steigung
00605    stream.writeChar(jamming);
00606    stream.writeWord(view);
00607    stream.writeChar(wait);
00608    stream.writeWord(0);
00609    stream.writeWord(0);
00610    stream.writeChar(0);
00611    stream.writeChar(0);
00612    stream.writeChar(0);
00613    stream.writeInt(id );
00614    stream.writeInt(fuelConsumption );
00615    for ( j = 0; j < 8; j++ )
00616       stream.writeInt( movement[j] );
00617 
00618 
00619    stream.writeChar(movemalustyp );
00620 
00621    stream.writeChar(maxwindspeedonwater );
00622    stream.writeChar(digrange );
00623    stream.writeInt(initiative );
00624    stream.writeInt( objectsBuildable.size() );
00625 
00626    stream.writeInt(weight );
00627 
00628    stream.writeInt(bipicture );
00629    stream.writeInt(vehiclesBuildable.size() );
00630    stream.writeInt( buildingsBuildable.size() );
00631    stream.writeInt( 1 ); // weapons
00632 
00633    stream.writeInt( autorepairrate );
00634    writeClassContainer( wreckageObject, stream );
00635 
00636    stream.writeInt( 0 );
00637 
00638    if ( !name.empty() )
00639       stream.writeString( name );
00640 
00641    if ( !description.empty() )
00642       stream.writeString( description );
00643 
00644    if ( !infotext.empty() )
00645       stream.writeString( infotext );
00646 
00647    image.write( stream );
00648 
00649    for ( i = 0; i < objectsBuildable.size(); i++ ) {
00650       stream.writeInt ( objectsBuildable[i].from );
00651       stream.writeInt ( objectsBuildable[i].to );
00652    }
00653 
00654    stream.writeInt ( objectsRemovable.size() );
00655    for ( i = 0; i < objectsRemovable.size(); i++ ) {
00656       stream.writeInt ( objectsRemovable[i].from );
00657       stream.writeInt ( objectsRemovable[i].to );
00658    }
00659 
00660    stream.writeInt ( objectGroupsBuildable.size() );
00661    for ( i = 0; i < objectGroupsBuildable.size(); i++ ) {
00662       stream.writeInt ( objectGroupsBuildable[i].from );
00663       stream.writeInt ( objectGroupsBuildable[i].to );
00664    }
00665 
00666    stream.writeInt ( objectGroupsRemovable.size() );
00667    for ( i = 0; i < objectGroupsRemovable.size(); i++ ) {
00668       stream.writeInt ( objectGroupsRemovable[i].from );
00669       stream.writeInt ( objectGroupsRemovable[i].to );
00670    }
00671 
00672 
00673    for ( i = 0; i < vehiclesBuildable.size(); i++ ) {
00674       stream.writeInt ( vehiclesBuildable[i].from );
00675       stream.writeInt ( vehiclesBuildable[i].to );
00676    }
00677 
00678    stream.writeInt(weapons.count );
00679    for ( j = 0; j< 16; j++ ) {
00680       stream.writeInt(weapons.weapon[j].gettype( ));
00681       stream.writeInt(weapons.weapon[j].targ);
00682       stream.writeInt(weapons.weapon[j].sourceheight );
00683       stream.writeInt(weapons.weapon[j].maxdistance );
00684       stream.writeInt(weapons.weapon[j].mindistance );
00685       stream.writeInt(weapons.weapon[j].count );
00686       stream.writeInt(weapons.weapon[j].maxstrength );
00687       stream.writeInt(weapons.weapon[j].minstrength );
00688       stream.writeInt(weapons.weapon[j].reactionFireShots );
00689       stream.writeString( weapons.weapon[j].name );
00690 
00691       for ( int k = 0; k < 13; k++ )
00692          stream.writeInt(weapons.weapon[j].efficiency[k] );
00693 
00694       stream.writeInt ( cmovemalitypenum );
00695       for ( int i = 0; i < cmovemalitypenum; i++ )
00696          stream.writeInt(weapons.weapon[j].targetingAccuracy[i] );
00697 
00698       stream.writeInt( weapons.weapon[j].laserRechargeRate );
00699       weapons.weapon[j].laserRechargeCost.write( stream );
00700       stream.writeString( weapons.weapon[j].soundLabel );
00701    }
00702 
00703    terrainaccess.write ( stream );
00704 
00705    for ( i = 0; i < buildingsBuildable.size(); i++ ) {
00706       stream.writeInt( buildingsBuildable[i].from );
00707       stream.writeInt( buildingsBuildable[i].to );
00708    }
00709 
00710    ContainerBaseType::write ( stream );
00711 
00712 
00713    stream.writeInt( heightChangeMethodNum );
00714    for ( i = 0; i < heightChangeMethodNum; i++ )
00715       heightChangeMethod[i].write( stream );
00716 
00717    techDependency.write( stream );
00718 
00719    stream.writeFloat ( cargoMovementDivisor );
00720 
00721    stream.writeString( movementSoundLabel );
00722    stream.writeString( killSoundLabel );
00723    writeClassContainer( guideSortHelp, stream );
00724 
00725    stream.writeInt( efficiencyfuel );
00726    stream.writeInt( efficiencymaterial );
00727 
00728    asc_mode_tank.write( stream );
00729    bi_mode_tank.write( stream );
00730 
00731    stream.writeInt( maxresearchpoints );
00732    stream.writeInt( defaultMaxResearchpoints );
00733    stream.writeInt( nominalresearchpoints );
00734    maxplus.write ( stream );
00735    defaultProduction.write( stream );
00736    
00737    stream.writeInt( jumpDrive.height );
00738    jumpDrive.targetterrain.write( stream );
00739    jumpDrive.consumption.write( stream );
00740    stream.writeInt( jumpDrive.maxDistance );
00741 
00742    stream.writeInt ( objectLayedByMovement.size() );
00743    for ( i = 0; i < objectLayedByMovement.size(); i++ ) {
00744       stream.writeInt ( objectLayedByMovement[i].from );
00745       stream.writeInt ( objectLayedByMovement[i].to );
00746    }
00747    
00748    stream.writeInt( unitConstructionMoveCostPercentage );
00749 }
00750 
00751 
00752 ASCString Vehicletype::getName( ) const
00753 {
00754    if ( !name.empty() )
00755       return name;
00756    else
00757       return description;
00758 }
00759 
00760 int Vehicletype :: maxSpeed ( ) const
00761 {
00762    int maxUnitMovement = 0;
00763    for ( int i = 0; i < 8; i++ )
00764       maxUnitMovement = max ( maxUnitMovement, movement[i] );
00765    return maxUnitMovement;
00766 }
00767 
00768 int Vehicletype::getMemoryFootprint() const 
00769 {
00770    return sizeof(*this) + image.getMemoryFootprint(); 
00771 }
00772 
00773 
00774 Vehicletype :: ~Vehicletype ( )
00775 {
00776    for ( int i = 0; i < 8; i++ )
00777       if ( aiparam[i] ) {
00778          delete aiparam[i];
00779          aiparam[i] = NULL;
00780       }
00781 }
00782 
00783 
00784 
00785 SingleWeapon::SingleWeapon()
00786 {
00787    typ = 0;
00788    targ = 0;
00789    sourceheight = 0;
00790    maxdistance = 0;
00791    mindistance = 0;
00792    count = 0;
00793    maxstrength= 0;
00794    minstrength = 0;
00795    laserRechargeRate = 0;
00796    for ( int i = 0; i < 13; i++ )
00797       efficiency[i] = 0;
00798    for ( int i = 0; i < cmovemalitypenum; i++ )
00799       targetingAccuracy[i] = 100;
00800 
00801    reactionFireShots = 1;
00802 }
00803 
00804 
00805 /* Translate the weapon/mine/service bit pattern into scalar
00806  * weapon number for use in fetching UI resources.
00807  */
00808 int SingleWeapon::getScalarWeaponType(void) const
00809 {
00810    if ( typ & (cwweapon | cwmineb) )
00811       return log2 ( typ & (cwweapon | cwmineb) );
00812    else
00813       return -1;
00814 }
00815 
00816 
00817 bool SingleWeapon::requiresAmmo(void) const
00818 {
00819    if ( typ & cwlaserb )
00820       return false;
00821    else
00822       return typ & ( cwweapon | cwmineb );
00823 }
00824 
00825 bool SingleWeapon::shootable( void ) const
00826 {
00827    return typ & cwshootableb;
00828 }
00829 
00830 bool SingleWeapon::offensive( void ) const
00831 {
00832    return typ & cwweapon;
00833 }
00834 
00835 bool SingleWeapon::service( void ) const
00836 {
00837    return typ & cwserviceb;
00838 }
00839 
00840 bool SingleWeapon::placeObjects(  ) const
00841 {
00842    return typ & cwobjectplacementb;
00843 }
00844 
00845 
00846 bool SingleWeapon::canRefuel( void ) const
00847 {
00848    return typ & cwammunitionb;
00849 }
00850 
00851 void SingleWeapon::set
00852    ( int type )
00853 {
00854    typ = type;
00855 }
00856 
00857 ASCString SingleWeapon::getName ( void ) const
00858 {
00859    if ( !name.empty() )
00860       return name;
00861 
00862    ASCString s;
00863 
00864    int k = getScalarWeaponType();
00865    if ( k < cwaffentypennum && k >= 0 )
00866       s = cwaffentypen[k];
00867    else
00868       if ( service() || placeObjects() )
00869          s = cwaffentypen[cwservicen];
00870       else
00871          s = "undefined";
00872 
00873    return s;
00874 }
00875 
00876 ASCString    SingleWeapon::getIconFileName( int numerical )
00877 {
00878    switch ( numerical ) {
00879       case cwcruisemissile:
00880          return "weap-cruisemissile";
00881       case cwbombn:
00882          return "weap-bomb";
00883       case cwlargemissilen:
00884          return "weap-bigmissile";
00885       case cwsmallmissilen:
00886          return "weap-smallmissile";
00887       case cwtorpedon:
00888          return "weap-torpedo";
00889       case cwmachinegunn:
00890          return "weap-machinegun";
00891       case cwcannonn:
00892          return "weap-cannon";
00893       case cwminen:
00894          return "weap-mine";
00895       case cwservicen:
00896          return "weap-service";
00897       case cwlasern:
00898          return "weap-laser";
00899       default:
00900          return "weap-undefined";
00901    };
00902 }
00903 
00904 
00905 bool SingleWeapon::equals( const SingleWeapon* otherWeapon ) const
00906 {
00907       if(
00908               otherWeapon->targ == this->targ &&
00909               otherWeapon->sourceheight == this->sourceheight &&
00910               otherWeapon->maxdistance == this->maxdistance &&
00911               otherWeapon->mindistance == this->mindistance &&
00912               otherWeapon->count == this->count &&
00913               otherWeapon->maxstrength == this->maxstrength &&
00914               otherWeapon->minstrength == this->minstrength &&
00915               otherWeapon->gettype() == this->gettype()
00916       )
00917       {
00918               bool equal = true;
00919               for( int i=0; i<13; i++ )
00920               {
00921                       if( otherWeapon->efficiency[ i ] != this->efficiency[ i ] )
00922                       {
00923                               equal = false;
00924                       }
00925               }
00926               if( equal ) return true;
00927       }
00928 
00929       return false;
00930 }
00931 
00932 
00933 UnitWeapon :: UnitWeapon ( void )
00934 {
00935    count = 0;
00936 }
00937 
00938 
00939 
00940 
00941 void Vehicletype::runTextIO ( PropertyContainer& pc )
00942 {
00943    ContainerBaseType::runTextIO ( pc );
00944 
00945    pc.addString( "Description", description);
00946 
00947    pc.addInteger( "Armor", armor );
00948 
00949    ASCString fn;
00950    if ( filename.empty() ) {
00951       fn += "vehicle";
00952       fn += strrr(id);
00953    } else
00954       fn = extractFileName_withoutSuffix( filename );
00955 
00956    pc.addImage( "Picture", image, fn, true );
00957    if( image.w() < fieldsizex || image.h() < fieldsizey )
00958       image.strech( fieldsizex, fieldsizey );
00959 
00960    image.assignDefaultPalette();
00961 
00962    pc.addTagInteger( "Height", height, choehenstufennum, heightTags );
00963    pc.addBool ( "WaitForAttack", wait );
00964 
00965    if ( bi_mode_tank == Resources(0,0,0) && asc_mode_tank == Resources(0,0,0)) {
00966            pc.openBracket( "Tank" );
00967            Resources tank;
00968            tank.runTextIO ( pc );
00969            pc.closeBracket();
00970            bi_mode_tank = tank;
00971            asc_mode_tank = tank;
00972    }
00973    
00974    pc.addInteger( "FuelConsumption", fuelConsumption );
00975    if ( !pc.find("Features") && pc.isReading() ) {
00976       int abilities;
00977       pc.addTagInteger ( "Abilities", abilities, legacyVehicleFunctionNum, vehicleAbilities );
00978 
00979       features = convertOldFunctions ( abilities, pc.getFileName() );
00980 
00981    } else
00982       pc.addTagArray ( "Features", features, functionNum, containerFunctionTags );
00983 
00984 
00985    pc.addIntegerArray ( "Movement", movement );
00986    for ( vector<int>::iterator i = movement.begin(); i != movement.end(); i++ )
00987       if ( *i > 255 )
00988          *i = 255;
00989 
00990    pc.addNamedInteger ( "Category", movemalustyp, cmovemalitypenum, unitCategoryTags );
00991    pc.addInteger("MaxSurvivableStorm", maxwindspeedonwater, 255 );
00992    pc.addInteger("ResourceDrillingRange", digrange, 0 );
00993    pc.addInteger("SelfRepairRate", autorepairrate, 0 );
00994    if ( pc.find ( "WreckageObject" ) || !pc.isReading() )
00995       pc.addIntegerArray("WreckageObject", wreckageObject );
00996 
00997 
00998    if ( pc.find( "CargoMovementDivisor" ))
00999       pc.addDFloat("CargoMovementDivisor", cargoMovementDivisor);
01000    else {
01001       pc.openBracket( "Transportation" );
01002       pc.addDFloat("CargoMovementDivisor", cargoMovementDivisor, 2 );
01003       pc.closeBracket();
01004    }
01005 
01006 
01007    pc.addInteger("Weight",  weight);
01008    pc.openBracket("TerrainAccess" );
01009    terrainaccess.runTextIO ( pc );
01010    pc.closeBracket();
01011 
01012    pc.openBracket ( "Construction" );
01013    pc.addIntRangeArray ( "Buildings", buildingsBuildable );
01014    pc.addIntRangeArray ( "Vehicles", vehiclesBuildable );
01015    pc.addIntRangeArray ( "Objects", objectsBuildable );
01016    if ( pc.isReading() ) {
01017       if ( pc.find ( "ObjectsRemovable" ))
01018          pc.addIntRangeArray ( "ObjectsRemovable", objectsRemovable );
01019       else
01020          setupRemovableObjectsFromOldFileLayout();
01021    } else
01022       pc.addIntRangeArray ( "ObjectsRemovable", objectsRemovable );
01023 
01024    pc.addIntRangeArray ( "ObjectGroupsBuildable", objectGroupsBuildable, false );
01025    pc.addIntRangeArray ( "ObjectGroupsRemovable", objectGroupsRemovable, false );
01026    pc.addInteger("UnitConstructionMoveCostPercentage", unitConstructionMoveCostPercentage, 50);
01027    pc.closeBracket();
01028 
01029    pc.openBracket ( "Weapons");
01030    // pc.addInteger("Initiative", initiative );
01031    pc.addInteger("Number", weapons.count );
01032    for ( int i = 0; i < weapons.count; i++ ) {
01033       pc.openBracket ( ASCString("Weapon")+strrr(i) );
01034       weapons.weapon[i].runTextIO( pc );
01035       pc.closeBracket();
01036       if ( hasFunction( NoReactionfire ) )
01037          weapons.weapon[i].reactionFireShots = 0;
01038 
01039    }
01040 
01041    pc.closeBracket();
01042 
01043    int job = recommendedAIJob;
01044    pc.addNamedInteger ( "AIJobOverride", job, AiParameter::jobNum, AIjobs, AiParameter::job_undefined );
01045    recommendedAIJob = AiParameter::Job(job);
01046 
01047    pc.addString("MovementSound", movementSoundLabel, "" );
01048    pc.addString("KillSound", killSoundLabel, "" );
01049 
01050    pc.addInteger("HeightChangeMethodNum", heightChangeMethodNum, 0 );
01051    heightChangeMethod.resize( heightChangeMethodNum );
01052    for ( int i = 0; i < heightChangeMethodNum; i++ ) {
01053       pc.openBracket( ASCString("HeightChangeMethod")+strrr(i) );
01054       heightChangeMethod[i].runTextIO ( pc );
01055       pc.closeBracket();
01056    }
01057 
01058    techDependency.runTextIO( pc, strrr(id) );
01059 
01060 
01061 
01062    pc.openBracket ( "ConstructionCost" );
01063    productionCost.runTextIO ( pc );
01064    int costCalcMethod = 0;
01065    pc.addNamedInteger( "CalculationMethod", costCalcMethod, productionCostCalculationMethodNum, productionCostCalculationMethod,  0 );
01066    if ( pc.isReading() ) {
01067       if ( !pc.find ( "material" ) && costCalcMethod == 0)
01068          costCalcMethod = 1;
01069    }
01070 
01071    if ( costCalcMethod == 1 )
01072       productionCost = calcProductionsCost();
01073    if ( costCalcMethod == 2 )
01074       productionCost += calcProductionsCost();
01075 
01076    if ( costCalcMethod != 0 ) {
01077       displayLogMessage ( 4, "unit %s id %d has a production cost of %d E; %d M;  %d F \n", name.c_str(), id, productionCost.energy, productionCost.material, productionCost.fuel );
01078    }
01079 
01080    pc.closeBracket ();
01081 
01082    if ( pc.find( "guideSortHelp") || !pc.isReading() )
01083       pc.addIntegerArray("guideSortHelp", guideSortHelp );
01084 
01085    bool hasService = false;
01086    for ( int w = 0; w < weapons.count; ++w ) {
01087       if ( weapons.weapon[w].canRefuel() ) 
01088          setFunction( ExternalAmmoTransfer );
01089       if ( weapons.weapon[w].service() ) 
01090          hasService = true;
01091    }
01092 
01093    if ( !hasService ) {
01094       features.reset( ExternalRepair );
01095       features.reset( ExternalEnergyTransfer );
01096       features.reset( ExternalMaterialTransfer );
01097       features.reset( ExternalFuelTransfer );
01098       features.reset( ExternalAmmoTransfer );
01099    }
01100 
01101    
01102    
01103    pc.openBracket ( "JumpDrive" );
01104    pc.addTagInteger( "Height", jumpDrive.height, choehenstufennum, heightTags, 0 );
01105    pc.openBracket ( "consumption" );
01106    jumpDrive.consumption.runTextIO ( pc, Resources(0,0,0) );
01107    pc.closeBracket();
01108    if ( jumpDrive.height || !pc.isReading() )
01109       jumpDrive.targetterrain.runTextIO ( pc );
01110    pc.addInteger( "MaxDistance", jumpDrive.maxDistance, maxint );
01111    pc.closeBracket();
01112    
01113    if ( jumpDrive.height && view )
01114       pc.error( "only units without radar may have a jump drive." ); 
01115 
01116    if ( !pc.isReading() || pc.find ( "ObjectsLayedByMovement" ))
01117       pc.addIntRangeArray ( "ObjectsLayedByMovement", objectLayedByMovement );
01118    else
01119       objectLayedByMovement.clear();
01120 
01121    if ( hasFunction( ContainerBaseType::IceBreaker ))
01122       objectLayedByMovement.push_back ( 6 );
01123 
01124    if ( hasFunction( ContainerBaseType::MakesTracks ))
01125       objectLayedByMovement.push_back ( 7 );
01126 
01127    
01128 }
01129 
01130 BitSet Vehicletype::convertOldFunctions( int abilities, const ASCString& location )
01131 {
01132    BitSet features;
01133    if ( abilities & 1 )
01134       features.set( Sonar );
01135    if ( abilities & 2 )
01136       features.set( Paratrooper );
01137    if ( abilities & 4 )
01138       features.set( PlaceMines );
01139    if ( abilities & 8 )
01140       features.set( CruiserLanding );
01141    if ( abilities & 16 ) {
01142       features.set( ExternalRepair );
01143       features.set( InternalUnitRepair );
01144    }
01145    if ( abilities & 32 )
01146       features.set( ConquerBuildings );
01147    if ( abilities & 64 )
01148       features.set( MoveAfterAttack );
01149    if ( abilities & 128 )
01150       features.set( SatelliteView );
01151    if ( abilities & 256 )
01152       errorMessage( location + ": The features construct_ALL_buildings is not supported any more");
01153    if ( abilities & 512 )
01154       features.set( MineView );
01155    if ( abilities & 1024 )
01156       features.set( ExternalVehicleProduction );
01157    if ( abilities & 2048 )
01158       features.set( ConstructBuildings );
01159    if ( abilities & 4096 )
01160       features.set( ExternalFuelTransfer );
01161    if ( abilities & 8192 )
01162       features.set( IceBreaker );
01163    if ( abilities & 16384 )
01164       features.set( NoInairRefuelling );
01165    if ( abilities & 32768 )
01166       features.set( ExternalMaterialTransfer );
01167    if ( abilities & (1 << 17) )
01168       features.set( MakesTracks );
01169    if ( abilities & (1 << 18) )
01170       features.set( DetectsMineralResources );
01171    if ( abilities & (1 << 19) )
01172       features.set( NoReactionfire );
01173    if ( abilities & (1 << 20) )
01174       features.set( AutoRepair );
01175    if ( abilities & (1 << 21) )
01176       features.set( MatterConverter );
01177    // we probably need to setup the conversion matrix at this point
01178 
01179    if ( abilities & (1 << 22) )
01180       features.set( DetectsMineralResources );
01181    if ( abilities & (1 << 23) )
01182       features.set( KamikazeOnly );
01183    if ( abilities & (1 << 24) )
01184       features.set( ImmuneToMines );
01185    if ( abilities & (1 << 25) )
01186       features.set( ExternalEnergyTransfer );
01187    if ( abilities & (1 << 26) )
01188       features.set( JamsOnlyOwnField );
01189    if ( abilities & (1 << 27) )
01190       features.set( MoveWithReactionFire );
01191    if ( abilities & (1 << 28) )
01192       features.set( OnlyMoveToAndFromTransports );
01193    return features;
01194 }
01195 
01196 void  Vehicletype::paint ( Surface& s, SPoint pos, const PlayerColor& player, int direction ) const
01197 {
01198    megaBlitter<ColorTransform_PlayerCol,ColorMerger_AlphaOverwrite,SourcePixelSelector_Plain,TargetPixelSelector_All>( getImage(), s, pos, player, nullParam, nullParam, nullParam );
01199 }
01200 
01201 void  Vehicletype::paint ( Surface& s, SPoint pos ) const
01202 {
01203    megaBlitter<ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_Plain,TargetPixelSelector_All>( getImage(), s, pos, nullParam, nullParam, nullParam, nullParam );
01204 }
01205 
01206 
01207 void SingleWeapon::runTextIO ( PropertyContainer& pc )
01208 {
01209    pc.addTagInteger( "Type", typ, cwaffentypennum, weaponTags );
01210    pc.addTagInteger( "targets", targ, choehenstufennum, heightTags );
01211    pc.addTagInteger( "shotFrom", sourceheight, choehenstufennum, heightTags );
01212    pc.addInteger("MaxRange", maxdistance );
01213    pc.addInteger("MinRange", mindistance );
01214    pc.addInteger("Ammo", count );
01215    pc.addInteger("Punch@MaxRange", minstrength );
01216    pc.addInteger("Punch@MinRange", maxstrength );
01217    pc.addString("Sound", soundLabel, "");
01218    pc.addInteger("LaserRechargeRate", laserRechargeRate, 0 );
01219    pc.openBracket( "laserRechargeCost" );
01220    laserRechargeCost.runTextIO ( pc, Resources(0,0,0) );
01221    pc.closeBracket();
01222 
01223    pc.addInteger("ReactionFireShots", reactionFireShots, 1 );
01224 
01225    pc.openBracket("HitAccuracy" );
01226    {
01227       for ( int j = 0; j < 13; j++ )
01228          if ( j < 6 )
01229             pc.addInteger( ASCString("d")+strrr(abs(j-6)), efficiency[j] );
01230          else
01231             if ( j == 6 )
01232                pc.addInteger( "0", efficiency[j] );
01233             else
01234                pc.addInteger( ASCString("u")+strrr(j-6), efficiency[j] );
01235    }
01236    pc.closeBracket();
01237 
01238    if ( pc.isReading() ) {
01239       if ( pc.find ( "cantHit" )) {
01240          int targets_not_hittable;
01241          pc.addTagInteger( "cantHit", targets_not_hittable, cmovemalitypenum, unitCategoryTags );
01242          for ( int i = 0; i < cmovemalitypenum; i++ )
01243             if ( targets_not_hittable & ( 1 << i ))
01244                targetingAccuracy[i] = 0;
01245       }
01246       pc.openBracket("WeaponEffectiveness" );
01247       for ( int i = 0; i < cmovemalitypenum; i++ ) {
01248          if ( pc.find ( unitCategoryTags[i] ))
01249             pc.addInteger( unitCategoryTags[i], targetingAccuracy[i] );
01250       }
01251       pc.closeBracket();
01252    } else {
01253       pc.openBracket("WeaponEffectiveness" );
01254       for ( int i = 0; i < cmovemalitypenum; i++ )
01255          if ( targetingAccuracy[i] != 100 )
01256             pc.addInteger( unitCategoryTags[i], targetingAccuracy[i] );
01257       pc.closeBracket();
01258    }
01259    pc.addString("name", name, "");
01260 }
01261 
01262 
01263 void Vehicletype :: HeightChangeMethod :: runTextIO ( PropertyContainer& pc )
01264 {
01265    pc.addTagInteger( "StartHeight", startHeight, choehenstufennum, heightTags );
01266    pc.addInteger("HeightDelta", heightDelta );
01267    pc.addInteger("MoveCost", moveCost, 0 );
01268    pc.addBool ( "CanAttack", canAttack );
01269    pc.addInteger("Dist", dist );
01270 }
01271 
01272 
01273 
01274 const int vehicleHeightChangeMethodVersion = 1;
01275 
01276 
01277 void Vehicletype :: HeightChangeMethod :: read ( tnstream& stream )
01278 {
01279    int version = stream.readInt();
01280    if ( version > vehicleHeightChangeMethodVersion || version < 1 ) {
01281       ASCString s = "invalid version for reading VehicleType :: HeightChangeMethod : ";
01282       s += strrr ( version );
01283       throw ASCmsgException ( s );
01284    }
01285    startHeight = stream.readInt();
01286    heightDelta = stream.readInt();
01287    moveCost = stream.readInt();
01288    canAttack = stream.readInt();
01289    dist = stream.readInt();
01290 }
01291 
01292 void Vehicletype :: HeightChangeMethod :: write ( tnstream& stream ) const
01293 {
01294    stream.writeInt ( vehicleHeightChangeMethodVersion );
01295    stream.writeInt ( startHeight );
01296    stream.writeInt ( heightDelta );
01297    stream.writeInt ( moveCost );
01298    stream.writeInt ( canAttack );
01299    stream.writeInt ( dist );
01300 }
01301 
01302 
01303 /***************************************************************************
01304                           Preiskalkulation  -  description
01305                              -------------------
01306     begin                : So Aug 15 2004
01307     copyright            : (C) 2001 by Martin Bickel & Steffen Froelich
01308     email                : bickel@asc-hq.org
01309  
01310  vehicletype {
01311    constructioncost {
01312     calculationMode = [auto](default)[add][manual]
01313     energy = 0
01314     material = 0
01315     fuel = 0
01316    } constructioncost
01317  } vehicletYpe
01318  
01319 Part I   -description
01320 Part II  -beginn calculation
01321 Part III -typecost
01322 part IV  -weaponcost
01323 Part V   -specialcost
01324 Part VI  -addition
01325 Part VII -malus
01326  
01327  ***************************************************************************/
01328 
01329 //Part II beginn calculation
01330 
01331 
01332 Resources Vehicletype :: calcProductionsCost()
01333 {
01334    Resources res;
01335    // Anfang -> Abschluss
01336    res.energy = 0;
01337    res.material = 0;
01338    res.fuel = 0;
01339    int typecoste = 0;
01340    int typecostm = 0;
01341    int weaponcoste = 0;
01342    int weaponcostm = 0;
01343    int specialcoste = 0;
01344    int specialcostm = 0;
01345    int movecostsize = 0;
01346    int rangecostsize = 0;
01347 
01348 
01349    // Part III typecost
01350 
01351    if ( movemalustyp == MoveMalusType::trooper) {
01352       typecoste += armor*2;
01353       typecostm += armor*2;
01354    } else
01355       if ( movemalustyp == MoveMalusType::light_wheeled_vehicle ) {
01356          typecoste += armor*6;
01357          typecostm += armor*6;
01358    } else
01359       if ( movemalustyp == MoveMalusType::light_tracked_vehicle || movemalustyp == MoveMalusType::medium_wheeled_vehicle ) {
01360          typecoste += armor*7;
01361          typecostm += armor*7;
01362    } else
01363       if ( movemalustyp == MoveMalusType::medium_tracked_vehicle || movemalustyp == MoveMalusType::heavy_wheeled_vehicle || movemalustyp == MoveMalusType::rail_vehicle || movemalustyp == MoveMalusType::structure) {
01364          typecoste += armor*8;
01365          typecostm += armor*8;
01366    } else
01367       if ( movemalustyp == MoveMalusType::heavy_tracked_vehicle ) {
01368          typecoste += armor*9;
01369          typecostm += armor*9;
01370 
01371    } else
01372       if ( movemalustyp == MoveMalusType::hoovercraft) {
01373          typecoste += armor*9;
01374          typecostm += armor*9;
01375    } else
01376       if ( movemalustyp == MoveMalusType::light_ship ) {
01377          typecoste += armor*8;
01378          typecostm += armor*8;
01379    } else
01380       if ( movemalustyp == MoveMalusType::medium_ship ) {
01381          typecoste += armor*10;
01382          typecostm += armor*10;
01383    } else
01384       if ( movemalustyp == MoveMalusType::heavy_ship ) {
01385          typecoste += armor*12;
01386          typecostm += armor*12;
01387 
01388    } else
01389       if ( movemalustyp == MoveMalusType::light_aircraft || movemalustyp == MoveMalusType::helicopter ) {
01390          typecoste += armor*18;
01391          typecostm += armor*18;
01392    } else
01393       if ( movemalustyp == MoveMalusType::medium_aircraft || movemalustyp == MoveMalusType::heavy_aircraft ) {
01394          typecoste += armor*20;
01395          typecostm += armor*20;
01396 
01397    } else {
01398          typecoste += armor*6;
01399          typecostm += armor*6;
01400    }
01401 
01402    // Zuschlag fuer Eisbrecher
01403    if ( hasFunction( IceBreaker ) ) {
01404       typecoste += armor *2;
01405       typecostm += armor *2;
01406    }
01407    // Zuschlag fuer U-Boote / Druckhuelle
01408    if