INT16 FindClosestClimbPoint( INT16 sStartGridNo, INT16 sDesiredGridNo, BOOLEAN fClimbUp ) { BUILDING * pBuilding; UINT8 ubNumClimbSpots; INT16 * psClimbSpots; UINT8 ubLoop; INT16 sDistance, sClosestDistance = 1000, sClosestSpot= NOWHERE; pBuilding = FindBuilding( sDesiredGridNo ); if (!pBuilding) { return( NOWHERE ); } ubNumClimbSpots = pBuilding->ubNumClimbSpots; if (fClimbUp) { psClimbSpots = pBuilding->sUpClimbSpots; } else { psClimbSpots = pBuilding->sDownClimbSpots; } for ( ubLoop = 0; ubLoop < ubNumClimbSpots; ubLoop++ ) { if ( (WhoIsThere2( pBuilding->sUpClimbSpots[ ubLoop ], 0 ) == NOBODY) && (WhoIsThere2( pBuilding->sDownClimbSpots[ ubLoop ], 1 ) == NOBODY) ) { sDistance = PythSpacesAway( sStartGridNo, psClimbSpots[ ubLoop ] ); if (sDistance < sClosestDistance ) { sClosestDistance = sDistance; sClosestSpot = psClimbSpots[ ubLoop ]; } } } return( sClosestSpot ); }
UINT16 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc, SOLDIERTYPE *pSrcSoldier ) { INT16 sTop, sBottom; INT16 sLeft, sRight; INT16 cnt1, cnt2, cnt3; INT16 sGridNo; INT32 uiRange, uiLowestRange = 999999; INT16 sLowestGridNo=-1; INT32 leftmost; BOOLEAN fFound = FALSE; UINT8 ubSaveNPCAPBudget; UINT8 ubSaveNPCDistLimit; UINT8 ubBestDirection=0; INT16 sSweetGridNo; SOLDIERTYPE soldier; sSweetGridNo = pSrcSoldier->sGridNo; //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 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 ) ) { BOOLEAN fDirectionFound = FALSE; UINT16 usOKToAddStructID; STRUCTURE_FILE_REF * pStructureFileRef; UINT16 usAnimSurface; if ( fClosestToMerc != 3 ) { if ( pSoldier->pLevelNode != NULL && pSoldier->pLevelNode->pStructureData != NULL ) { usOKToAddStructID = pSoldier->pLevelNode->pStructureData->usStructureID; } else { usOKToAddStructID = INVALID_STRUCTURE_ID; } // Get animation surface... usAnimSurface = DetermineSoldierAnimationSurface( pSoldier, usAnimState ); // Get structure ref... pStructureFileRef = GetAnimationStructureRef( pSoldier->ubID, usAnimSurface, usAnimState ); // Check each struct in each direction for( cnt3 = 0; cnt3 < 8; cnt3++ ) { if (OkayToAddStructureToWorld( (INT16)sGridNo, pSoldier->bLevel, &(pStructureFileRef->pDBStructureRef[gOneCDirection[ cnt3 ]]), usOKToAddStructID ) ) { fDirectionFound = TRUE; break; } } } else { fDirectionFound = TRUE; cnt3 = (UINT8)Random( 8 ); } if ( fDirectionFound ) { if ( fClosestToMerc == 1 ) { uiRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ); } else if ( fClosestToMerc == 2 ) { uiRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) + GetRangeInCellCoordsFromGridNoDiff( sSweetGridNo, sGridNo ); } else { //uiRange = GetRangeInCellCoordsFromGridNoDiff( sSweetGridNo, sGridNo ); uiRange = abs((sSweetGridNo / MAXCOL) - (sGridNo / MAXCOL)) + abs((sSweetGridNo % MAXROW) - (sGridNo % MAXROW)); } if ( uiRange < uiLowestRange || (uiRange == uiLowestRange && PythSpacesAway( pSoldier->sGridNo, sGridNo ) < PythSpacesAway( pSoldier->sGridNo, sLowestGridNo ) ) ) { ubBestDirection = (UINT8)cnt3; sLowestGridNo = sGridNo; uiLowestRange = uiRange; fFound = TRUE; } } } } } } gubNPCAPBudget = ubSaveNPCAPBudget; gubNPCDistLimit = ubSaveNPCDistLimit; if ( fFound ) { // Set direction we chose... *pubDirection = ubBestDirection; return( sLowestGridNo ); } else { return( NOWHERE ); } }
void CalculateTraitRange() { INT32 ubX, ubY, ubZ; SOLDIERTYPE* pSoldier; RemoveTraitObjectsFromViewArea(); if ( gubDrawModeTrait == TRAIT_DRAW_OFF ) return; if( gusSelectedSoldier == NOBODY || !GetSoldier( &pSoldier, gusSelectedSoldier ) ) return; UINT16 range1 = 0; UINT16 range2 = 0; switch ( usDisplayTrait ) { case RADIO_OPERATOR_NT: { // we 'mark' the map position with which we called the menu, so that the player sees where he is targetting } break; case VARIOUSSKILLS: { range1 = gGameExternalOptions.usSpotterRange; range2 = gGameExternalOptions.usSpotterRange * 2; } break; default: return; } //remove other displays if( gubDrawModeMine != MINES_DRAW_OFF ) RemoveMinesObjectsFromViewArea(); if ( gubDrawMode != COVER_DRAW_OFF ) RemoveCoverObjectsFromViewArea(); const INT32& sSelectedSoldierGridNo = MercPtrs[ gusSelectedSoldier ]->sGridNo; INT16 usTmp; GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, &gsMineMinCellX, &usTmp ); GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_END_Y, &gsMineMaxCellX, &usTmp ); GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_START_Y, &usTmp, &gsMineMinCellY ); GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_END_Y, &usTmp, &gsMineMaxCellY ); for ( ubX=gsMineMinCellX; ubX<=gsMineMaxCellX; ++ubX ) { for ( ubY=gsMineMinCellY; ubY<=gsMineMaxCellY; ++ubY ) { for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ ) { INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo; GetGridNoForViewPort( ubX, ubY, sGridNo ); if( !GridNoOnScreenAndAround( sGridNo, 2 ) ) { continue; } if ( !NewOKDestination( pSoldier, sGridNo, false, (INT8) ubZ ) ) { continue; } // do not show stuff on roofs if ground is shown if ( ubZ == I_ROOF_LEVEL && !IsTheRoofVisible( sGridNo ) ) { continue; } // do not show stuff on ground if roof is shown if ( ubZ == I_GROUND_LEVEL && IsTheRoofVisible( sGridNo ) ) { continue; } if ( range1 && PythSpacesAway(sSelectedSoldierGridNo, sGridNo) == range1 ) gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_1; else if ( range2 && PythSpacesAway(sSelectedSoldierGridNo, sGridNo) == range2 ) gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_2; // mark the gridno we are targetting else if ( PythSpacesAway(sTraitgridNo, sGridNo) == 1 ) gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = TRAIT_1; else gCoverViewArea[ ubX ][ ubY ][ ubZ ].bTrait = MAX_TRAIT; } } } AddTraitObjectsToViewArea(); }
void CalculateMines() { INT32 ubX, ubY, ubZ; SOLDIERTYPE* pSoldier; RemoveMinesObjectsFromViewArea(); if( gubDrawModeMine == MINES_DRAW_OFF ) { return; } if( gusSelectedSoldier == NOBODY ) { return; } // at we're here, we want to display mines, so remove the cover display if ( gubDrawMode != COVER_DRAW_OFF ) RemoveCoverObjectsFromViewArea(); GetSoldier( &pSoldier, gusSelectedSoldier ); // if we want to detect hostile mines and we have an metal detector in our hands, allow seeking BOOLEAN fWithMineDetector = FALSE; if ( pSoldier && gubDrawModeMine == MINES_DRAW_DETECT_ENEMY ) { if ( FindMetalDetectorInHand(pSoldier) != NO_SLOT ) fWithMineDetector = TRUE; // TODO: perhaps even consume batteries one day... } // if we are looking for mines via mine detector, but don't have one equipped, return, we won't detect anything if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && !fWithMineDetector ) { return; } const INT32& sSelectedSoldierGridNo = MercPtrs[ gusSelectedSoldier ]->sGridNo; INT16 usTmp; GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, &gsMineMinCellX, &usTmp ); GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_END_Y, &gsMineMaxCellX, &usTmp ); GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_START_Y, &usTmp, &gsMineMinCellY ); GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_END_Y, &usTmp, &gsMineMaxCellY ); for ( ubX=gsMineMinCellX; ubX<=gsMineMaxCellX; ++ubX ) { for ( ubY=gsMineMinCellY; ubY<=gsMineMaxCellY; ++ubY ) { for ( ubZ=0; ubZ<COVER_Z_CELLS; ++ubZ ) { INT32& sGridNo = gCoverViewArea[ ubX ][ ubY ][ ubZ ].sGridNo; GetGridNoForViewPort( ubX, ubY, sGridNo ); if( !GridNoOnScreenAndAround( sGridNo, 2 ) ) { continue; } if ( IsTheRoofVisible( sGridNo ) ) { if ( ubZ == I_GROUND_LEVEL ) continue; } else if ( ubZ == I_ROOF_LEVEL ) { continue; } // if we are looking for hostile mines, but the tile is out of our' detectors range, skip looking for mines if ( gubDrawModeMine == MINES_DRAW_DETECT_ENEMY && fWithMineDetector ) { if ( PythSpacesAway(sSelectedSoldierGridNo, sGridNo) > 4 ) continue; } if ( !NewOKDestination( pSoldier, sGridNo, false, (INT8) ubZ ) ) { continue; } INT8& bMines = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bMines; bMines = MAX_MINES; DetermineMineDisplayInTile( sGridNo, ubZ, bMines, fWithMineDetector ); } } } AddMinesObjectsToViewArea(); }
INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN * pfClimbingNecessary, BOOLEAN * pfReachable ) { UINT32 uiLoop; INT8 * pbPersOL, * pbPublOL; INT16 *psLastLoc,*psNoiseGridNo; INT8 * pbNoiseLevel; INT8 *pbLastLevel; UINT8 *pubNoiseVolume; INT32 iDistAway; INT32 iNoiseValue, iBestValue = -10000; INT16 sBestGridNo = NOWHERE; INT8 bBestLevel = 0; INT16 sClimbingGridNo; BOOLEAN fClimbingNecessary = FALSE; SOLDIERTYPE * pTemp; pubNoiseVolume = &gubPublicNoiseVolume[pSoldier->bTeam]; psNoiseGridNo = &gsPublicNoiseGridno[pSoldier->bTeam]; pbNoiseLevel = &gbPublicNoiseLevel[pSoldier->bTeam]; psLastLoc = gsLastKnownOppLoc[pSoldier->ubID]; // hang pointers at start of this guy's personal and public opponent opplists pbPersOL = pSoldier->bOppList; pbPublOL = gbPublicOpplist[pSoldier->bTeam]; // look through this man's personal & public opplists for opponents heard for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++) { pTemp = MercSlots[ uiLoop ]; // if this merc is inactive, at base, on assignment, or dead if (!pTemp || !pTemp->bLife) continue; // next merc // if this merc is neutral/on same side, he's not an opponent if ( CONSIDERED_NEUTRAL( pSoldier, pTemp ) || (pSoldier->bSide == pTemp->bSide)) continue; // next merc pbPersOL = pSoldier->bOppList + pTemp->ubID; pbPublOL = gbPublicOpplist[pSoldier->bTeam] + pTemp->ubID; psLastLoc = gsLastKnownOppLoc[pSoldier->ubID] + pTemp->ubID; pbLastLevel = gbLastKnownOppLevel[pSoldier->ubID] + pTemp->ubID; // if this guy's been personally heard within last 3 turns if (*pbPersOL < NOT_HEARD_OR_SEEN) { // calculate how far this noise was, and its relative "importance" iDistAway = SpacesAway(pSoldier->sGridNo,*psLastLoc); iNoiseValue = (*pbPersOL) * iDistAway; // always a negative number! if (iNoiseValue > iBestValue) { iBestValue = iNoiseValue; sBestGridNo = *psLastLoc; bBestLevel = *pbLastLevel; } } // if this guy's been publicly heard within last 3 turns if (*pbPublOL < NOT_HEARD_OR_SEEN) { // calculate how far this noise was, and its relative "importance" iDistAway = SpacesAway(pSoldier->sGridNo,gsPublicLastKnownOppLoc[pSoldier->bTeam][pTemp->ubID]); iNoiseValue = (*pbPublOL) * iDistAway; // always a negative number! if (iNoiseValue > iBestValue) { iBestValue = iNoiseValue; sBestGridNo = gsPublicLastKnownOppLoc[pSoldier->bTeam][pTemp->ubID]; bBestLevel = gbPublicLastKnownOppLevel[pSoldier->bTeam][pTemp->ubID]; } } } // if any "misc. noise" was also heard recently if (pSoldier->sNoiseGridno != NOWHERE) { if ( pSoldier->bNoiseLevel != pSoldier->bLevel || PythSpacesAway( pSoldier->sGridNo, pSoldier->sNoiseGridno ) >= 6 || SoldierTo3DLocationLineOfSightTest( pSoldier, pSoldier->sNoiseGridno, pSoldier->bNoiseLevel, 0, (UINT8) MaxDistanceVisible(), FALSE ) == 0 ) { // calculate how far this noise was, and its relative "importance" iDistAway = SpacesAway(pSoldier->sGridNo,pSoldier->sNoiseGridno); iNoiseValue = ((pSoldier->ubNoiseVolume / 2) - 6) * iDistAway; if (iNoiseValue > iBestValue) { iBestValue = iNoiseValue; sBestGridNo = pSoldier->sNoiseGridno; bBestLevel = pSoldier->bNoiseLevel; } } else { // we are there or near pSoldier->sNoiseGridno = NOWHERE; // wipe it out, not useful anymore pSoldier->ubNoiseVolume = 0; } } // if any recent PUBLIC "misc. noise" is also known if ( (pSoldier->bTeam != CIV_TEAM) || ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) ) { if (*psNoiseGridNo != NOWHERE) { // if we are NOT there (at the noise gridno) if ( *pbNoiseLevel != pSoldier->bLevel || PythSpacesAway( pSoldier->sGridNo, *psNoiseGridNo ) >= 6 || SoldierTo3DLocationLineOfSightTest( pSoldier, *psNoiseGridNo, *pbNoiseLevel, 0, (UINT8) MaxDistanceVisible(), FALSE ) == 0 ) { // calculate how far this noise was, and its relative "importance" iDistAway = SpacesAway(pSoldier->sGridNo,*psNoiseGridNo); iNoiseValue = ((*pubNoiseVolume / 2) - 6) * iDistAway; if (iNoiseValue > iBestValue) { iBestValue = iNoiseValue; sBestGridNo = *psNoiseGridNo; bBestLevel = *pbNoiseLevel; } } } } if (sBestGridNo != NOWHERE && pfReachable ) { *pfReachable = TRUE; // make civs not walk to noises outside their room if on close patrol/onguard if ( pSoldier->bOrders <= CLOSEPATROL && (pSoldier->bTeam == CIV_TEAM || pSoldier->ubProfile != NO_PROFILE ) ) { UINT8 ubRoom, ubNewRoom; // any other combo uses the default of ubRoom == 0, set above if ( InARoom( pSoldier->usPatrolGrid[0], &ubRoom ) ) { if ( !InARoom( pSoldier->usPatrolGrid[0], &ubNewRoom ) || ubRoom != ubNewRoom ) { *pfReachable = FALSE; } } } if ( *pfReachable ) { // if there is a climb involved then we should store the location // of where we have to climb to instead sClimbingGridNo = GetInterveningClimbingLocation( pSoldier, sBestGridNo, bBestLevel, &fClimbingNecessary ); if ( fClimbingNecessary ) { if ( sClimbingGridNo == NOWHERE ) { // can't investigate! *pfReachable = FALSE; } else { sBestGridNo = sClimbingGridNo; fClimbingNecessary = TRUE; } } else { fClimbingNecessary = FALSE; } } } if ( piRetValue ) { *piRetValue = iBestValue; } if ( pfClimbingNecessary ) { *pfClimbingNecessary = fClimbingNecessary; } #ifdef DEBUGDECISIONS if (sBestGridNo != NOWHERE) AINumMessage("MOST IMPORTANT NOISE HEARD FROM GRID #",sBestGridNo); #endif return(sBestGridNo); }
BOOLEAN HandleNextTileWaiting( SOLDIERTYPE *pSoldier ) { // Buddy is waiting to continue his path INT8 bBlocked, bPathBlocked; INT16 sCost; INT16 sNewGridNo, sCheckGridNo; UINT8 ubDirection, bCauseDirection; UINT8 ubPerson; UINT8 fFlags = 0; if ( pSoldier->fDelayedMovement ) { if ( TIMECOUNTERDONE( pSoldier->NextTileCounter, NEXT_TILE_CHECK_DELAY ) ) { RESETTIMECOUNTER( pSoldier->NextTileCounter, NEXT_TILE_CHECK_DELAY ); // Get direction from gridno... bCauseDirection = (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sDelayedMovementCauseGridNo ); bBlocked = TileIsClear( pSoldier, bCauseDirection, pSoldier->sDelayedMovementCauseGridNo, pSoldier->bLevel ); // If we are waiting for a temp blockage.... continue to wait if ( pSoldier->fDelayedMovement >= 100 && bBlocked == MOVE_TILE_TEMP_BLOCKED ) { // ATE: Increment 1 pSoldier->fDelayedMovement++; // Are we close enough to give up? ( and are a pc ) if ( pSoldier->fDelayedMovement > 120 ) { // Quit... SetFinalTile( pSoldier, pSoldier->sGridNo, TRUE ); pSoldier->fDelayedMovement = FALSE; } return( TRUE ); } // Try new path if anything but temp blockage! if ( bBlocked != MOVE_TILE_TEMP_BLOCKED ) { // Set to normal delay if ( pSoldier->fDelayedMovement >= 100 && pSoldier->fDelayedMovement != 150 ) { pSoldier->fDelayedMovement = 1; } // Default to pathing through people fFlags = PATH_THROUGH_PEOPLE; // Now, if we are in the state where we are desparently trying to get out... // Use other flag // CJC: path-through-people includes ignoring person at dest /* if ( pSoldier->fDelayedMovement >= 150 ) { fFlags = PATH_IGNORE_PERSON_AT_DEST; } */ // Check destination first! if ( pSoldier->sAbsoluteFinalDestination == pSoldier->sFinalDestination ) { // on last lap of scripted move, make sure we get to final dest sCheckGridNo = pSoldier->sAbsoluteFinalDestination; } else if (!NewOKDestination( pSoldier, pSoldier->sFinalDestination, TRUE, pSoldier->bLevel )) { if ( pSoldier->fDelayedMovement >= 150 ) { // OK, look around dest for the first one! sCheckGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sFinalDestination, 6, &ubDirection ); if ( sCheckGridNo == NOWHERE ) { // If this is nowhere, try harder! sCheckGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sFinalDestination, 16, &ubDirection ); } } else { // OK, look around dest for the first one! sCheckGridNo = FindGridNoFromSweetSpotThroughPeople( pSoldier, pSoldier->sFinalDestination, 6, &ubDirection ); if ( sCheckGridNo == NOWHERE ) { // If this is nowhere, try harder! sCheckGridNo = FindGridNoFromSweetSpotThroughPeople( pSoldier, pSoldier->sFinalDestination, 16, &ubDirection ); } } } else { sCheckGridNo = pSoldier->sFinalDestination; } // Try another path to destination // ATE: Allow path to exit grid! if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO ) { gfPlotPathToExitGrid = TRUE; } sCost = (INT16) FindBestPath( pSoldier, sCheckGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, fFlags ); gfPlotPathToExitGrid = FALSE; // Can we get there if ( sCost > 0 ) { // Is the next tile blocked too? sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) ); bPathBlocked = TileIsClear( pSoldier, (UINT8)guiPathingData[ 0 ], sNewGridNo, pSoldier->bLevel ); if ( bPathBlocked == MOVE_TILE_STATIONARY_BLOCKED ) { // Try to path around everyone except dest person if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO ) { gfPlotPathToExitGrid = TRUE; } sCost = (INT16) FindBestPath( pSoldier, sCheckGridNo, pSoldier->bLevel, pSoldier->usUIMovementMode, NO_COPYROUTE, PATH_IGNORE_PERSON_AT_DEST ); gfPlotPathToExitGrid = FALSE; // Is the next tile in this new path blocked too? sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) ); bPathBlocked = TileIsClear( pSoldier, (UINT8)guiPathingData[ 0 ], sNewGridNo, pSoldier->bLevel ); // now working with a path which does not go through people pSoldier->ubDelayedMovementFlags &= (~DELAYED_MOVEMENT_FLAG_PATH_THROUGH_PEOPLE); } else { // path through people worked fine if ( pSoldier->fDelayedMovement < 150 ) { pSoldier->ubDelayedMovementFlags |= DELAYED_MOVEMENT_FLAG_PATH_THROUGH_PEOPLE; } } // Are we clear? if ( bPathBlocked == MOVE_TILE_CLEAR ) { // Go for it path! if ( pSoldier->ubWaitActionToDo == 1 && gubWaitingForAllMercsToExitCode == WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO ) { gfPlotPathToExitGrid = TRUE; } //pSoldier->fDelayedMovement = FALSE; // ATE: THis will get set in EENT_GetNewSoldierPath.... pSoldier->usActionData = sCheckGridNo; pSoldier->bPathStored = FALSE; EVENT_GetNewSoldierPath( pSoldier, sCheckGridNo, pSoldier->usUIMovementMode ); gfPlotPathToExitGrid = FALSE; return( TRUE ); } } pSoldier->fDelayedMovement++; if ( pSoldier->fDelayedMovement == 99 ) { // Cap at 99 pSoldier->fDelayedMovement = 99; } // Do we want to force a swap? if (pSoldier->fDelayedMovement == 3 && (pSoldier->sAbsoluteFinalDestination != NOWHERE || gTacticalStatus.fAutoBandageMode) ) { // with person who is in the way? ubPerson = WhoIsThere2( pSoldier->sDelayedMovementCauseGridNo, pSoldier->bLevel ); // if either on a mission from god, or two AI guys not on stationary... if ( ubPerson != NOBODY && ( pSoldier->ubQuoteRecord != 0 || ( pSoldier->bTeam != gbPlayerNum && pSoldier->bOrders != STATIONARY && MercPtrs[ ubPerson ]->bTeam != gbPlayerNum && MercPtrs[ ubPerson ]->bOrders != STATIONARY ) || (pSoldier->bTeam == gbPlayerNum && gTacticalStatus.fAutoBandageMode && !(MercPtrs[ ubPerson ]->bTeam == CIV_TEAM && MercPtrs[ ubPerson ]->bOrders == STATIONARY ) ) ) ) { // Swap now! //MercPtrs[ ubPerson ]->fBlockedByAnotherMerc = FALSE; // Restore final dest.... //MercPtrs[ ubPerson ]->sFinalDestination = sTempDestGridNo; // Swap merc positions..... SwapMercPositions( pSoldier, MercPtrs[ ubPerson ] ); // With these two guys swapped, we should try to continue on our way.... pSoldier->fDelayedMovement = FALSE; // We must calculate the path here so that we can give it the "through people" parameter if ( gTacticalStatus.fAutoBandageMode && pSoldier->sAbsoluteFinalDestination == NOWHERE ) { FindBestPath( pSoldier, pSoldier->sFinalDestination, pSoldier->bLevel, pSoldier->usUIMovementMode, COPYROUTE, PATH_THROUGH_PEOPLE ); } else if ( pSoldier->sAbsoluteFinalDestination != NOWHERE && !FindBestPath( pSoldier, pSoldier->sAbsoluteFinalDestination, pSoldier->bLevel, pSoldier->usUIMovementMode, COPYROUTE, PATH_THROUGH_PEOPLE ) ) { // check to see if we're there now! if ( pSoldier->sGridNo == pSoldier->sAbsoluteFinalDestination ) { NPCReachedDestination( pSoldier, FALSE ); pSoldier->bNextAction = AI_ACTION_WAIT; pSoldier->usNextActionData = 500; return( TRUE ); } } pSoldier->bPathStored = TRUE; EVENT_GetNewSoldierPath( pSoldier, pSoldier->sAbsoluteFinalDestination, pSoldier->usUIMovementMode ); //EVENT_GetNewSoldierPath( MercPtrs[ ubPerson ], MercPtrs[ ubPerson ]->sFinalDestination, MercPtrs[ ubPerson ]->usUIMovementMode ); } } // Are we close enough to give up? ( and are a pc ) if ( pSoldier->fDelayedMovement > 20 && pSoldier->fDelayedMovement != 150) { if ( PythSpacesAway( pSoldier->sGridNo, pSoldier->sFinalDestination ) < 5 && pSoldier->bTeam == gbPlayerNum ) { // Quit... SetFinalTile( pSoldier, pSoldier->sGridNo, FALSE ); pSoldier->fDelayedMovement = FALSE; } } // Are we close enough to give up? ( and are a pc ) if ( pSoldier->fDelayedMovement > 170 ) { if ( PythSpacesAway( pSoldier->sGridNo, pSoldier->sFinalDestination ) < 5 && pSoldier->bTeam == gbPlayerNum ) { // Quit... SetFinalTile( pSoldier, pSoldier->sGridNo, FALSE ); pSoldier->fDelayedMovement = FALSE; } } } } } return( TRUE ); }