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