00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <sigc++/sigc++.h>
00022
00023 #include "servicing.h"
00024
00025 #include "../vehicle.h"
00026 #include "../spfst.h"
00027 #include "../containercontrols.h"
00028 #include "../gameoptions.h"
00029
00030 #include "consumeresource.h"
00031 #include "consumeammo.h"
00032
00033 #include "context.h"
00034
00035 enum TransferLimitation { NONE, GET, ALL };
00036
00037 TransferLimitation getTransferLimitation( const ContainerBase* target )
00038 {
00039 if ( target->getOwner() == target->getMap()->actplayer )
00040 return NONE;
00041
00042 if ( target->getMap()->player[target->getMap()->actplayer].diplomacy.isAllied( target->getOwner() ))
00043 return NONE;
00044
00045 if ( target->getMap()->player[target->getMap()->actplayer].diplomacy.getState( target->getOwner() ) >= PEACE )
00046 return GET;
00047
00048 return ALL;
00049 }
00050
00051
00052
00053 ResourceWatch::ResourceWatch( ContainerBase* container )
00054 {
00055 this->container = container;
00056 orgAmount = available = container->getResource( Resources( maxint, maxint, maxint), true );
00057 storagelimit = container->putResource( Resources( maxint, maxint, maxint), true );
00058 for ( int r = 0; r < 3; ++r )
00059 if ( maxint - available.resource(r) > storagelimit.resource(r))
00060 storagelimit.resource(r) += available.resource(r);
00061 else
00062 storagelimit.resource(r) = maxint;
00063 };
00064
00065 ContainerBase* ResourceWatch::getContainer()
00066 {
00067 return container;
00068 };
00069
00070 const Resources ResourceWatch::amount()
00071 {
00072 return available;
00073 }
00074
00075
00076 const Resources ResourceWatch::avail() {
00077 TransferLimitation limit = getTransferLimitation( container );
00078 if ( limit == ALL )
00079 return Resources();
00080
00081 if ( limit == GET ) {
00082 Resources res = available - orgAmount;
00083 for ( int r = 0; r < resourceTypeNum; ++r )
00084 if ( res.resource(r) < 0 )
00085 res.resource(r) = 0;
00086
00087 return res;
00088 }
00089
00090 return available;
00091 };
00092
00093 const Resources ResourceWatch::limit() {
00094 if( getTransferLimitation( container ) == ALL )
00095 return available;
00096 else
00097 return storagelimit;
00098 };
00099
00100 bool ResourceWatch::putResource( int resourcetype, int amount )
00101 {
00102 Resources rr = available;
00103 rr.resource(resourcetype) += amount;
00104
00105 for ( int r = 0; r < resourceTypeNum; ++r)
00106 if ( rr.resource(r) > storagelimit.resource(r))
00107 return false;
00108 available = rr;
00109 sigChanged( resourcetype );
00110 return true;
00111 }
00112
00113
00114 bool ResourceWatch::getResource( int resourcetype, int amount )
00115 {
00116 if ( available.resource(resourcetype) >= amount ) {
00117 available.resource(resourcetype) -= amount;
00118 sigChanged( resourcetype );
00119 return true;
00120 }
00121 return false;
00122 }
00123
00124 bool ResourceWatch::getResources( Resources res )
00125 {
00126 bool b = true;
00127 for ( int r = 0; r < resourceTypeNum; ++r)
00128 if ( res.resource(r) > 0 )
00129 if ( !getResource( r, res.resource(r) ))
00130 b = false;
00131 return b;
00132 }
00133
00134
00135
00136 ResourceWatch& Transferrable::getResourceWatch( const ContainerBase* unit )
00137 {
00138 assert( unit == source.getContainer() || unit == dest.getContainer() );
00139 if ( unit == source.getContainer() )
00140 return source;
00141 else
00142 return dest;
00143 }
00144
00145 ResourceWatch& Transferrable::getOpposingResourceWatch( const ContainerBase* unit )
00146 {
00147 return getResourceWatch ( opposingContainer( unit ));
00148 }
00149
00150 ContainerBase* Transferrable::opposingContainer( const ContainerBase* unit )
00151 {
00152 assert( unit == source.getContainer() || unit == dest.getContainer() );
00153 if ( unit == dest.getContainer() )
00154 return source.getContainer();
00155 else
00156 return dest.getContainer();
00157 }
00158
00159 void Transferrable::show( const ContainerBase* unit )
00160 {
00161 assert( unit == source.getContainer() || unit == dest.getContainer() );
00162 if ( unit == dest.getContainer() )
00163 return sigDestAmount( ASCString::toString( getAmount( unit )));
00164 else
00165 return sigSourceAmount( ASCString::toString( getAmount( unit )));
00166 }
00167
00168
00169 Transferrable::Transferrable( ResourceWatch& s, ResourceWatch& d ) : source( s ) , dest( d ) {};
00170
00171 ContainerBase* Transferrable::getSrcContainer()
00172 {
00173 return source.getContainer();
00174 }
00175
00176 ContainerBase* Transferrable::getDstContainer()
00177 {
00178 return dest.getContainer();
00179 }
00180
00181 bool Transferrable::setDestAmount( long amount )
00182 {
00183 return setAmount( getDstContainer(), amount ) == amount;
00184 }
00185
00186 void Transferrable::showAll()
00187 {
00188 show( source.getContainer() );
00189 show( dest.getContainer() );
00190 }
00191
00192 int Transferrable::setAmount( ContainerBase* target, int newamount )
00193 {
00194 transfer( target, newamount - getAmount( target ) );
00195 return getAmount( target );
00196 }
00197
00198 void Transferrable::fill( ContainerBase* target )
00199 {
00200 setAmount( target, getMax( target, true ));
00201 }
00202
00203
00204 void Transferrable::empty( ContainerBase* target )
00205 {
00206 setAmount( target, 0 );
00207 }
00208
00209
00210
00211 class AmmoTransferrable : public Transferrable {
00212 private:
00213 int ammoType;
00214 int sourceAmmo;
00215 int destAmmo;
00216 map<const ContainerBase*,int> produced;
00217 map<const ContainerBase*,int> orgAmmo;
00218 bool& allowAmmoProduction;
00219
00220
00221 int& getAmmo( const ContainerBase* unit );
00222 int put( ContainerBase* c, int toPut, bool queryOnly );
00223 int get( ContainerBase* c, int toGet, bool queryOnly );
00224 void executeTransfer( ContainerBase* from, ContainerBase* to, int amount, const Context& context );
00225
00226 public:
00227 AmmoTransferrable( int ammo, ResourceWatch& src, ResourceWatch& dst, bool& allowProduction );
00228 ASCString getName();
00229
00230 int getID();
00231 int getMax( ContainerBase* c, bool avail );
00232 int getMin( ContainerBase* c, bool avail );
00233 int getAmount ( const ContainerBase* target );
00234 int transfer( ContainerBase* target, int delta );
00235 bool isExchangable() const;
00236 void commit( const Context& context );
00237 };
00238
00239 class ResourceTransferrable : public Transferrable {
00240 private:
00241 int resourceType;
00242 bool exchangable;
00243 void warn();
00244 void srcChanged( int res );
00245 void dstChanged( int res );
00246 void executeTransfer( ContainerBase* from, ContainerBase* to, int amount, const Context& context );
00247 public:
00248 ResourceTransferrable( int resource, ResourceWatch& src, ResourceWatch& dst, bool isExchangable = true );
00249 ASCString getName();
00250 int getID();
00251 int getMax( ContainerBase* c, bool avail );
00252 int getMin( ContainerBase* c, bool avail );
00253 int getAmount ( const ContainerBase* target );
00254 int getAvail ( const ContainerBase* target );
00255 int transfer( ContainerBase* target, int delta );
00256 bool isExchangable() const;
00257 void commit(const Context& context);
00258 };
00259
00260
00261
00262
00263
00264 void ResourceTransferrable::warn()
00265 {
00266 warningMessage( "Inconsistency in ResourceTransfer");
00267 };
00268
00269 void ResourceTransferrable::srcChanged( int res )
00270 {
00271 if ( res == resourceType ) {
00272 show( source.getContainer() );
00273 }
00274 }
00275
00276 void ResourceTransferrable::dstChanged( int res )
00277 {
00278 if ( res == resourceType ) {
00279 show( dest.getContainer() );
00280 }
00281 }
00282
00283
00284 void ResourceTransferrable::executeTransfer( ContainerBase* from, ContainerBase* to, int amount, const Context& context )
00285 {
00286 if ( amount == 0 )
00287 return;
00288
00289 if ( amount < 0 )
00290 executeTransfer( to, from, -amount, context );
00291 else
00292 if ( amount > 0 ) {
00293 Resources r;
00294 r.resource(resourceType) = amount;
00295
00296 ActionResult res = (new ConsumeResource( from, r ))->execute( context );
00297 if ( !res.successful() )
00298 throw res;
00299
00300 res = (new ConsumeResource( to, -r))->execute( context );
00301 if ( !res.successful() )
00302 throw res;
00303
00304 }
00305 }
00306
00307
00308 ResourceTransferrable::ResourceTransferrable( int resource, ResourceWatch& src, ResourceWatch& dst, bool isExchangable )
00309 : Transferrable( src, dst ), resourceType ( resource ), exchangable( isExchangable )
00310 {
00311 source.sigChanged.connect( SigC::slot( *this, &ResourceTransferrable::srcChanged ));
00312 dest.sigChanged.connect( SigC::slot( *this, &ResourceTransferrable::dstChanged ));
00313 };
00314
00315 ASCString ResourceTransferrable::getName()
00316 {
00317 return Resources::name( resourceType );
00318 }
00319
00320 int ResourceTransferrable::getID()
00321 {
00322 return resourceType + 1000;
00323 };
00324
00325 int ResourceTransferrable::getMax( ContainerBase* c, bool avail )
00326 {
00327 if ( avail ) {
00328 int needed = getResourceWatch( c ).limit().resource(resourceType) - getAvail( c );
00329 int av = min ( needed, getOpposingResourceWatch( c ).avail().resource(resourceType) );
00330
00331 return getAvail( c ) + av;
00332 } else
00333 return getResourceWatch( c ).limit().resource(resourceType);
00334 }
00335
00336 int ResourceTransferrable::getMin( ContainerBase* c, bool avail )
00337 {
00338 if ( avail ) {
00339 int space = getOpposingResourceWatch( c ).limit().resource(resourceType) - getOpposingResourceWatch( c ).avail().resource(resourceType);
00340 if ( space > getAvail( c ) )
00341 return 0;
00342 else
00343 return getAvail( c ) - space;
00344 } else
00345 return 0;
00346 }
00347
00348 int ResourceTransferrable::getAmount ( const ContainerBase* target )
00349 {
00350 return getResourceWatch( target ).amount().resource(resourceType);
00351 }
00352
00353 int ResourceTransferrable::getAvail ( const ContainerBase* target )
00354 {
00355 return getResourceWatch( target ).avail().resource(resourceType);
00356 }
00357
00358 int ResourceTransferrable::transfer( ContainerBase* target, int delta )
00359 {
00360 if ( delta < 0 )
00361 return transfer( opposingContainer( target ), -delta );
00362 else {
00363 delta = min( delta, getOpposingResourceWatch( target ).avail().resource(resourceType) );
00364 delta = min( delta, getResourceWatch( target ).limit().resource(resourceType) - getAvail( target ));
00365 getOpposingResourceWatch( target ).getResource( resourceType, delta );
00366 getResourceWatch( target ).putResource(resourceType, delta);
00367 return delta;
00368 }
00369 }
00370
00371 bool ResourceTransferrable::isExchangable() const
00372 {
00373 return exchangable;
00374 }
00375
00376 void ResourceTransferrable::commit(const Context& context)
00377 {
00378 ContainerBase* target = dest.getContainer();
00379 executeTransfer( source.getContainer(), target, getAmount( target ) - target->getResource( maxint, resourceType, true ), context );
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 int& AmmoTransferrable::getAmmo( const ContainerBase* unit )
00391 {
00392 assert( unit == source.getContainer() || unit == dest.getContainer() );
00393 if ( unit == source.getContainer() )
00394 return sourceAmmo;
00395 else
00396 return destAmmo;
00397 }
00398
00399 int AmmoTransferrable::put( ContainerBase* c, int toPut, bool queryOnly )
00400 {
00401 TransferLimitation limit = getTransferLimitation( c );
00402
00403 if ( limit == ALL )
00404 return 0;
00405
00406 int undoProduction = min( toPut, produced[c]);
00407 if ( undoProduction > 0 ) {
00408 if ( !queryOnly ) {
00409 for ( int r = 0; r < resourceTypeNum; ++r )
00410 getResourceWatch( c ).putResource( r, ammoProductionCost[ammoType][r] * undoProduction );
00411
00412 produced[c] -= undoProduction;
00413 }
00414 }
00415 toPut -= undoProduction;
00416
00417 toPut = min( toPut, c->maxAmmo(ammoType) - getAmmo( c ));
00418
00419 if( !queryOnly ) {
00420 getAmmo(c) += toPut;
00421 show(c);
00422 }
00423
00424 return toPut + undoProduction;
00425 }
00426
00427 int AmmoTransferrable::get( ContainerBase* c, int toGet, bool queryOnly )
00428 {
00429 TransferLimitation limit = getTransferLimitation( c );
00430
00431 if ( limit == ALL )
00432 return 0;
00433
00434 int gettable;
00435
00436 if ( limit == GET ) {
00437 gettable = getAmmo(c) - orgAmmo[c];
00438 if ( gettable < 0 )
00439 gettable = 0;
00440 } else
00441 gettable = getAmmo( c );
00442
00443 int got = min ( toGet, gettable);
00444 int toProduce = toGet - got;
00445
00446 if ( allowAmmoProduction && toProduce > 0 && weaponAmmo[ammoType] && c->baseType->hasFunction(ContainerBaseType::AmmoProduction) ) {
00447 for ( int r = 0; r < resourceTypeNum; ++r ) {
00448 if ( ammoProductionCost[ammoType][r] ) {
00449 int produceable = getResourceWatch(c).avail().resource(r) / ammoProductionCost[ammoType][r];
00450 if ( produceable < toProduce )
00451 toProduce = produceable;
00452 }
00453 }
00454 if ( !queryOnly ) {
00455 Resources res;
00456 for ( int r = 0; r < resourceTypeNum; ++r )
00457 res.resource(r) = ammoProductionCost[ammoType][r] * toProduce;
00458
00459 getResourceWatch( c ).getResources( res );
00460 produced[c] += toProduce;
00461
00462 getAmmo(c) -= got;
00463 }
00464 got += toProduce;
00465 } else {
00466 if ( !queryOnly ) {
00467 getAmmo(c) -= got;
00468 show( c );
00469 }
00470
00471 }
00472 return got;
00473 }
00474
00475
00476 void AmmoTransferrable::executeTransfer( ContainerBase* from, ContainerBase* to, int amount, const Context& context )
00477 {
00478 if ( amount < 0 )
00479 executeTransfer( to, from, -amount, context );
00480 else
00481 if ( amount > 0 ) {
00482 auto_ptr<ConsumeAmmo> ca1 ( new ConsumeAmmo( from, ammoType, -1, amount ));
00483 ca1->setAmmoProduction( allowAmmoProduction );
00484
00485 ActionResult res = ca1->execute( context );
00486 if( res.successful() )
00487 ca1.release();
00488 else
00489 throw res;
00490
00491 auto_ptr<ConsumeAmmo> ca2 ( new ConsumeAmmo( to, ammoType, -1, -amount ));
00492 res = ca2->execute( context );
00493 if( res.successful() )
00494 ca2.release();
00495 else
00496 throw res;
00497 }
00498 }
00499
00500 AmmoTransferrable::AmmoTransferrable( int ammo, ResourceWatch& src, ResourceWatch& dst, bool& allowProduction ) : Transferrable( src, dst ), ammoType ( ammo ), allowAmmoProduction( allowProduction )
00501 {
00502 sourceAmmo = src.getContainer()->getAmmo( ammoType, maxint, true );
00503 destAmmo = dst.getContainer()->getAmmo( ammoType, maxint, true );
00504
00505 orgAmmo[src.getContainer()] = sourceAmmo;
00506 orgAmmo[dst.getContainer()] = destAmmo;
00507 };
00508
00509 ASCString AmmoTransferrable::getName()
00510 {
00511 return cwaffentypen[ ammoType ];
00512 }
00513
00514 int AmmoTransferrable::getID()
00515 {
00516
00517 return ammoType + 2000;
00518 };
00519
00520 int AmmoTransferrable::getMax( ContainerBase* c, bool avail )
00521 {
00522 if ( avail ) {
00523 int needed = c->maxAmmo( ammoType ) - getAmount( c );
00524 int av = get( opposingContainer( c ), needed, true );
00525 return getAmount( c ) + av;
00526 } else
00527 return c->maxAmmo( ammoType );
00528 }
00529
00530 int AmmoTransferrable::getMin( ContainerBase* c, bool avail )
00531 {
00532 if ( avail ) {
00533 int storable = opposingContainer(c)->maxAmmo(ammoType) - getAmmo( opposingContainer(c) );
00534 int transferable = min( getAmmo(c), storable );
00535 return getAmmo(c) - transferable;
00536 } else
00537 return 0;
00538 }
00539
00540 int AmmoTransferrable::getAmount ( const ContainerBase* target )
00541 {
00542 return getAmmo( target );
00543 }
00544
00545 int AmmoTransferrable::transfer( ContainerBase* target, int delta )
00546 {
00547 if ( delta < 0 )
00548 return transfer( opposingContainer( target ), -delta );
00549 else {
00550 delta = min( delta, put( target, delta, true ));
00551 int got = get( opposingContainer( target ), delta, false );
00552 put( target, got, false );
00553 return got;
00554 }
00555 }
00556
00557 bool AmmoTransferrable::isExchangable() const
00558 {
00559 return true;
00560 };
00561
00562 void AmmoTransferrable::commit( const Context& context )
00563 {
00564 executeTransfer( source.getContainer(), dest.getContainer(), destAmmo - orgAmmo[dest.getContainer()], context );
00565 }
00566
00567
00568
00569
00570 const SingleWeapon* ServiceChecker :: getServiceWeapon()
00571 {
00572 Vehicle* srcVehicle = dynamic_cast<Vehicle*>(source);
00573 if ( !srcVehicle )
00574 return false;
00575
00576 const SingleWeapon* serviceWeapon = NULL;
00577 for (int i = 0; i < srcVehicle->typ->weapons.count ; i++)
00578 if ( srcVehicle->typ->weapons.weapon[i].service() )
00579 serviceWeapon = &srcVehicle->typ->weapons.weapon[i];
00580
00581 return serviceWeapon;
00582 }
00583
00584 bool ServiceChecker::serviceWeaponFits( ContainerBase* dest )
00585 {
00586 const SingleWeapon* serviceWeapon = getServiceWeapon();
00587 if ( serviceWeapon )
00588 if ( (ignoreChecks & ignoreHeight) || (serviceWeapon->sourceheight & source->getHeight()) )
00589 if ( (ignoreChecks & ignoreHeight) || (serviceWeapon->targ & dest->getHeight() )) {
00590 int dist = beeline( source->getPosition(), dest->getPosition() );
00591 if ( (ignoreChecks & ignoreDistance) || (serviceWeapon->mindistance <= dist && serviceWeapon->maxdistance >= dist) )
00592 if ( serviceWeapon->targetingAccuracy[dest->baseType->getMoveMalusType()] > 0 )
00593 if ( (ignoreChecks & ignoreHeight) || (serviceWeapon->efficiency[6+getheightdelta(source,dest)] > 0 ))
00594 if ( ! ((source->getHeight() & (chtieffliegend | chfliegend | chhochfliegend)) && dest->baseType->hasFunction(ContainerBaseType::NoInairRefuelling)))
00595 return true;
00596
00597 }
00598
00599 return false;
00600 }
00601
00602 ServiceChecker :: ServiceChecker( ContainerBase* src, int skipChecks ) : source(src), ignoreChecks( skipChecks )
00603 {
00604 }
00605
00606
00607 void ServiceChecker :: check( ContainerBase* dest )
00608 {
00609 MapCoordinate spos = source->getPosition();
00610 MapCoordinate dpos = dest->getPosition();
00611 bool externalTransfer = spos != dpos;
00612
00613 if ( source->isBuilding() && dest->isBuilding() )
00614 return;
00615
00616 if ( getTransferLimitation( dest ) == ALL )
00617 return;
00618
00619
00620 if ( source->getMap()->getPlayer(source).diplomacy.getState(dest->getOwner()) < PEACE )
00621 return;
00622
00623 static ContainerBaseType::ContainerFunctions resourceVehicleFunctions[resourceTypeNum] = { ContainerBaseType::ExternalEnergyTransfer,
00624 ContainerBaseType::ExternalMaterialTransfer,
00625 ContainerBaseType::ExternalFuelTransfer };
00626
00627
00628 for ( int r = 0; r < resourceTypeNum; r++ ) {
00629 if ( externalTransfer ) {
00630 Vehicle* srcVehicle = dynamic_cast<Vehicle*>(source);
00631 if ( !srcVehicle ) {
00632 Building* bld = dynamic_cast<Building*>(source);
00633 assert(bld);
00634 bool active = source->baseType->hasFunction( resourceVehicleFunctions[r] ) || dest->baseType->hasFunction( resourceVehicleFunctions[r] );
00635 if ( (ignoreChecks & ignoreHeight) || (bld->typ->externalloadheight & dest->getHeight()) )
00636 if ( (ignoreChecks & ignoreDistance) || beeline(source->getPosition(), dest->getPosition()) < 20 )
00637 resource( dest, r, active );
00638 } else {
00639 if ( serviceWeaponFits( dest )) {
00640 bool active = source->baseType->hasFunction( resourceVehicleFunctions[r] ) || dest->baseType->hasFunction( resourceVehicleFunctions[r] );
00641 resource( dest, r, active );
00642 }
00643 }
00644
00645 } else {
00646 bool active = (source->getStorageCapacity().resource(r) || source->isBuilding() )
00647 && (dest->getStorageCapacity().resource(r) || dest->isBuilding());
00648 resource( dest, r, active );
00649 }
00650 }
00651
00652
00653
00654
00655 for ( int a = 0; a < weaponTypeNum; ++a ) {
00656 if ( source->maxAmmo( a ) && dest->maxAmmo( a )) {
00657 if ( weaponAmmo[a] ) {
00658 if ( externalTransfer ) {
00659 if ( source->baseType->hasFunction( ContainerBaseType::ExternalAmmoTransfer ) || dest->baseType->hasFunction( ContainerBaseType::ExternalAmmoTransfer ) ) {
00660 Vehicle* srcVehicle = dynamic_cast<Vehicle*>(source);
00661 if ( !srcVehicle ) {
00662 Building* bld = dynamic_cast<Building*>(source);
00663 assert(bld);
00664 if ( (ignoreChecks & ignoreHeight) || (bld->typ->externalloadheight & dest->getHeight()) )
00665 if ( (ignoreChecks & ignoreDistance) || beeline(source->getPosition(), dest->getPosition()) < 20 )
00666 ammo(dest, a);
00667 } else {
00668 if ( serviceWeaponFits( dest ) )
00669 ammo(dest, a);
00670 }
00671 }
00672 } else {
00673 ammo(dest, a);
00674 }
00675 }
00676 }
00677 }
00678
00679
00680
00681 if ( externalTransfer ) {
00682 Vehicle* srcVehicle = dynamic_cast<Vehicle*>(source);
00683 if ( srcVehicle ) {
00684 if ( srcVehicle->baseType->hasFunction( ContainerBaseType::ExternalRepair ))
00685 if ( serviceWeaponFits( dest ) && dest->damage > 0 ) {
00686 repair( dest );
00687 }
00688 }
00689
00690 } else {
00691 if ( source->baseType->hasFunction( ContainerBaseType::InternalUnitRepair ))
00692 repair( dest );
00693 }
00694
00695
00696
00697 }
00698
00699
00700
00701 void ServiceTargetSearcher::fieldChecker( const MapCoordinate& pos )
00702 {
00703 MapField* fld = gamemap->getField( pos );
00704 if ( fld && fld->getContainer() )
00705 check( fld->getContainer() );
00706 }
00707
00708 void ServiceTargetSearcher::addTarget( ContainerBase* target )
00709 {
00710 if ( find( targets.begin(), targets.end(), target ) == targets.end() )
00711 targets.push_back( target );
00712 }
00713
00714 void ServiceTargetSearcher::ammo( ContainerBase* dest, int type )
00715 {
00716 if ( checks & checkAmmo )
00717 addTarget ( dest );
00718 }
00719
00720 void ServiceTargetSearcher::resource( ContainerBase* dest, int type, bool active )
00721 {
00722 if ( checks & checkResources )
00723 if ( active )
00724 addTarget ( dest );
00725 }
00726
00727 void ServiceTargetSearcher::repair( ContainerBase* dest)
00728 {
00729 if ( checks & checkRepair )
00730 addTarget ( dest );
00731 }
00732
00733
00734 ServiceTargetSearcher::ServiceTargetSearcher( ContainerBase* src, int checkFlags ) : ServiceChecker( src ), checks ( checkFlags )
00735 {
00736 gamemap = src->getMap();
00737 }
00738
00739
00740 bool ServiceTargetSearcher::externallyAvailable()
00741 {
00742 Vehicle* srcVehicle = dynamic_cast<Vehicle*>(source);
00743 if ( srcVehicle ) {
00744 if ( srcVehicle->attacked )
00745 return false;
00746
00747
00748 if ( srcVehicle->reactionfire.getStatus() == Vehicle::ReactionFire::off || srcVehicle->baseType->hasFunction(ContainerBaseType::MoveWithReactionFire))
00749 if ( source->getMap()->getField( source->getPosition() )->unitHere( srcVehicle )) {
00750 const SingleWeapon* weap = getServiceWeapon();
00751 if( weap )
00752 if ( source->baseType->hasFunction( ContainerBaseType::ExternalEnergyTransfer ) ||
00753 source->baseType->hasFunction( ContainerBaseType::ExternalMaterialTransfer ) ||
00754 source->baseType->hasFunction( ContainerBaseType::ExternalFuelTransfer ) ||
00755 source->baseType->hasFunction( ContainerBaseType::ExternalAmmoTransfer ))
00756 return true;
00757
00758 }
00759 } else {
00760 if ( source->baseType->hasFunction( ContainerBaseType::ExternalEnergyTransfer ) )
00761
00762 return true;
00763
00764 if ( source->baseType->hasFunction( ContainerBaseType::ExternalMaterialTransfer ) )
00765
00766 return true;
00767
00768 if ( source->baseType->hasFunction( ContainerBaseType::ExternalFuelTransfer ) )
00769
00770 return true;
00771
00772 }
00773 return false;
00774 }
00775
00776
00777 void ServiceTargetSearcher::startSearch()
00778 {
00779 Vehicle* srcVehicle = dynamic_cast<Vehicle*>(source);
00780 if ( srcVehicle ) {
00781 if ( source->getMap()->getField( source->getPosition() )->unitHere( srcVehicle )) {
00782 const SingleWeapon* weap = getServiceWeapon();
00783 if( weap )
00784 circularFieldIterator(source->getMap(), source->getPosition(), weap->maxdistance / maxmalq, (weap->mindistance + maxmalq - 1) / maxmalq, FieldIterationFunctor( this, &ServiceTargetSearcher::fieldChecker ) );
00785 }
00786 } else
00787 circularFieldIterator(source->getMap(), source->getPosition(), 1, 1, FieldIterationFunctor( this, &ServiceTargetSearcher::fieldChecker ) );
00788
00789 for ( ContainerBase::Cargo::const_iterator i = source->getCargo().begin(); i != source->getCargo().end(); ++i )
00790 if ( *i )
00791 check( *i );
00792 };
00793
00794
00795
00796 void TransferHandler::ammo( ContainerBase* dest, int type )
00797 {
00798 transfers.push_back ( new AmmoTransferrable( type, sourceRes, destRes, allowProduction ));
00799 }
00800
00801 void TransferHandler::resource( ContainerBase* dest, int type, bool active )
00802 {
00803 transfers.push_back( new ResourceTransferrable( type, sourceRes, destRes, active ));
00804 }
00805
00806 TransferHandler::TransferHandler( ContainerBase* src, ContainerBase* dst, int flags ) : ServiceChecker( src, flags ), sourceRes( src ), destRes( dst ), source(src), dest(dst)
00807 {
00808 allowProduction = CGameOptions::Instance()->autoproduceammunition ;
00809
00810 if ( dest->getMap()->player[dest->getMap()->actplayer].diplomacy.getState( dest->getOwner() ) <= TRUCE )
00811 return;
00812
00813 check( dst );
00814 };
00815
00816 bool TransferHandler::allowAmmoProduction( bool allow )
00817 {
00818 if ( ammoProductionPossible() ) {
00819 allowProduction = allow;
00820 updateRanges();
00821 return true;
00822 } else
00823 return false;
00824 }
00825
00826
00827 TransferHandler::~TransferHandler()
00828 {
00829 if ( allowProduction != CGameOptions::Instance()->autoproduceammunition ) {
00830 CGameOptions::Instance()->autoproduceammunition = allowProduction ;
00831 CGameOptions::Instance()->setChanged();
00832 }
00833 }
00834
00835 bool TransferHandler::ammoProductionPossible()
00836 {
00837 return source->baseType->hasFunction( ContainerBaseType::AmmoProduction ) || dest->baseType->hasFunction( ContainerBaseType::AmmoProduction );
00838 }
00839
00840 TransferHandler::Transfers& TransferHandler::getTransfers()
00841 {
00842 return transfers;
00843 }
00844
00845 void TransferHandler::fillDest()
00846 {
00847 for ( Transfers::iterator i = transfers.begin(); i != transfers.end(); ++i )
00848 if ( (*i)->isExchangable())
00849 (*i)->fill( dest );
00850 }
00851
00852 void TransferHandler::fillDestAmmo()
00853 {
00854 for ( Transfers::iterator i = transfers.begin(); i != transfers.end(); ++i )
00855 if ( (*i)->isExchangable())
00856 if ( dynamic_cast<AmmoTransferrable*>(*i))
00857 (*i)->fill( dest );
00858 }
00859
00860 void TransferHandler::fillDestResource()
00861 {
00862 for ( Transfers::iterator i = transfers.begin(); i != transfers.end(); ++i )
00863 if ( (*i)->isExchangable())
00864 if ( dynamic_cast<ResourceTransferrable*>(*i))
00865 (*i)->fill( dest );
00866 }
00867
00868
00869 void TransferHandler::emptyDest()
00870 {
00871 for ( Transfers::iterator i = transfers.begin(); i != transfers.end(); ++i )
00872 (*i)->empty( dest );
00873
00874 }
00875
00876
00877 bool TransferHandler::commit( const Context& context )
00878 {
00879 for ( Transfers::iterator i = transfers.begin(); i != transfers.end(); ++i )
00880 (*i)->commit( context );
00881
00882 return true;
00883 }
00884
00885
00886