INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb ) { UINT8 cnt, cnt2; INT32 bBestPriority = 0, sBestAdjGridNo = NOWHERE; INT32 sPatientGridNo = NOWHERE, sBestPatientGridNo = NOWHERE; INT16 sShortestPath = 1000, sPathCost, sOtherMedicPathCost; SOLDIERTYPE * pPatient; SOLDIERTYPE * pBestPatient = NULL; SOLDIERTYPE * pOtherMedic; INT8 bPatientPriority; UINT8 ubDirection; INT32 sAdjustedGridNo, sAdjacentGridNo, sOtherAdjacentGridNo; INT32 sClimbGridNo, sBestClimbGridNo = NOWHERE, sShortestClimbPath = 1000; BOOLEAN fClimbingNecessary; gubGlobalPathFlags = PATH_THROUGH_PEOPLE; // search for someone who needs aid cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; for ( pPatient = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pPatient++) { if ( !(pPatient->bActive) || !(pPatient->bInSector) ) { continue; // NEXT!!! } if (pPatient->stats.bLife > 0 && pPatient->bBleeding && pPatient->ubServiceCount == 0) { if (pPatient->stats.bLife < OKLIFE) { bPatientPriority = 3; } else if (pPatient->stats.bLife < OKLIFE * 2) { bPatientPriority = 2; } else { bPatientPriority = 1; } if (bPatientPriority >= bBestPriority) { if ( !ClimbingNecessary( pSoldier, pPatient->sGridNo, pPatient->pathing.bLevel ) ) { sPatientGridNo = pPatient->sGridNo; sAdjacentGridNo = FindAdjacentGridEx( pSoldier, sPatientGridNo, &ubDirection, &sAdjustedGridNo, FALSE, FALSE ); if ( sAdjacentGridNo == -1 && gAnimControl[ pPatient->usAnimState ].ubEndHeight == ANIM_PRONE ) { // prone; could be the base tile is inaccessible but the rest isn't... for ( cnt2 = 0; cnt2 < NUM_WORLD_DIRECTIONS; cnt2++ ) { sPatientGridNo = pPatient->sGridNo + DirectionInc( cnt2 ); if ( WhoIsThere2( sPatientGridNo, pPatient->pathing.bLevel ) == pPatient->ubID ) { // patient is also here, try this location sAdjacentGridNo = FindAdjacentGridEx( pSoldier, sPatientGridNo, &ubDirection, &sAdjustedGridNo, FALSE, FALSE ); if ( sAdjacentGridNo != -1 ) { break; } } } } if (sAdjacentGridNo != -1) { if (sAdjacentGridNo == pSoldier->sGridNo) { sPathCost = 1; } else { sPathCost = PlotPath( pSoldier, sAdjacentGridNo, FALSE, FALSE, FALSE, RUNNING, FALSE, FALSE, 0); } if ( sPathCost != 0 ) { // we can get there... can anyone else? if ( pPatient->ubAutoBandagingMedic != NOBODY && pPatient->ubAutoBandagingMedic != pSoldier->ubID ) { // only switch to this patient if our distance is closer than // the other medic's pOtherMedic = MercPtrs[ pPatient->ubAutoBandagingMedic ]; sOtherAdjacentGridNo = FindAdjacentGridEx( pOtherMedic, sPatientGridNo, &ubDirection, &sAdjustedGridNo, FALSE, FALSE ); if (sOtherAdjacentGridNo != -1) { if (sOtherAdjacentGridNo == pOtherMedic->sGridNo) { sOtherMedicPathCost = 1; } else { sOtherMedicPathCost = PlotPath( pOtherMedic, sOtherAdjacentGridNo, FALSE, FALSE, FALSE, RUNNING, FALSE, FALSE, 0); } if (sPathCost >= sOtherMedicPathCost) { // this patient is best served by the merc moving to them now continue; } } } if (bPatientPriority == bBestPriority) { // compare path distances if ( sPathCost > sShortestPath ) { continue; } } sShortestPath = sPathCost; pBestPatient = pPatient; sBestPatientGridNo = sPatientGridNo; bBestPriority = bPatientPriority; sBestAdjGridNo = sAdjacentGridNo; } } } else { sClimbGridNo = NOWHERE; // see if guy on another building etc and we need to climb somewhere sPathCost = EstimatePathCostToLocation( pSoldier, pPatient->sGridNo, pPatient->pathing.bLevel, FALSE, &fClimbingNecessary, &sClimbGridNo ); // if we can get there if ( sPathCost != 0 && fClimbingNecessary && sPathCost < sShortestClimbPath ) { sBestClimbGridNo = sClimbGridNo; sShortestClimbPath = sPathCost; } } } } } gubGlobalPathFlags = 0; if (pBestPatient) { if (pBestPatient->ubAutoBandagingMedic != NOBODY) { // cancel that medic CancelAIAction( MercPtrs[ pBestPatient->ubAutoBandagingMedic ], TRUE ); } pBestPatient->ubAutoBandagingMedic = pSoldier->ubID; *pfDoClimb = FALSE; if ( CardinalSpacesAway( pSoldier->sGridNo, sBestPatientGridNo ) == 1 ) { pSoldier->aiData.usActionData = sBestPatientGridNo; return( AI_ACTION_GIVE_AID ); } else { pSoldier->aiData.usActionData = sBestAdjGridNo; return( AI_ACTION_GET_CLOSER ); } } else if (!TileIsOutOfBounds(sBestClimbGridNo)) { *pfDoClimb = TRUE; pSoldier->aiData.usActionData = sBestClimbGridNo; return( AI_ACTION_MOVE_TO_CLIMB ); } else { return( AI_ACTION_NONE ); } }
//Kris: modified to actually path from sweetspot to gridno. Previously, it only checked if the //destination was sittable (though it was possible that that location would be trapped. UINT16 FindGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection ) { INT16 sTop, sBottom; INT16 sLeft, sRight; INT16 cnt1, cnt2; INT16 sGridNo; INT32 uiRange, uiLowestRange = 999999; INT16 sLowestGridNo=-1; INT32 leftmost; BOOLEAN fFound = FALSE; SOLDIERTYPE soldier; UINT8 ubSaveNPCAPBudget; UINT8 ubSaveNPCDistLimit; //Save AI pathing vars. changing the distlimit restricts how //far away the pathing will consider. ubSaveNPCAPBudget = gubNPCAPBudget; ubSaveNPCDistLimit = gubNPCDistLimit; gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); soldier.bLevel = 0; soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; sTop = ubRadius; sBottom = -ubRadius; sLeft = - ubRadius; sRight = ubRadius; //clear the mapelements of potential residue MAPELEMENT_REACHABLE flags //in the square region. // ATE: CHECK FOR BOUNDARIES!!!!!! for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ ) { leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS; for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ ) { sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2; if( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) ) { gpWorldLevelData[ sGridNo ].uiFlags &= (~MAPELEMENT_REACHABLE); } } } //Now, find out which of these gridnos are reachable //(use the fake soldier and the pathing settings) FindBestPath( &soldier, NOWHERE, 0, WALKING, COPYREACHABLE, ( PATH_IGNORE_PERSON_AT_DEST | PATH_THROUGH_PEOPLE ) ); uiLowestRange = 999999; for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ ) { leftmost = ( ( sSweetGridNo + ( WORLD_COLS * cnt1 ) )/ WORLD_COLS ) * WORLD_COLS; for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ ) { sGridNo = sSweetGridNo + ( WORLD_COLS * cnt1 ) + cnt2; if( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) && gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_REACHABLE ) { // Go on sweet stop if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->bLevel ) ) { // ATE: INstead of using absolute range, use the path cost! //uiRange = PlotPath( &soldier, sGridNo, NO_COPYROUTE, NO_PLOT, TEMPORARY, WALKING, NOT_STEALTH, FORWARD, 50 ); uiRange = CardinalSpacesAway( sSweetGridNo, sGridNo ); // if ( uiRange == 0 ) // { // uiRange = 999999; // } if ( uiRange < uiLowestRange ) { sLowestGridNo = sGridNo; uiLowestRange = uiRange; fFound = TRUE; } } } } } gubNPCAPBudget = ubSaveNPCAPBudget; gubNPCDistLimit = ubSaveNPCDistLimit; if ( fFound ) { // Set direction to center of map! *pubDirection = (UINT8)GetDirectionToGridNoFromGridNo( sLowestGridNo, ( ( ( WORLD_ROWS / 2 ) * WORLD_COLS ) + ( WORLD_COLS / 2 ) ) ); return( sLowestGridNo ); } else { return( NOWHERE ); } }