00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "ai_common.h"
00019
00020 #include "../actions/repairunitcommand.h"
00021 #include "../actions/servicing.h"
00022 #include "../actions/servicecommand.h"
00023
00024
00025 AI :: ServiceOrder :: ServiceOrder ( AI* _ai, AI::ServiceOrder::Service _requiredService, int UnitID, int _pos )
00026 {
00027 active = false;
00028 failure = 0;
00029 ai = _ai;
00030 targetUnitID = UnitID;
00031 requiredService = _requiredService;
00032 serviceUnitID = 0;
00033 position = _pos;
00034 time = ai->getMap()->time;
00035
00036 nextServiceBuildingDistance = -1;
00037 nextServiceBuilding = NULL;
00038 if ( ai->getMap()->getUnit ( UnitID )->canMove()) {
00039 MapCoordinate3D sb = ai->findServiceBuilding ( *this, &nextServiceBuildingDistance );
00040 if ( sb.valid() )
00041 nextServiceBuilding = ai->getMap()->getField( sb )->building;
00042 }
00043 }
00044
00045 AI :: ServiceOrder :: ServiceOrder ( AI* _ai, tnstream& stream )
00046 {
00047 active = false;
00048 failure = 0;
00049 ai = _ai;
00050 read ( stream );
00051 }
00052
00053 void AI :: ServiceOrder :: activate( ServiceOrder& so )
00054 {
00055 so.active = true;
00056 }
00057
00058
00059 const int currentServiceOrderVersion = 10002;
00060
00061 void AI :: ServiceOrder :: read ( tnstream& stream )
00062 {
00063 int version = stream.readInt( );
00064 if ( version > currentServiceOrderVersion )
00065 throw tinvalidversion ( "AI :: ServiceOrder", currentServiceOrderVersion, version );
00066 targetUnitID = stream.readInt ( );
00067 serviceUnitID = stream.readInt ( );
00068 position = stream.readInt ( );
00069 time.abstime = stream.readInt ( );
00070 if ( version >= 10001 ) {
00071 int i= stream.readInt();
00072 if ( i ) {
00073 MapCoordinate3D mc;
00074 mc.read ( stream );
00075 nextServiceBuilding = ai->getMap()->getField( mc )->building;
00076 nextServiceBuildingDistance = stream.readInt();
00077 } else
00078 nextServiceBuilding = NULL;
00079
00080 if ( version >= 10002 )
00081 requiredService = ServiceOrder::Service( stream.readInt() );
00082 }
00083 }
00084
00085 void AI :: ServiceOrder :: write ( tnstream& stream ) const
00086 {
00087 stream.writeInt( currentServiceOrderVersion );
00088 stream.writeInt ( targetUnitID );
00089 stream.writeInt ( serviceUnitID );
00090 stream.writeInt ( position );
00091 stream.writeInt ( time.abstime );
00092 if ( nextServiceBuilding ) {
00093 stream.writeInt ( 1 );
00094 nextServiceBuilding->getEntry().write ( stream );
00095 stream.writeInt ( nextServiceBuildingDistance );
00096 } else {
00097 stream.writeInt ( 0 );
00098 }
00099 stream.writeInt ( requiredService );
00100 }
00101
00102 bool AI :: ServiceOrder :: completelyFailed ()
00103 {
00104 return failure > 2 ;
00105 }
00106
00107
00108 int AI::ServiceOrder::getServiceID() const
00109 {
00110 if ( requiredService == srv_ammo )
00111 return 2000+getTargetUnit()->typ->weapons.weapon[position].getScalarWeaponType();
00112
00113 if ( requiredService == srv_resource )
00114 return 1000+position;
00115
00116 return -1;
00117 }
00118
00119
00120 int AI::ServiceOrder::possible ( Vehicle* supplier )
00121 {
00122 if ( !ai->getMap()->getField( getTargetUnit()->getPosition())->unitHere ( getTargetUnit() ))
00123 return 0;
00124
00125 TransferHandler transferHandler( supplier, getTargetUnit(), TransferHandler::ignoreHeight + TransferHandler::ignoreDistance );
00126
00127 int serviceAmount = 0;
00128 for ( TransferHandler::Transfers::const_iterator i = transferHandler.getTransfers().begin(); i != transferHandler.getTransfers().end(); ++i ) {
00129 if ( (*i)->getID() == getServiceID() ) {
00130 int now = (*i)->getAmount(getTargetUnit());
00131 int poss = (*i)->getMax( getTargetUnit(), true);
00132 int mx = (*i)->getMax( getTargetUnit(), false);
00133 if ( poss > now && mx > now ) {
00134 int percentage = 100 * (poss-now) / (mx - now );
00135 serviceAmount += percentage;
00136 }
00137 }
00138
00139 }
00140 return serviceAmount;
00141 }
00142
00143
00144 bool AI::ServiceOrder::execute1st ( Vehicle* supplier )
00145 {
00146 Vehicle* targ = getTargetUnit();
00147 MapCoordinate3D meet;
00148
00149 vector<MapCoordinate3D> dest;
00150 for ( int h = 0; h < 8; h++ ) {
00151 if ( supplier->typ->height & ( 1<<h)) {
00152 for ( int i = 0; i < sidenum; i++ ) {
00153 int x = targ->xpos;
00154 int y = targ->ypos;
00155 getnextfield ( x, y, i );
00156 MapField* fld = ai->getMap()->getField ( x, y );
00157 if ( fld && fieldAccessible ( fld, supplier, 1<<h ) == 2 && !fld->building && !fld->vehicle ) {
00158 bool result = false;
00159 TemporaryContainerStorage tus ( supplier );
00160 supplier->xpos = x;
00161 supplier->ypos = y;
00162 supplier->height = 1 << h;
00163
00164
00165 TransferHandler transferHandler( supplier, getTargetUnit() );
00166
00167 for ( TransferHandler::Transfers::const_iterator i = transferHandler.getTransfers().begin(); i != transferHandler.getTransfers().end(); ++i )
00168 if ( (*i)->getID() == getServiceID() )
00169 result = true;
00170
00171 tus.restore();
00172
00173 if ( result )
00174 dest.push_back ( MapCoordinate3D(x, y, 1<<h ));
00175 }
00176 }
00177 }
00178 }
00179
00180 if ( !dest.size() )
00181 return false;
00182
00183 AStar3D ast ( ai->getMap(), supplier, true, supplier->typ->maxSpeed()*6 );
00184 AStar3D::Path path;
00185 ast.findPath( path, dest );
00186 if ( path.size() ) {
00187 meet = *path.rbegin();
00188
00189 int supplySpeed = supplier->maxMovement();
00190 if ( !canWait() )
00191 supplySpeed += targ->maxMovement();
00192 if ( supplySpeed == 0 )
00193 fatalError ( "AI::ServiceOrder::execute1st - supplySpeed is 0 ");
00194
00195 if ( !targ->maxMovement() || beeline(supplier,targ) / supplySpeed < nextServiceBuildingDistance/targ->maxMovement() || nextServiceBuildingDistance < 0 ) {
00196 supplier->aiparam[ai->getPlayerNum()]->dest = meet;
00197 supplier->aiparam[ai->getPlayerNum()]->setTask( AiParameter::tsk_move );
00198 supplier->aiparam[ai->getPlayerNum()]->dest_nwid = targ->networkid;
00199
00200 setServiceUnit ( supplier );
00201 return true;
00202 }
00203 }
00204 return false;
00205 }
00206
00207 void AI::ServiceOrder::setServiceUnit ( Vehicle* veh )
00208 {
00209 if ( veh )
00210 serviceUnitID = veh->networkid;
00211 else
00212 serviceUnitID = 0;
00213 }
00214
00215 void AI::ServiceOrder::releaseServiceUnit ( ServiceOrder& so )
00216 {
00217 Vehicle* veh = so.getServiceUnit();
00218 if ( veh ) {
00219 so.setServiceUnit ( NULL );
00220 veh->aiparam[so.ai->getPlayerNum()]->resetTask();
00221 }
00222 }
00223
00224
00225 bool AI::ServiceOrder::timeOut ( )
00226 {
00227 GameTime t = time;
00228 t.set ( t.turn() + 2, t.move() );
00229 return ( t.abstime <= ai->getMap()->time.abstime );
00230 }
00231
00232 bool AI::ServiceOrder::canWait( )
00233 {
00234 if ( requiredService == srv_repair )
00235 return false;
00236
00237 if ( requiredService == srv_ammo ) {
00238 if ( getTargetUnit()->ammo[position] )
00239 return true;
00240
00241 if ( ai->targetsNear( getTargetUnit() ))
00242 return true;
00243 }
00244
00245 bool fuelLack = requiredService == srv_resource && position == 2 ;
00246 bool couldWait = fuelLack || !timeOut();
00247 if ( couldWait )
00248 return serviceUnitExists();
00249 else
00250 return false;
00251 }
00252
00253 bool AI::ServiceOrder::serviceUnitExists()
00254 {
00255 for ( Player::VehicleList::iterator vi = ai->getPlayer().vehicleList.begin(); vi != ai->getPlayer().vehicleList.end(); vi++ )
00256 if ( possible ( *vi ))
00257 return true;
00258 return false;
00259 }
00260
00261
00262 bool AI::ServiceOrder::valid ( ) const
00263 {
00264 switch ( requiredService ) {
00265 case srv_repair : return getTargetUnit()->damage > 0;
00266 case srv_ammo : return getTargetUnit()->ammo[position] < getTargetUnit()->typ->weapons.weapon[position].count;
00267 case srv_resource : return getTargetUnit()->getResource(getTargetUnit()->getStorageCapacity().resource(position), position, 1) < getTargetUnit()->getStorageCapacity().resource(position);
00268 default: return false;
00269 }
00270 }
00271
00272 bool AI::ServiceOrder::invalid ( const ServiceOrder& so )
00273 {
00274 return !so.valid();
00275 }
00276
00277 bool AI::ServiceOrder::operator==( const ServiceOrder& so ) const
00278 {
00279 return targetUnitID == so.targetUnitID
00280 && requiredService == so.requiredService
00281 && ai == so.ai
00282 && position == so.position;
00283 }
00284
00285 bool AI::ServiceOrder::operator!=( const ServiceOrder& so ) const
00286 {
00287 return ! (*this == so);
00288 }
00289
00290
00291 AI :: ServiceOrder :: ~ServiceOrder ( )
00292 {
00293 if ( active ) {
00294 Vehicle* serv = getServiceUnit();
00295 if ( serv )
00296 serv->aiparam[ai->getPlayerNum()]->resetTask();
00297 }
00298 }
00299
00300 AI::ServiceOrder& AI :: issueService ( AI::ServiceOrder::Service requiredService, int UnitID, int pos )
00301 {
00302 ServiceOrder so ( this, requiredService, UnitID, pos );
00303 ServiceOrderContainer::iterator soi = find ( serviceOrders.begin(), serviceOrders.end(), so );
00304 if ( soi == serviceOrders.end() ) {
00305 serviceOrders.push_back ( so );
00306 ServiceOrder::activate ( *serviceOrders.rbegin() );
00307 return *serviceOrders.rbegin();
00308 } else {
00309 return *soi;
00310 }
00311 }
00312
00313
00314
00315 void AI :: issueServices ( )
00316 {
00317 displaymessage2("issuing services ... ");
00318 serviceOrders.erase ( remove_if ( serviceOrders.begin(), serviceOrders.end(), ServiceOrder::targetDestroyed ), serviceOrders.end());
00319
00320 for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); vi++ ) {
00321 Vehicle* veh = *vi;
00322 if ( getMap()->getField( veh->getPosition() )->unitHere( veh )) {
00323 if ( veh->damage > config.damageLimit )
00324 issueService ( ServiceOrder::srv_repair, veh->networkid ) ;
00325
00326 for ( int i = 0; i< resourceTypeNum; i++ )
00327 if ( veh->maxMovement() )
00328 if ( veh->getResource(maxint, i, 1) < veh->getStorageCapacity().resource(i) * config.resourceLimit.resource(i) / 100 )
00329 issueService ( ServiceOrder::srv_resource, veh->networkid, i);
00330
00331 for ( int w = 0; w< veh->typ->weapons.count; w++ )
00332 if ( veh->typ->weapons.weapon[w].count )
00333 if ( veh->ammo[w] <= veh->typ->weapons.weapon[w].count * config.ammoLimit / 100 )
00334 issueService ( ServiceOrder::srv_ammo, veh->networkid, w);
00335 }
00336 }
00337 }
00338
00339 AI::ServiceOrder& AI :: issueRefuelOrder ( Vehicle* veh, bool returnImmediately )
00340 {
00341 ServiceOrder& so = issueService ( ServiceOrder::srv_resource, veh->networkid, Resources::Fuel);
00342 if ( returnImmediately ) {
00343 if ( RefuelConstraint::necessary ( veh, *this )) {
00344 RefuelConstraint apl ( *this, veh );
00345 veh->aiparam[getPlayerNum()]->dest = apl.getNearestRefuellingPosition ( true, true, false );
00346 if ( veh->aiparam[getPlayerNum()]->dest.valid() ) {
00347 veh->aiparam[getPlayerNum()]->setTask( AiParameter::tsk_serviceRetreat );
00348 runUnitTask ( veh );
00349 }
00350 } else {
00351
00352 }
00353 }
00354 return so;
00355 }
00356
00357
00358
00359 MapCoordinate3D AI :: findServiceBuilding ( const ServiceOrder& so, int* distance )
00360 {
00361 Vehicle* veh = so.getTargetUnit();
00362 if ( getMap()->getField( veh->getPosition())->unitHere ( veh ))
00363 if ( !veh->canMove() )
00364 return MapCoordinate3D ( -1, -1, 1 );
00365
00366
00367
00368
00369
00370
00371
00372 int maxMovement = 0;
00373 for ( int i = 0; i < 8; i++ )
00374 maxMovement = max ( maxMovement, veh->typ->movement[i] );
00375
00376 AStar3D astar ( getMap(), veh, true, maxMovement*10 );
00377 astar.findAllAccessibleFields ( );
00378
00379 Building* bestBuilding = NULL;
00380 int bestDistance = maxint;
00381 MapCoordinate3D bestPos;
00382
00383 Building* bestBuilding_p = NULL;
00384 int bestDistance_p = maxint;
00385 MapCoordinate3D bestPos_p;
00386
00387 for ( Player::BuildingList::iterator bi = getPlayer().buildingList.begin(); bi != getPlayer().buildingList.end(); bi++ ) {
00388 Building* bld = *bi;
00389 if ( astar.getFieldAccess( bld->getEntry()) ) {
00390 MapCoordinate3D buildingPos = bld->getEntry();
00391 buildingPos.setnum ( buildingPos.x, buildingPos.y, -1 );
00392
00393
00394
00395
00396
00397 bool loadable = true;
00398 if ( loadable ) {
00399 int fullfillableServices = 0;
00400 int partlyFullfillabelServices = 0;
00401 switch ( so.requiredService ) {
00402 case ServiceOrder::srv_repair : if ( bld->canRepair( veh ) ) {
00403 int mr = bld->getMaxRepair( veh );
00404 if ( mr == 0 )
00405 fullfillableServices++;
00406
00407 if ( mr < veh->damage )
00408 partlyFullfillabelServices++;
00409
00410 }
00411 break;
00412 case ServiceOrder::srv_resource: {
00413 Resources needed = veh->getStorageCapacity() - veh->getResource(Resources(maxint,maxint,maxint), true);
00414 Resources avail = bld->getResource ( needed, 1 );
00415 if ( avail < needed )
00416 avail += bld->netResourcePlus( ) * config.waitForResourcePlus;
00417
00418 int missing = 0;
00419 int pmissing = 0;
00420 for ( int r = 0; r < resourceTypeNum; r++ ) {
00421 if( needed.resource(r) * 75 / 100 > avail.resource(r) )
00422 missing ++;
00423
00424 if( needed.resource(r) * 10 / 100 > avail.resource(r) )
00425 pmissing ++;
00426 }
00427 if ( missing == 0 )
00428 fullfillableServices++;
00429
00430 if ( pmissing == 0)
00431 partlyFullfillabelServices++;
00432 }
00433 break;
00434 case ServiceOrder::srv_ammo : {
00435 int missing = 0;
00436 int pmissing = 0;
00437 int ammoNeeded[waffenanzahl];
00438 for ( int t = 0; t < waffenanzahl; t++ )
00439 ammoNeeded[t] = 0;
00440
00441 for ( int i = 0; i < veh->typ->weapons.count; i++ )
00442 if ( veh->typ->weapons.weapon[i].requiresAmmo() )
00443 ammoNeeded[ veh->typ->weapons.weapon[i].getScalarWeaponType() ] += veh->typ->weapons.weapon[i].count - veh->ammo[i];
00444
00445 Resources needed;
00446 for ( int j = 0; j < waffenanzahl; j++ ) {
00447 int n = ammoNeeded[j] - bld->ammo[j];
00448 if ( n > 0 ) {
00449 if ( bld->typ->hasFunction( ContainerBaseType::AmmoProduction )) {
00450 for ( int r = 0; r < resourceTypeNum; r++ )
00451 needed.resource(r) += (n+4)/5 * ammoProductionCost[j][r];
00452 } else
00453 missing++;
00454 }
00455 }
00456 Resources avail = bld->getResource ( needed, 1 );
00457 if ( avail < needed )
00458 avail += bld->netResourcePlus( ) * config.waitForResourcePlus;
00459
00460 for ( int r = 0; r < resourceTypeNum; r++ ) {
00461 if ( avail.resource(r) < needed.resource (r) )
00462 missing++;
00463 if ( avail.resource(r) <= needed.resource (r)/3 )
00464 pmissing++;
00465 }
00466
00467 if ( missing == 0 )
00468 fullfillableServices++;
00469
00470 if ( pmissing == 0)
00471 partlyFullfillabelServices++;
00472
00473 }
00474 break;
00475
00476 };
00477
00478 if ( fullfillableServices ) {
00479 const AStar3D::Node* nde = astar.fieldVisited(buildingPos);
00480 if ( nde ) {
00481 int dist = int( nde->gval );
00482 if ( dist < bestDistance ) {
00483 bestDistance = dist;
00484 bestBuilding = bld;
00485 bestPos = buildingPos;
00486 }
00487 }
00488 } else
00489 if ( partlyFullfillabelServices ) {
00490 const AStar3D::Node* nde = astar.fieldVisited(buildingPos);
00491 if ( nde ) {
00492 int dist = int( nde->gval );
00493 if ( dist < bestDistance_p ) {
00494 bestDistance_p = dist;
00495 bestBuilding_p = bld;
00496 bestPos_p = buildingPos;
00497 }
00498 }
00499 }
00500 }
00501 }
00502 }
00503
00504 if ( bestBuilding && (bestDistance < bestDistance_p*3)) {
00505 if ( distance )
00506 *distance = bestDistance;
00507 return bestPos;
00508 } else {
00509 if ( distance )
00510 *distance = bestDistance_p;
00511 return bestPos_p;
00512 }
00513 }
00514
00515
00516
00517
00518 bool AI :: ServiceTargetEquals :: operator() (const ServiceOrder& so ) const
00519 {
00520 Vehicle* t = so.getTargetUnit();
00521 return target== t;
00522 }
00523
00524
00525
00526 void AI::removeServiceOrdersForUnit ( const Vehicle* veh )
00527 {
00528 serviceOrders.erase ( remove_if ( serviceOrders.begin(), serviceOrders.end(), ServiceTargetEquals( veh ) ), serviceOrders.end());
00529 }
00530
00531 void AI :: runServiceUnit ( Vehicle* supplyUnit )
00532 {
00533 bool destinationReached = false;
00534 typedef multimap<float,ServiceOrder*> ServiceMap;
00535 ServiceMap serviceMap;
00536
00537
00538 for ( ServiceOrderContainer::iterator i = serviceOrders.begin(); i != serviceOrders.end(); i++ ) {
00539 if ( !i->getServiceUnit() && i->getTargetUnit() ) {
00540 int poss = i->possible( supplyUnit );
00541 if ( poss && beeline( i->getTargetUnit() ,supplyUnit ) ) {
00542 float f = i->getTargetUnit()->aiparam[getPlayerNum()]->getValue() * poss/100 / beeline( i->getTargetUnit() ,supplyUnit );
00543 serviceMap.insert(make_pair(f,&(*i)));
00544 }
00545
00546
00547
00548
00549
00550
00551 }
00552 }
00553 int target = 0;
00554 int counter = 0;
00555 for ( ServiceMap::reverse_iterator ri = serviceMap.rbegin(); ri != serviceMap.rend(); ri++ ) {
00556 displaymessage2("test service %d", ++counter);
00557 if ( ri->second->execute1st( supplyUnit ) ) {
00558 target = supplyUnit->aiparam[getPlayerNum()]->dest_nwid;
00559 destinationReached = runUnitTask ( supplyUnit );
00560 break;
00561 }
00562 }
00563
00564 Vehicle* targetUnit = getMap()->getUnit(target);
00565 if ( destinationReached && targetUnit ) {
00566
00567 auto_ptr<ServiceCommand> sc ( new ServiceCommand( supplyUnit ));
00568 sc->setDestination( targetUnit );
00569 sc->getTransferHandler().fillDest();
00570 sc->saveTransfers();
00571 ActionResult res = sc->execute( getContext() );
00572 if ( res.successful() )
00573 sc.release();
00574 else
00575 displayActionError(res);
00576
00577
00578 if ( targetUnit->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_serviceRetreat )
00579 targetUnit->aiparam[getPlayerNum()]->resetTask();
00580
00581 removeServiceOrdersForUnit ( targetUnit );
00582
00583
00584 runServiceUnit( supplyUnit );
00585 }
00586 }
00587
00588
00589 AI::AiResult AI :: executeServices ( )
00590 {
00591
00592 removeServiceOrdersForUnit ( NULL );
00593 serviceOrders.erase ( remove_if ( serviceOrders.begin(), serviceOrders.end(), ServiceOrder::invalid ), serviceOrders.end());
00594
00595 for_each ( serviceOrders.begin(), serviceOrders.end(), ServiceOrder::releaseServiceUnit );
00596
00597 AiResult res;
00598
00599 vector<int> unitIds;
00600 for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); ++vi )
00601 unitIds.push_back ( (*vi)->networkid );
00602
00603
00604 for ( vector<int>::iterator vi = unitIds.begin(); vi != unitIds.end(); ++vi ) {
00605 Vehicle* veh = getMap()->getUnit( *vi );
00606 if ( veh ) {
00607 checkKeys();
00608 if ( veh->aiparam[getPlayerNum()]->getJob() == AiParameter::job_supply )
00609 runServiceUnit ( veh );
00610 }
00611 }
00612
00613 removeServiceOrdersForUnit ( NULL );
00614 int counter = 0;
00615 for ( ServiceOrderContainer::iterator i = serviceOrders.begin(); i != serviceOrders.end(); ) {
00616 ServiceOrderContainer::iterator nxt = i;
00617 ++nxt;
00618
00619 if ( !i->canWait() ) {
00620 displaymessage2("executing priority service order %d", ++counter);
00621 Vehicle* veh = i->getTargetUnit();
00622 if ( i->getServiceUnit() ) {
00623 if ( veh->canMove() ) {
00624 veh->aiparam[ getPlayerNum() ]->dest = i->getServiceUnit()->getPosition();
00625 veh->aiparam[ getPlayerNum() ]->dest_nwid = i->getServiceUnit()->networkid;
00626 veh->aiparam[ getPlayerNum() ]->setTask( AiParameter::tsk_serviceRetreat );
00627 }
00628 } else {
00630 if ( (veh->height & ( chtieffliegend | chfliegend | chhochfliegend )) && veh->typ->fuelConsumption && false ) {
00631 RefuelConstraint apl ( *this, veh );
00632 MapCoordinate3D dst = apl.getNearestRefuellingPosition( true, true, false );
00633 if ( dst.x != -1 ) {
00634 veh->aiparam[ getPlayerNum() ]->dest = dst;
00635 veh->aiparam[ getPlayerNum() ]->setTask( AiParameter::tsk_serviceRetreat );
00636 }
00637 } else {
00638 MapCoordinate3D dest = findServiceBuilding( *i );
00639 if ( dest.valid() && veh->canMove() ) {
00640 veh->aiparam[ getPlayerNum() ]->dest = dest;
00641 veh->aiparam[ getPlayerNum() ]->setTask( AiParameter::tsk_serviceRetreat );
00642 } else {
00643
00644 }
00645 }
00646 }
00647 }
00648
00649 i = nxt;
00650 }
00651
00652
00653 unitIds.clear();
00654 for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); ++vi )
00655 unitIds.push_back ( (*vi)->networkid );
00656
00657
00658 counter = 0;
00659 for ( vector<int>::iterator vi = unitIds.begin(); vi != unitIds.end(); ++vi ) {
00660 Vehicle* veh = getMap()->getUnit( *vi );
00661 checkKeys();
00662
00663 if ( veh && veh->canMove() && veh->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_serviceRetreat ) {
00664 displaymessage2("retreating with unit %d", ++counter);
00665 int nwid = veh->networkid;
00666 moveUnit ( veh, veh->aiparam[ getPlayerNum() ]->dest, true );
00667
00668
00669 Vehicle* veh = getMap()->getUnit ( nwid );
00670 if ( veh ) {
00671 if ( veh->getPosition3D() == veh->aiparam[ getPlayerNum() ]->dest ) {
00672 MapField* fld = getMap()->getField ( veh->xpos, veh->ypos );
00673 if ( fld->building ) {
00674 auto_ptr<ServiceCommand> sc ( new ServiceCommand( fld->building ));
00675 sc->setDestination( veh );
00676 sc->getTransferHandler().fillDest();
00677 sc->saveTransfers();
00678 ActionResult res = sc->execute( getContext() );
00679 if ( res.successful() )
00680 sc.release();
00681 else
00682 displayActionError(res);
00683
00684
00685 if ( veh->damage ) {
00686 if( RepairUnitCommand::avail( fld->building )) {
00687 auto_ptr<RepairUnitCommand> ruc ( new RepairUnitCommand( fld->building ));
00688 if ( ruc->validTarget( veh )) {
00689 ruc->setTarget( veh );
00690 ActionResult res = ruc->execute( getContext() );
00691 if ( res.successful() )
00692 ruc.release();
00693 }
00694 }
00695 }
00696
00697 removeServiceOrdersForUnit ( veh );
00698
00699 if ( veh->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_serviceRetreat )
00700 veh->aiparam[getPlayerNum()]->resetTask();
00701
00702 }
00703 }
00704 }
00705 }
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 return res;
00724
00725 }