00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdio.h>
00028 #include <cstring>
00029 #include <math.h>
00030 #include <stdarg.h>
00031 #include <ctime>
00032
00033 #include "buildingtype.h"
00034 #include "vehicletype.h"
00035 #include "typen.h"
00036
00037 #include "spfst.h"
00038 #include "loaders.h"
00039 #include "controls.h"
00040 #include "attack.h"
00041 #include "gameoptions.h"
00042 #include "errors.h"
00043 #include "viewcalculation.h"
00044 #include "replay.h"
00045 #include "resourcenet.h"
00046 #include "stack.h"
00047
00048
00049 bool checkUnitsForCrash( Player& player, ASCString& text )
00050 {
00051 bool endangeredUnits = false;
00052
00053 for ( Player::VehicleList::const_iterator i = player.vehicleList.begin(); i != player.vehicleList.end(); ++i ) {
00054 int endurance = UnitHooveringLogic::getEndurance( *i );
00055 if ( endurance>= 0 && endurance <= CGameOptions::Instance()->aircraftCrashWarningTime ) {
00056 endangeredUnits = true;
00057 text += (*i)->getName() + " " + (*i)->getPosition().toString() + "\n";
00058 }
00059
00060 }
00061 return endangeredUnits;
00062 }
00063
00064
00065
00066
00067 int windbeeline ( const MapCoordinate& start, const MapCoordinate& dest, WindMovement* wm ) {
00068 int x1 = start.x;
00069 int y1 = start.y;
00070 int dist = 0;
00071 while ( x1 != dest.x || y1 != dest.y ) {
00072 dist+= minmalq;
00073 int direc = getdirection ( x1, y1, dest.x, dest.y );
00074 dist -= wm->getDist(direc);
00075 getnextfield ( x1, y1, direc );
00076 }
00077 return dist;
00078 }
00079
00080
00081
00082 pair<int,int> calcMoveMalus( const MapCoordinate3D& start,
00083 const MapCoordinate3D& dest,
00084 const Vehicle* vehicle,
00085 WindMovement* wm,
00086 bool* inhibitAttack,
00087 bool container2container )
00088 {
00089 int direc = getdirection ( start.x, start.y, dest.x, dest.y );
00090
00091
00092 int fuelcost = 10;
00093 int movecost;
00094 bool checkHemming = true;
00095 bool checkWind = wm != NULL;
00096 int dist = 1;
00097
00098 if ( start.getNumericalHeight() >= 0 && dest.getNumericalHeight() >= 0 ) {
00099
00100
00101 if ( (start.getNumericalHeight() != dest.getNumericalHeight()) && !container2container ) {
00102 const VehicleType::HeightChangeMethod* hcm = vehicle->getHeightChange( start.getNumericalHeight() < dest.getNumericalHeight() ? 1 : -1, start.getBitmappedHeight());
00103 if ( !hcm || hcm->dist != beeline ( start, dest )/maxmalq )
00104 fatalError("Calcmovemalus called with invalid height change distance");
00105 dist = hcm->dist;
00106 movecost = hcm->moveCost;
00107 fuelcost = max(hcm->dist*10,10);
00108 if ( inhibitAttack && !hcm->canAttack )
00109 *inhibitAttack = !hcm->canAttack;
00110 checkHemming = false;
00111 if ( start.getNumericalHeight() < 4 || dest.getNumericalHeight() < 4 )
00112 checkWind = false;
00113 } else
00114
00115 if (start.getNumericalHeight() >= 4 )
00116 movecost = maxmalq;
00117 else
00118 if ( start.getNumericalHeight() <= 1 ) {
00119 movecost = submarineMovement;
00120 checkWind = false;
00121 } else {
00122
00123 MapField* fld = vehicle->getMap()->getField( dest.x, dest.y );
00124 if ( fld->building )
00125 movecost = maxmalq;
00126 else
00127 movecost = fld->getmovemalus( vehicle );
00128 checkWind = false;
00129 }
00130
00131 } else
00132 if ( dest.getNumericalHeight() >= 0 ) {
00133
00134 int mm;
00135 const ContainerBaseType::TransportationIO* unloadSystem = vehicle->getMap()->getField( start.x, start.y )->getContainer()->vehicleUnloadSystem( vehicle->typ, dest.getBitmappedHeight() );
00136 if ( unloadSystem )
00137 mm = unloadSystem->movecost;
00138 else
00139 mm = 0;
00140
00141 if ( mm > 0 )
00142 movecost = mm;
00143 else {
00144 if ( dest.getNumericalHeight() >= 4 )
00145
00146 movecost = maxmalq;
00147 else {
00148 if ( dest.getNumericalHeight() <= 1 ) {
00149 movecost = submarineMovement;
00150 checkWind = false;
00151 } else {
00152 movecost = vehicle->getMap()->getField( dest.x, dest.y )->getmovemalus( vehicle );
00153 }
00154 }
00155 }
00156 } else {
00157
00158 movecost = maxmalq;
00159 checkHemming = false;
00160 checkWind = false;
00161 }
00162
00163 static const int movemalus[6] = { 0, 3, 5, 0, 5, 3 };
00164
00165 if ( checkHemming )
00166 for (int c = 0; c < sidenum; c++) {
00167 int x = dest.x;
00168 int y = dest.y;
00169 getnextfield( x, y, c );
00170 MapField* fld = vehicle->getMap()->getField ( x, y );
00171 if ( fld ) {
00172 int d = (c - direc);
00173
00174 if (d >= sidenum)
00175 d -= sidenum;
00176
00177 if (d < 0)
00178 d += sidenum;
00179
00180 MapField* fld = vehicle->getMap()->getField(x,y);
00181 if ( fld->vehicle && dest.getNumericalHeight() >= 0 ) {
00182 if ( vehicle->getMap()->getPlayer(vehicle).diplomacy.isHostile( fld->vehicle->getOwner() ) )
00183 if ( attackpossible28(fld->vehicle,vehicle, NULL, dest.getBitmappedHeight() ))
00184 movecost += movemalus[d];
00185
00186 }
00187 }
00188 }
00189
00190
00191
00192
00193 if ( wm && checkWind && direc >= 0 && direc < 5 )
00194 if (dest.getNumericalHeight() >= 4 && dest.getNumericalHeight() <= 6 &&
00195 start.getNumericalHeight() >= 4 && start.getNumericalHeight() <= 6 &&
00196 vehicle->getMap()->weather.windSpeed ) {
00197 movecost -= wm->getDist( direc ) * dist;
00198 fuelcost -= wm->getDist ( direc ) * dist;
00199
00200 if ( movecost < 1 )
00201 movecost = 1;
00202
00203 if ( fuelcost <= 0 )
00204 fuelcost = 0;
00205 }
00206 return make_pair(movecost,fuelcost);
00207 }
00208
00209
00210
00211
00212
00213
00214 void Building :: execnetcontrol ( void )
00215 {
00216 for ( int i = 0; i < 3; i++ )
00217 if ( !getMap()->isResourceGlobal(i) ) {
00218 if ( netcontrol & (cnet_moveenergyout << i )) {
00219 npush ( netcontrol );
00220 netcontrol |= (cnet_stopenergyinput << i );
00221 actstorage.resource(i) -= putResource ( actstorage.resource(i), i, 0 );
00222 npop ( netcontrol );
00223 } else
00224 if ( netcontrol & (cnet_storeenergy << i )) {
00225 npush ( netcontrol );
00226 netcontrol |= (cnet_stopenergyoutput << i );
00227 actstorage.resource(i) += getResource ( getStorageCapacity().resource(i) - actstorage.resource(i), i, false );
00228 npop ( netcontrol );
00229 }
00230 }
00231
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 int Building :: putResource ( int need, int resourcetype, bool queryonly, int scope, int player )
00247 {
00248 if ( need < 0 )
00249 return -getResource( -need, resourcetype, queryonly, scope, player );
00250 else {
00251 int placed;
00252 {
00253 PutResource putresource ( getMap(), scope );
00254 placed = putresource.getresource ( entryPosition.x, entryPosition.y, resourcetype, need, queryonly, player >= 0 ? player : getMap()->actplayer, scope );
00255 }
00256
00257
00258 return placed;
00259 }
00260 }
00261
00262
00263 int Building :: getResource ( int need, int resourcetype, bool queryonly, int scope, int player )
00264 {
00265 if ( need < 0 )
00266 return -putResource( -need, resourcetype, queryonly, scope, player );
00267 else {
00268 int got;
00269 {
00270 GetResource gr ( getMap(), scope );
00271 got = gr.getresource ( entryPosition.x, entryPosition.y, resourcetype, need, queryonly, player >= 0 ? player : getMap()->actplayer, scope );
00272 }
00273
00274
00275 return got;
00276
00277 }
00278 }
00279
00280 int Building :: getAvailableResource ( int need, int resourcetype, int scope ) const
00281 {
00282 int got;
00283 {
00284 GetResource gr ( getMap(), scope );
00285 got = gr.getresource ( entryPosition.x, entryPosition.y, resourcetype, need, true, getMap()->actplayer, scope );
00286 }
00287 return got;
00288 }
00289