// Swaps 2 soldier positions... void SwapMercPositions( SOLDIERTYPE *pSoldier1, SOLDIERTYPE *pSoldier2 ) { INT16 sGridNo1, sGridNo2; // OK, save positions... sGridNo1 = pSoldier1->sGridNo; sGridNo2 = pSoldier2->sGridNo; // OK, remove each..... RemoveSoldierFromGridNo( pSoldier1 ); RemoveSoldierFromGridNo( pSoldier2 ); // OK, test OK destination for each....... if ( NewOKDestination( pSoldier1, sGridNo2, TRUE, 0 ) && NewOKDestination( pSoldier2, sGridNo1, TRUE, 0 ) ) { // OK, call teleport function for each....... TeleportSoldier( pSoldier1, sGridNo2, FALSE ); TeleportSoldier( pSoldier2, sGridNo1, FALSE ); } else { // Place back... TeleportSoldier( pSoldier1, sGridNo1, TRUE ); TeleportSoldier( pSoldier2, sGridNo2, TRUE ); } }
UINT16 FindRandomGridNoFromSweetSpotExcludingSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection ) { INT16 sX, sY; INT16 sGridNo; INT32 leftmost; BOOLEAN fFound = FALSE; UINT32 cnt = 0; do { sX = (UINT16)Random( ubRadius ); sY = (UINT16)Random( ubRadius ); leftmost = ( ( sSweetGridNo + ( WORLD_COLS * sY ) )/ WORLD_COLS ) * WORLD_COLS; sGridNo = sSweetGridNo + ( WORLD_COLS * sY ) + sX; if ( sGridNo == sSweetGridNo ) { continue; } if ( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) ) { // Go on sweet stop if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->bLevel ) ) { fFound = TRUE; } } cnt++; if ( cnt > 2000 ) { return( NOWHERE ); } } while( !fFound ); // Set direction to center of map! *pubDirection = (UINT8)GetDirectionToGridNoFromGridNo( sGridNo, ( ( ( WORLD_ROWS / 2 ) * WORLD_COLS ) + ( WORLD_COLS / 2 ) ) ); return( sGridNo ); }
BOOLEAN TeleportSoldier( SOLDIERTYPE *pSoldier, INT16 sGridNo, BOOLEAN fForce ) { INT16 sX, sY; // Check dest... if ( NewOKDestination( pSoldier, sGridNo, TRUE, 0 ) || fForce ) { // TELEPORT TO THIS LOCATION! sX = CenterX( sGridNo ); sY = CenterY( sGridNo ); EVENT_SetSoldierPosition( pSoldier, (FLOAT) sX, (FLOAT) sY ); pSoldier->sFinalDestination = sGridNo; // Make call to FOV to update items... RevealRoofsAndItems(pSoldier, TRUE, TRUE, pSoldier->bLevel, TRUE ); // Handle sight! HandleSight(pSoldier,SIGHT_LOOK | SIGHT_RADIO); // Cancel services... GivingSoldierCancelServices( pSoldier ); // Change light.... if ( pSoldier->bLevel == 0 ) { if(pSoldier->iLight!=(-1)) LightSpriteRoofStatus(pSoldier->iLight, FALSE ); } else { if(pSoldier->iLight!=(-1)) LightSpriteRoofStatus(pSoldier->iLight, TRUE ); } return( TRUE ); } return( FALSE ); }
int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubPathMode, UINT8 ubWaterOK, UINT8 fFlags) { BOOLEAN fSkipTilesWithMercs; if ((sGridno < 0) || (sGridno >= GRIDSIZE)) { #ifdef RECORDNET fprintf(NetDebugFile,"LegalNPC->sDestination: ERROR - rcvd invalid gridno %d",gridno); #endif #ifdef BETAVERSION NumMessage("LegalNPC->sDestination: ERROR - rcvd invalid gridno ",gridno); #endif return(FALSE); } // return false if gridno on different level from merc if ( GridNoOnVisibleWorldTile( pSoldier->sGridNo ) && gpWorldLevelData[ pSoldier->sGridNo ].sHeight != gpWorldLevelData[ sGridno ].sHeight ) { return( FALSE ); } // skip mercs if turnbased and adjacent AND not doing an IGNORE_PATH check (which is used almost exclusively by GoAsFarAsPossibleTowards) fSkipTilesWithMercs = (gfTurnBasedAI && ubPathMode != IGNORE_PATH && SpacesAway( pSoldier->sGridNo, sGridno ) == 1 ); // if this gridno is an OK destination // AND the gridno is NOT in a tear-gassed tile when we have no gas mask // AND someone is NOT already standing there // AND we're NOT already standing at that gridno // AND the gridno hasn't been black-listed for us // Nov 28 98: skip people in destination tile if in turnbased if ( ( NewOKDestination(pSoldier, sGridno, fSkipTilesWithMercs, pSoldier->bLevel ) ) && ( !InGas( pSoldier, sGridno ) ) && ( sGridno != pSoldier->sGridNo ) && ( sGridno != pSoldier->sBlackList ) ) /* if ( ( NewOKDestination(pSoldier, sGridno, FALSE, pSoldier->bLevel ) ) && ( !(gpWorldLevelData[ sGridno ].ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) || ( pSoldier->inv[ HEAD1POS ].usItem == GASMASK || pSoldier->inv[ HEAD2POS ].usItem == GASMASK ) ) && ( sGridno != pSoldier->sGridNo ) && ( sGridno != pSoldier->sBlackList ) )*/ /* if ( ( NewOKDestination(pSoldier,sGridno,ALLPEOPLE, pSoldier->bLevel ) ) && ( !(gpWorldLevelData[ sGridno ].ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) || ( pSoldier->inv[ HEAD1POS ].usItem == GASMASK || pSoldier->inv[ HEAD2POS ].usItem == GASMASK ) ) && ( sGridno != pSoldier->sGridNo ) && ( sGridno != pSoldier->sBlackList ) ) */ { // if water's a problem, and gridno is in a water tile (bridges are OK) if (!ubWaterOK && Water(sGridno)) return(FALSE); // passed all checks, now try to make sure we can get there! switch (ubPathMode) { // if finding a path wasn't asked for (could have already been done, // for example), don't bother case IGNORE_PATH : return(TRUE); case ENSURE_PATH : if ( FindBestPath( pSoldier, sGridno, pSoldier->bLevel, WALKING, COPYROUTE, fFlags ) ) { return(TRUE); // legal destination } else // got this far, but found no clear path, { // so test fails return(FALSE); } // *** NOTE: movement mode hardcoded to WALKING !!!!! case ENSURE_PATH_COST: return(PlotPath(pSoldier,sGridno,FALSE,FALSE,FALSE,WALKING,FALSE,FALSE,0)); default : #ifdef BETAVERSION NumMessage("LegalNPC->sDestination: ERROR - illegal pathMode = ",ubPathMode); #endif return(FALSE); } } else // something failed - didn't even have to test path return(FALSE); // illegal destination }
INT8 PointPatrolAI(SOLDIERTYPE *pSoldier) { INT16 sPatrolPoint; INT8 bOldOrders; sPatrolPoint = pSoldier->usPatrolGrid[pSoldier->bNextPatrolPnt]; // if we're already there, advance next patrol point if (pSoldier->sGridNo == sPatrolPoint || pSoldier->bNextPatrolPnt == 0) { // find next valid patrol point do { sPatrolPoint = NextPatrolPoint(pSoldier); } while ((sPatrolPoint != NOWHERE) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel) < 1)); // if we're back where we started, then ALL other patrol points are junk! if (pSoldier->sGridNo == sPatrolPoint) { #ifdef BETAVERSION NumMessage("PROBLEM WITH SCENARIO: All other patrol points are invalid for guynum ",pSoldier->ubID); #endif // force change of orders & an abort sPatrolPoint = NOWHERE; } } // if we don't have a legal patrol point if (sPatrolPoint == NOWHERE) { #ifdef BETAVERSION NumMessage("PointPatrolAI: ERROR - no legal patrol point for %d",pSoldier->ubID); #endif // over-ride orders to something safer pSoldier->bOrders = FARPATROL; return(FALSE); } // make sure we can get there from here at this time, if we can't get all // the way there, at least do our best to get close if (LegalNPCDestination(pSoldier,sPatrolPoint,ENSURE_PATH,WATEROK,0)) { pSoldier->bPathStored = TRUE; // optimization - Ian pSoldier->usActionData = sPatrolPoint; } else { // temporarily extend roaming range to infinity by changing orders, else // this won't work if the next patrol point is > 10 tiles away! bOldOrders = pSoldier->bOrders; pSoldier->bOrders = ONCALL; pSoldier->usActionData = GoAsFarAsPossibleTowards(pSoldier,sPatrolPoint,pSoldier->bAction); pSoldier->bOrders = bOldOrders; // if it's not possible to get any closer, that's OK, but fail this call if (pSoldier->usActionData == NOWHERE) return(FALSE); } // passed all tests - start moving towards next patrol point #ifdef DEBUGDECISIONS sprintf(tempstr,"%s - POINT PATROL to grid %d",pSoldier->name,pSoldier->usActionData); AIPopMessage(tempstr); #endif return(TRUE); }
UINT16 FindRandomGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection ) { INT16 sX, sY; INT16 sGridNo; INT32 leftmost; BOOLEAN fFound = FALSE; UINT32 cnt = 0; SOLDIERTYPE soldier; UINT8 ubSaveNPCAPBudget; UINT8 ubSaveNPCDistLimit; UINT8 ubBestDirection=0; INT16 sTop, sBottom; INT16 sLeft, sRight; INT16 cnt1, cnt2; UINT8 ubRoomNum; //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; // 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 ) ); do { sX = (UINT16)Random( ubRadius ); sY = (UINT16)Random( ubRadius ); leftmost = ( ( sSweetGridNo + ( WORLD_COLS * sY ) )/ WORLD_COLS ) * WORLD_COLS; sGridNo = sSweetGridNo + ( WORLD_COLS * sY ) + sX; 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) ) { // If we are a crow, we need this additional check if ( pSoldier->ubBodyType == CROW ) { if ( !InARoom( sGridNo, &ubRoomNum ) ) { fFound = TRUE; } } else { fFound = TRUE; } } } cnt++; if ( cnt > 2000 ) { return( NOWHERE ); } } while( !fFound ); // Set direction to center of map! *pubDirection = (UINT8)GetDirectionToGridNoFromGridNo( sGridNo, ( ( ( WORLD_ROWS / 2 ) * WORLD_COLS ) + ( WORLD_COLS / 2 ) ) ); gubNPCAPBudget = ubSaveNPCAPBudget; gubNPCDistLimit = ubSaveNPCDistLimit; return( sGridNo ); }
UINT16 FindGridNoFromSweetSpotExcludingSweetSpotInQuardent( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection, INT8 ubQuardentDir ) { INT16 sTop, sBottom; INT16 sLeft, sRight; INT16 cnt1, cnt2; INT16 sGridNo; INT32 uiRange, uiLowestRange = 999999; INT16 sLowestGridNo=-1; INT32 leftmost; BOOLEAN fFound = FALSE; sTop = ubRadius; sBottom = -ubRadius; sLeft = - ubRadius; sRight = ubRadius; // Switch on quadrent if ( ubQuardentDir == SOUTHEAST ) { sBottom = 0; sLeft = 0; } 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 ( sSweetGridNo == sGridNo ) { continue; } if ( sGridNo >=0 && sGridNo < WORLD_MAX && sGridNo >= leftmost && sGridNo < ( leftmost + WORLD_COLS ) ) { // Go on sweet stop if ( NewOKDestination( pSoldier, sGridNo, TRUE, pSoldier->bLevel ) ) { uiRange = GetRangeInCellCoordsFromGridNoDiff( sSweetGridNo, sGridNo ); if ( uiRange < uiLowestRange ) { sLowestGridNo = sGridNo; uiLowestRange = uiRange; fFound = TRUE; } } } } } 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 ); } }
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 ); } }
//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 ); } }
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 ); }
BUILDING * GenerateBuilding( INT16 sDesiredSpot ) { UINT32 uiLoop; INT16 sTempGridNo, sNextTempGridNo, sVeryTemporaryGridNo; INT16 sStartGridNo, sCurrGridNo, sPrevGridNo = NOWHERE, sRightGridNo; INT8 bDirection, bTempDirection; BOOLEAN fFoundDir, fFoundWall; UINT32 uiChanceIn = ROOF_LOCATION_CHANCE; // chance of a location being considered INT16 sWallGridNo; INT8 bDesiredOrientation; INT8 bSkipSpots = 0; SOLDIERTYPE FakeSoldier; BUILDING * pBuilding; UINT8 ubBuildingID = 0; pBuilding = CreateNewBuilding( &ubBuildingID ); if (!pBuilding) { return( NULL ); } // set up fake soldier for location testing memset( &FakeSoldier, 0, sizeof( SOLDIERTYPE ) ); FakeSoldier.sGridNo = sDesiredSpot; FakeSoldier.bLevel = 1; FakeSoldier.bTeam = 1; #ifdef ROOF_DEBUG memset( gsCoverValue, 0x7F, sizeof( INT16 ) * WORLD_MAX ); #endif // Set reachable RoofReachableTest( sDesiredSpot, ubBuildingID ); // From sGridNo, search until we find a spot that isn't part of the building bDirection = NORTHWEST; sTempGridNo = sDesiredSpot; // using diagonal directions to hopefully prevent picking a // spot that while( (gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE ) ) { sNextTempGridNo = NewGridNo( sTempGridNo, DirectionInc( bDirection ) ); if ( sTempGridNo == sNextTempGridNo ) { // hit edge of map!??! return( NULL ); } else { sTempGridNo = sNextTempGridNo; } } // we've got our spot sStartGridNo = sTempGridNo; sCurrGridNo = sStartGridNo; sVeryTemporaryGridNo = NewGridNo( sCurrGridNo, DirectionInc( EAST ) ); if ( gpWorldLevelData[ sVeryTemporaryGridNo ].uiFlags & MAPELEMENT_REACHABLE ) { // go north first bDirection = NORTH; } else { // go that way (east) bDirection = EAST; } gpWorldLevelData[ sStartGridNo ].ubExtFlags[0] |= MAPELEMENT_EXT_ROOFCODE_VISITED; while( 1 ) { // if point to (2 clockwise) is not part of building and is not visited, // or is starting point, turn! sRightGridNo = NewGridNo( sCurrGridNo, DirectionInc( gTwoCDirection[ bDirection ] ) ); sTempGridNo = sRightGridNo; if ( ( ( !(gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE) && !(gpWorldLevelData[ sTempGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_ROOFCODE_VISITED) ) || (sTempGridNo == sStartGridNo) ) && (sCurrGridNo != sStartGridNo) ) { bDirection = gTwoCDirection[ bDirection ]; // try in that direction continue; } // if spot ahead is part of building, turn sTempGridNo = NewGridNo( sCurrGridNo, DirectionInc( bDirection ) ); if ( gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE ) { // first search for a spot that is neither part of the building or visited // we KNOW that the spot in the original direction is blocked, so only loop 3 times bTempDirection = gTwoCDirection[ bDirection ]; fFoundDir = FALSE; for ( uiLoop = 0; uiLoop < 3; uiLoop++ ) { sTempGridNo = NewGridNo( sCurrGridNo, DirectionInc( bTempDirection ) ); if ( !(gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE) && !(gpWorldLevelData[ sTempGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_ROOFCODE_VISITED) ) { // this is the way to go! fFoundDir = TRUE; break; } bTempDirection = gTwoCDirection[ bTempDirection ]; } if (!fFoundDir) { // now search for a spot that is just not part of the building bTempDirection = gTwoCDirection[ bDirection ]; fFoundDir = FALSE; for ( uiLoop = 0; uiLoop < 3; uiLoop++ ) { sTempGridNo = NewGridNo( sCurrGridNo, DirectionInc( bTempDirection ) ); if ( !(gpWorldLevelData[ sTempGridNo ].uiFlags & MAPELEMENT_REACHABLE) ) { // this is the way to go! fFoundDir = TRUE; break; } bTempDirection = gTwoCDirection[ bTempDirection ]; } if (!fFoundDir) { // WTF is going on? return( NULL ); } } bDirection = bTempDirection; // try in that direction continue; } // move ahead sPrevGridNo = sCurrGridNo; sCurrGridNo = sTempGridNo; sRightGridNo = NewGridNo( sCurrGridNo, DirectionInc( gTwoCDirection[ bDirection ] ) ); #ifdef ROOF_DEBUG if (gsCoverValue[sCurrGridNo] == 0x7F7F) { gsCoverValue[sCurrGridNo] = 1; } else if (gsCoverValue[sCurrGridNo] >= 0) { gsCoverValue[sCurrGridNo]++; } DebugAI( String( "Roof code visits %d", sCurrGridNo ) ); #endif if (sCurrGridNo == sStartGridNo) { // done break; } if ( !(gpWorldLevelData[ sCurrGridNo ].ubExtFlags[0] & MAPELEMENT_EXT_ROOFCODE_VISITED) ) { gpWorldLevelData[ sCurrGridNo ].ubExtFlags[0] |= MAPELEMENT_EXT_ROOFCODE_VISITED; // consider this location as possible climb gridno // there must be a regular wall adjacent to this for us to consider it a // climb gridno // if the direction is east or north, the wall would be in our gridno; // if south or west, the wall would be in the gridno two clockwise fFoundWall = FALSE; switch( bDirection ) { case NORTH: sWallGridNo = sCurrGridNo; bDesiredOrientation = OUTSIDE_TOP_RIGHT; break; case EAST: sWallGridNo = sCurrGridNo; bDesiredOrientation = OUTSIDE_TOP_LEFT; break; case SOUTH: sWallGridNo = (INT16) ( sCurrGridNo + DirectionInc( gTwoCDirection[ bDirection ] ) ); bDesiredOrientation = OUTSIDE_TOP_RIGHT; break; case WEST: sWallGridNo = (INT16) ( sCurrGridNo + DirectionInc( gTwoCDirection[ bDirection ] ) ); bDesiredOrientation = OUTSIDE_TOP_LEFT; break; default: // what the heck? return( NULL ); } if (bDesiredOrientation == OUTSIDE_TOP_LEFT) { if (WallExistsOfTopLeftOrientation( sWallGridNo )) { fFoundWall = TRUE; } } else { if (WallExistsOfTopRightOrientation( sWallGridNo )) { fFoundWall = TRUE; } } if (fFoundWall) { if (bSkipSpots > 0) { bSkipSpots--; } else if ( Random( uiChanceIn ) == 0 ) { // don't consider people as obstacles if ( NewOKDestination( &FakeSoldier, sCurrGridNo, FALSE, 0 ) ) { pBuilding->sUpClimbSpots[ pBuilding->ubNumClimbSpots ] = sCurrGridNo; pBuilding->sDownClimbSpots[ pBuilding->ubNumClimbSpots ] = sRightGridNo; pBuilding->ubNumClimbSpots++; if ( pBuilding->ubNumClimbSpots == MAX_CLIMBSPOTS_PER_BUILDING) { // gotta stop! return( pBuilding ); } // if location is added as a spot, reset uiChanceIn uiChanceIn = ROOF_LOCATION_CHANCE; #ifdef ROOF_DEBUG gsCoverValue[sCurrGridNo] = 99; #endif // skip the next spot bSkipSpots = 1; } else { // if location is not added, 100% chance of handling next location // and the next until we can add one uiChanceIn = 1; } } else { // didn't pick this location, so increase chance that next location // will be considered if (uiChanceIn > 2) { uiChanceIn--; } } } else { // can't select this spot if ( (sPrevGridNo != NOWHERE) && (pBuilding->ubNumClimbSpots > 0) ) { if ( pBuilding->sDownClimbSpots[ pBuilding->ubNumClimbSpots - 1 ] == sCurrGridNo ) { // unselect previous spot pBuilding->ubNumClimbSpots--; // overwrote a selected spot so go into automatic selection for later uiChanceIn = 1; #ifdef ROOF_DEBUG // reset marker gsCoverValue[sPrevGridNo] = 1; #endif } } // skip the next gridno bSkipSpots = 1; } } } // at end could prune # of locations if there are too many /* #ifdef ROOF_DEBUG SetRenderFlags( RENDER_FLAG_FULL ); RenderWorld(); RenderCoverDebug( ); InvalidateScreen( ); EndFrameBufferRender(); RefreshScreen( NULL ); #endif */ return( pBuilding ); }
BOOLEAN AddUIPlan( UINT16 sGridNo, UINT8 ubPlanID ) { SOLDIERTYPE *pPlanSoldier; INT16 sXPos, sYPos; INT16 sAPCost = 0; INT8 bDirection; INT32 iLoop; SOLDIERCREATE_STRUCT MercCreateStruct; UINT8 ubNewIndex; // Depeding on stance and direction facing, add guy! // If we have a planned action here, ignore! // If not OK Dest, ignore! if ( !NewOKDestination( gpUIPlannedSoldier, sGridNo, FALSE, (INT8)gsInterfaceLevel ) ) { return( FALSE ); } if ( ubPlanID == UIPLAN_ACTION_MOVETO ) { // Calculate cost to move here sAPCost = PlotPath( gpUIPlannedSoldier, sGridNo, COPYROUTE, NO_PLOT, TEMPORARY, (UINT16) gpUIPlannedSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, gpUIPlannedSoldier->bActionPoints ); // Adjust for running if we are not already running if ( gpUIPlannedSoldier->usUIMovementMode == RUNNING ) { sAPCost += AP_START_RUN_COST; } if ( EnoughPoints( gpUIPlannedSoldier, sAPCost, 0, FALSE ) ) { memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) ); MercCreateStruct.bTeam = SOLDIER_CREATE_AUTO_TEAM; MercCreateStruct.ubProfile = NO_PROFILE; MercCreateStruct.fPlayerPlan = TRUE; MercCreateStruct.bBodyType = gpUIPlannedSoldier->ubBodyType; MercCreateStruct.sInsertionGridNo = sGridNo; // Get Grid Corrdinates of mouse if ( TacticalCreateSoldier( &MercCreateStruct, &ubNewIndex ) ) { // Get pointer to soldier GetSoldier( &pPlanSoldier, (UINT16)ubNewIndex ); pPlanSoldier->sPlannedTargetX = -1; pPlanSoldier->sPlannedTargetY = -1; // Compare OPPLISTS! // Set ones we don't know about but do now back to old ( ie no new guys ) for (iLoop = 0; iLoop < MAX_NUM_SOLDIERS; iLoop++ ) { if ( gpUIPlannedSoldier->bOppList[ iLoop ] < 0 ) { pPlanSoldier->bOppList[ iLoop ] = gpUIPlannedSoldier->bOppList[ iLoop ]; } } // Get XY from Gridno ConvertGridNoToCenterCellXY( sGridNo, &sXPos, &sYPos ); EVENT_SetSoldierPosition( pPlanSoldier, sXPos, sYPos ); EVENT_SetSoldierDestination( pPlanSoldier, sGridNo ); pPlanSoldier->bVisible = 1; pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode; pPlanSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost; pPlanSoldier->ubPlannedUIAPCost = (UINT8)pPlanSoldier->bActionPoints; // Get direction bDirection = (INT8)gpUIPlannedSoldier->usPathingData[ gpUIPlannedSoldier->usPathDataSize - 1 ]; // Set direction pPlanSoldier->bDirection = bDirection; pPlanSoldier->bDesiredDirection = bDirection; // Set walking animation ChangeSoldierState( pPlanSoldier, pPlanSoldier->usUIMovementMode, 0, FALSE ); // Change selected soldier gusSelectedSoldier = (UINT16)pPlanSoldier->ubID; // Change global planned mode to this guy! gpUIPlannedSoldier = pPlanSoldier; gubNumUIPlannedMoves++; gfPlotNewMovement = TRUE; ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Adding Merc Move to Plan" ); } } else { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Merc will not have enough action points" ); } } else if ( ubPlanID == UIPLAN_ACTION_FIRE ) { sAPCost = CalcTotalAPsToAttack( gpUIPlannedSoldier, sGridNo, TRUE, (INT8)(gpUIPlannedSoldier->bShownAimTime /2) ); // Get XY from Gridno ConvertGridNoToCenterCellXY( sGridNo, &sXPos, &sYPos ); // If this is a player guy, show message about no APS if ( EnoughPoints( gpUIPlannedSoldier, sAPCost, 0, FALSE ) ) { // CHECK IF WE ARE A PLANNED SOLDIER OR NOT< IF SO< CREATE! if ( gpUIPlannedSoldier->ubID < MAX_NUM_SOLDIERS ) { memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) ); MercCreateStruct.bTeam = SOLDIER_CREATE_AUTO_TEAM; MercCreateStruct.ubProfile = NO_PROFILE; MercCreateStruct.fPlayerPlan = TRUE; MercCreateStruct.bBodyType = gpUIPlannedSoldier->ubBodyType; MercCreateStruct.sInsertionGridNo = sGridNo; // Get Grid Corrdinates of mouse if ( TacticalCreateSoldier( &MercCreateStruct, &ubNewIndex ) ) { // Get pointer to soldier GetSoldier( &pPlanSoldier, (UINT16)ubNewIndex ); pPlanSoldier->sPlannedTargetX = -1; pPlanSoldier->sPlannedTargetY = -1; // Compare OPPLISTS! // Set ones we don't know about but do now back to old ( ie no new guys ) for (iLoop = 0; iLoop < MAX_NUM_SOLDIERS; iLoop++ ) { if ( gpUIPlannedSoldier->bOppList[ iLoop ] < 0 ) { pPlanSoldier->bOppList[ iLoop ] = gpUIPlannedSoldier->bOppList[ iLoop ]; } } EVENT_SetSoldierPosition( pPlanSoldier, gpUIPlannedSoldier->dXPos, gpUIPlannedSoldier->dYPos ); EVENT_SetSoldierDestination( pPlanSoldier, gpUIPlannedSoldier->sGridNo ); pPlanSoldier->bVisible = 1; pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode; pPlanSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost; pPlanSoldier->ubPlannedUIAPCost = (UINT8)pPlanSoldier->bActionPoints; // Get direction bDirection = (INT8)gpUIPlannedSoldier->usPathingData[ gpUIPlannedSoldier->usPathDataSize - 1 ]; // Set direction pPlanSoldier->bDirection = bDirection; pPlanSoldier->bDesiredDirection = bDirection; // Set walking animation ChangeSoldierState( pPlanSoldier, pPlanSoldier->usUIMovementMode, 0, FALSE ); // Change selected soldier gusSelectedSoldier = (UINT16)pPlanSoldier->ubID; // Change global planned mode to this guy! gpUIPlannedSoldier = pPlanSoldier; gubNumUIPlannedMoves++; } } gpUIPlannedSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost; gpUIPlannedSoldier->ubPlannedUIAPCost = (UINT8)gpUIPlannedSoldier->bActionPoints; // Get direction from gridno bDirection = (INT8)GetDirectionFromGridNo( sGridNo, gpUIPlannedSoldier ); // Set direction gpUIPlannedSoldier->bDirection = bDirection; gpUIPlannedSoldier->bDesiredDirection = bDirection; // Set to shooting animation SelectPausedFireAnimation( gpUIPlannedSoldier ); gpUIPlannedSoldier->sPlannedTargetX = sXPos; gpUIPlannedSoldier->sPlannedTargetY = sYPos; ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Adding Merc Shoot to Plan" ); } else { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Merc will not have enough action points" ); } } return( TRUE ); }
void CalculateCover() { register INT32 ubX, ubY; register INT8 ubZ; SOLDIERTYPE* pSoldier; RemoveCoverObjectsFromViewArea(); if( gubDrawMode == COVER_DRAW_OFF ) { return; } if( gusSelectedSoldier == NOBODY ) { return; } // at we're here, we want to display cover, so remove the mines display if ( gubDrawModeMine != MINES_DRAW_OFF ) RemoveMinesObjectsFromViewArea(); GetSoldier( &pSoldier, gusSelectedSoldier ); INT16 usTmp; GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_START_Y, &gsMinCellX, &usTmp ); GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_END_Y, &gsMaxCellX, &usTmp ); GetScreenXYWorldCell( gsVIEWPORT_END_X, gsVIEWPORT_START_Y, &usTmp, &gsMinCellY ); GetScreenXYWorldCell( gsVIEWPORT_START_X, gsVIEWPORT_END_Y, &usTmp, &gsMaxCellY ); for ( ubX=gsMinCellX; ubX<=gsMaxCellX; ++ubX ) { for ( ubY=gsMinCellY; ubY<=gsMaxCellY; ++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; } // do not show stuff on ground if roof is shown if ( IsTheRoofVisible( sGridNo ) ) { if ( ubZ == I_GROUND_LEVEL ) continue; } // do not show stuff on roofs if ground is shown else if ( ubZ == I_ROOF_LEVEL ) continue; if ( !NewOKDestination( pSoldier, sGridNo, false, ubZ ) ) { continue; } INT8& bCover = gCoverViewArea[ ubX ][ ubY ][ ubZ ].bCover; BOOLEAN& fInverseColor = gCoverViewArea[ ubX ][ ubY ][ ubZ ].fInverseColor; if ( gubDrawMode == COVER_DRAW_ENEMY_VIEW ) // view of enemies against your selected merc { // reset cover value bCover = MAX_COVER; CalculateCoverForSoldier( pSoldier, sGridNo, ubZ, bCover ); fInverseColor = FALSE; } else if ( gubDrawMode == COVER_DRAW_MERC_VIEW ) { // reset cover value bCover = MAX_COVER; if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect ) // view of selected mercs { // OK, loop through all guys who are 'multi-selected' and INT32 cnt; cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ ) { if ( pSoldier->bActive && pSoldier->bInSector ) { if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED ) { CalculateCoverFromSoldier( pSoldier, sGridNo, ubZ, bCover ); } } } } else // single view from your merc CalculateCoverFromSoldier( pSoldier, sGridNo, ubZ, bCover ); fInverseColor = TRUE; // we don't want to show the cover for the enemy } } } } AddCoverObjectsToViewArea(); }
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(); }
INT8 RandomPointPatrolAI(SOLDIERTYPE *pSoldier) { INT16 sPatrolPoint; INT8 bOldOrders, bPatrolIndex; INT8 bCnt; sPatrolPoint = pSoldier->usPatrolGrid[pSoldier->bNextPatrolPnt]; // if we're already there, advance next patrol point if (pSoldier->sGridNo == sPatrolPoint || pSoldier->bNextPatrolPnt == 0) { // find next valid patrol point // we keep a count of the # of times we are in here to make sure we don't get into an endless //loop bCnt = 0; do { // usPatrolGrid[0] gets used for centre of close etc patrols, so we have to add 1 to the Random # bPatrolIndex = (INT8) PreRandom( pSoldier->bPatrolCnt ) + 1; sPatrolPoint = pSoldier->usPatrolGrid[ bPatrolIndex]; bCnt++; } while ( (sPatrolPoint == pSoldier->sGridNo) || ( (sPatrolPoint != NOWHERE) && (bCnt < pSoldier->bPatrolCnt) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel ) < 1)) ); if (bCnt == pSoldier->bPatrolCnt) { // ok, we tried doing this randomly, didn't work well, so now do a linear search pSoldier->bNextPatrolPnt = 0; do { sPatrolPoint = NextPatrolPoint(pSoldier); } while ((sPatrolPoint != NOWHERE) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel) < 1)); } // do nothing this time around if (pSoldier->sGridNo == sPatrolPoint) { return( FALSE ); } } // if we don't have a legal patrol point if (sPatrolPoint == NOWHERE) { #ifdef BETAVERSION NumMessage("PointPatrolAI: ERROR - no legal patrol point for %d",pSoldier->ubID); #endif // over-ride orders to something safer pSoldier->bOrders = FARPATROL; return(FALSE); } // make sure we can get there from here at this time, if we can't get all // the way there, at least do our best to get close if (LegalNPCDestination(pSoldier,sPatrolPoint,ENSURE_PATH,WATEROK,0)) { pSoldier->bPathStored = TRUE; // optimization - Ian pSoldier->usActionData = sPatrolPoint; } else { // temporarily extend roaming range to infinity by changing orders, else // this won't work if the next patrol point is > 10 tiles away! bOldOrders = pSoldier->bOrders; pSoldier->bOrders = SEEKENEMY; pSoldier->usActionData = GoAsFarAsPossibleTowards(pSoldier,sPatrolPoint,pSoldier->bAction); pSoldier->bOrders = bOldOrders; // if it's not possible to get any closer, that's OK, but fail this call if (pSoldier->usActionData == NOWHERE) return(FALSE); } // passed all tests - start moving towards next patrol point #ifdef DEBUGDECISIONS sprintf(tempstr,"%s - POINT PATROL to grid %d",pSoldier->name,pSoldier->usActionData); AIPopMessage(tempstr); #endif return(TRUE); }
void SoldierTriesToContinueAlongPath(SOLDIERTYPE *pSoldier) { INT16 usNewGridNo,bAPCost; // turn off the flag now that we're going to do something about it... // ATE: USed to be redundent, now if called befroe NewDest can cause some side efects... // AdjustNoAPToFinishMove( pSoldier, FALSE ); if (pSoldier->bNewSituation == IS_NEW_SITUATION) { CancelAIAction(pSoldier,DONTFORCE); return; } if (pSoldier->usActionData >= NOWHERE) { CancelAIAction(pSoldier,DONTFORCE); return; } if (!NewOKDestination( pSoldier,pSoldier->usActionData, TRUE, pSoldier->bLevel )) { CancelAIAction(pSoldier,DONTFORCE); return; } if (IsActionAffordable(pSoldier)) { if (pSoldier->bActionInProgress == FALSE) { // start a move that didn't even get started before... // hope this works... NPCDoesAct(pSoldier); // perform the chosen action pSoldier->bActionInProgress = ExecuteAction(pSoldier); // if started, mark us as busy } else { // otherwise we shouldn't have to do anything(?) } } else { CancelAIAction(pSoldier,DONTFORCE); #ifdef TESTAI DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, String("Soldier (%d) HAS NOT ENOUGH AP to continue along path",pSoldier->ubID) ); #endif } usNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)pSoldier->usPathingData[ pSoldier->usPathIndex ] ) ); // Find out how much it takes to move here! bAPCost = EstimateActionPointCost( pSoldier, usNewGridNo, (INT8)pSoldier->usPathingData[ pSoldier->usPathIndex ], pSoldier->usUIMovementMode, (INT8) pSoldier->usPathIndex, (INT8) pSoldier->usPathDataSize ); if (pSoldier->bActionPoints >= bAPCost) { // seems to have enough points... NewDest(pSoldier,usNewGridNo); // maybe we didn't actually start the action last turn... pSoldier->bActionInProgress = TRUE; #ifdef TESTAI DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, String("Soldier (%d) continues along path",pSoldier->ubID) ); #endif } else { CancelAIAction(pSoldier,DONTFORCE); #ifdef TESTAI DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, String("Soldier (%d) HAS NOT ENOUGH AP to continue along path",pSoldier->ubID) ); #endif } }
INT8 TileIsClear( SOLDIERTYPE *pSoldier, INT8 bDirection, INT16 sGridNo, INT8 bLevel ) { UINT8 ubPerson; INT16 sTempDestGridNo; INT16 sNewGridNo; BOOLEAN fSwapInDoor = FALSE; if ( sGridNo == NOWHERE ) { return( MOVE_TILE_CLEAR ); } ubPerson = WhoIsThere2( sGridNo, bLevel ); if ( ubPerson != NO_SOLDIER ) { // If this us? if ( ubPerson != pSoldier->ubID ) { // OK, set flag indicating we are blocked by a merc.... if ( pSoldier->bTeam != gbPlayerNum ) // CJC: shouldn't this be in all cases??? //if ( 0 ) { pSoldier->fBlockedByAnotherMerc = TRUE; // Set direction we were trying to goto pSoldier->bBlockedByAnotherMercDirection = bDirection; // Are we only temporarily blocked? // Check if our final destination is = our gridno if ( ( MercPtrs[ ubPerson ]->sFinalDestination == MercPtrs[ ubPerson ]->sGridNo ) ) { return( MOVE_TILE_STATIONARY_BLOCKED ); } else { // OK, if buddy who is blocking us is trying to move too... // And we are in opposite directions... if ( MercPtrs[ ubPerson ]->fBlockedByAnotherMerc && MercPtrs[ ubPerson ]->bBlockedByAnotherMercDirection == gOppositeDirection[ bDirection ] ) { // OK, try and get a path around buddy.... // We have to temporarily make buddy stopped... sTempDestGridNo = MercPtrs[ ubPerson ]->sFinalDestination; MercPtrs[ ubPerson ]->sFinalDestination = MercPtrs[ ubPerson ]->sGridNo; if ( PlotPath( pSoldier, pSoldier->sFinalDestination, NO_COPYROUTE, NO_PLOT, TEMPORARY, pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ) ) { pSoldier->bPathStored = FALSE; // OK, make guy go here... EVENT_GetNewSoldierPath( pSoldier, pSoldier->sFinalDestination, pSoldier->usUIMovementMode ); // Restore final dest.... MercPtrs[ ubPerson ]->sFinalDestination = sTempDestGridNo; pSoldier->fBlockedByAnotherMerc = FALSE; // Is the next tile blocked too? sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)guiPathingData[ 0 ] ) ); return( TileIsClear( pSoldier, (UINT8)guiPathingData[ 0 ], sNewGridNo, pSoldier->bLevel ) ); } else { // Not for multi-tiled things... if ( !( pSoldier->uiStatusFlags & SOLDIER_MULTITILE ) ) { // Is the next movement cost for a door? if ( DoorTravelCost( pSoldier, sGridNo, gubWorldMovementCosts[ sGridNo ][ bDirection ][ pSoldier->bLevel ], (BOOLEAN)( pSoldier->bTeam == gbPlayerNum ), NULL ) == TRAVELCOST_DOOR ) { fSwapInDoor = TRUE; } // If we are to swap and we're near a door, open door first and then close it...? // 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, they should try and continue on their way.... // Start them both again along their way... EVENT_GetNewSoldierPath( pSoldier, pSoldier->sFinalDestination, pSoldier->usUIMovementMode ); EVENT_GetNewSoldierPath( MercPtrs[ ubPerson ], MercPtrs[ ubPerson ]->sFinalDestination, MercPtrs[ ubPerson ]->usUIMovementMode ); } } } return( MOVE_TILE_TEMP_BLOCKED ); } } else { //return( MOVE_TILE_STATIONARY_BLOCKED ); // ATE: OK, put some smartshere... // If we are waiting for more than a few times, change to stationary... if ( MercPtrs[ ubPerson ]->fDelayedMovement >= 105 ) { // Set to special 'I want to walk through people' value pSoldier->fDelayedMovement = 150; return( MOVE_TILE_STATIONARY_BLOCKED ); } if ( MercPtrs[ ubPerson ]->sGridNo == MercPtrs[ ubPerson ]->sFinalDestination ) { return( MOVE_TILE_STATIONARY_BLOCKED ); } return( MOVE_TILE_TEMP_BLOCKED ); } } } if ( ( gpWorldLevelData[ sGridNo ].uiFlags & MAPELEMENT_MOVEMENT_RESERVED ) ) { if ( gpWorldLevelData[ sGridNo ].ubReservedSoldierID != pSoldier->ubID ) { return( MOVE_TILE_TEMP_BLOCKED ); } } // Are we clear of structs? if ( !NewOKDestination( pSoldier, sGridNo, FALSE, pSoldier->bLevel ) ) { // ATE: Fence cost is an exclusiuon here.... if ( gubWorldMovementCosts[ sGridNo ][ bDirection ][ pSoldier->bLevel ] != TRAVELCOST_FENCE ) { // ATE: HIdden structs - we do something here... reveal it! if ( gubWorldMovementCosts[ sGridNo ][ bDirection ][ pSoldier->bLevel ] == TRAVELCOST_HIDDENOBSTACLE ) { gpWorldLevelData[ sGridNo ].uiFlags|=MAPELEMENT_REVEALED; gpWorldLevelData[ sGridNo ].uiFlags|=MAPELEMENT_REDRAW; SetRenderFlags(RENDER_FLAG_MARKED); RecompileLocalMovementCosts( (UINT16)sGridNo ); } // Unset flag for blocked by soldier... pSoldier->fBlockedByAnotherMerc = FALSE; return( MOVE_TILE_STATIONARY_BLOCKED ); } else { #if 0 // Check if there is a reserved marker here at least.... sNewGridNo = NewGridNo( sGridNo, DirectionInc( bDirection ) ); if ( ( gpWorldLevelData[ sNewGridNo ].uiFlags & MAPELEMENT_MOVEMENT_RESERVED ) ) { if ( gpWorldLevelData[ sNewGridNo ].ubReservedSoldierID != pSoldier->ubID ) { return( MOVE_TILE_TEMP_BLOCKED ); } } #endif } } // Unset flag for blocked by soldier... pSoldier->fBlockedByAnotherMerc = FALSE; return( MOVE_TILE_CLEAR ); }