void HaltMoveForSoldierOutOfPoints(SOLDIERTYPE *pSoldier) { // If a special move, ignore this! if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) ) { return; } // record that this merc can no longer animate and why... AdjustNoAPToFinishMove( pSoldier, TRUE ); // We'll keep his action intact though... DebugAI( String("NO AP TO FINISH MOVE for %d (%d APs left)",pSoldier->ubID, pSoldier->bActionPoints) ); // if this dude is under AI right now, then pass the baton to someone else if (pSoldier->uiStatusFlags & SOLDIER_UNDERAICONTROL) { #ifdef TESTAICONTROL DebugAI( String("Ending turn for %d because out of APs for movement", pSoldier->ubID ) ); #endif EndAIGuysTurn(pSoldier); } }
int TryToResumeMovement(SOLDIERTYPE *pSoldier, INT16 sGridno) { UINT8 ubGottaCancel = FALSE; UINT8 ubSuccess = FALSE; // have to make sure the old destination is still legal (somebody may // have occupied the destination gridno in the meantime!) if (LegalNPCDestination(pSoldier,sGridno,ENSURE_PATH,WATEROK,0)) { #ifdef DEBUGDECISIONS DebugAI( String( "%d CONTINUES MOVEMENT to gridno %d...\n",pSoldier->ubID,gridno ) ); #endif pSoldier->bPathStored = TRUE; // optimization - Ian // make him go to it (needed to continue movement across multiple turns) NewDest(pSoldier,sGridno); ubSuccess = TRUE; // make sure that it worked (check that pSoldier->sDestination == pSoldier->sGridNo) if (pSoldier->sDestination == sGridno) { ubSuccess = TRUE; } else { #ifdef BETAVERSION sprintf(tempstr,"TryToResumeMovement: ERROR - NewDest failed for %s, action CANCELED",pSoldier->name); #ifdef RECORDNET fprintf(NetDebugFile,"\n\t%s\n",tempstr); #endif PopMessage(tempstr); SaveGame(ERROR_SAVE); #endif // must work even for escorted civs, can't just set the flag CancelAIAction(pSoldier,FORCE); } } else { // don't black-list anything here, this situation can come up quite // legally if another soldier gets in the way between turns #ifdef BETAVERSION sprintf(tempstr,"TryToResumeMovement: %d can't continue to gridno %d, no longer legal!",pSoldier->ubID,gridno); #ifdef RECORDNET fprintf(NetDebugFile,"\n\t%s\n",tempstr); #endif #ifdef DEBUGDECISIONS AIPopMessage(tempstr); #endif #endif if (!pSoldier->bUnderEscort) { CancelAIAction(pSoldier,DONTFORCE); // no need to force this } else { // this is an escorted NPC, don't want to just completely stop // moving, try to find a nearby "next best" destination if possible pSoldier->usActionData = GoAsFarAsPossibleTowards(pSoldier,sGridno,pSoldier->bAction); // if it's not possible to get any closer if (pSoldier->usActionData == NOWHERE) { ubGottaCancel = TRUE; } else { // change his desired destination to this new one sGridno = pSoldier->usActionData; // GoAsFar... sets pathStored TRUE only if he could go all the way // make him go to it (needed to continue movement across multiple turns) NewDest(pSoldier,sGridno); // make sure that it worked (check that pSoldier->sDestination == pSoldier->sGridNo) if (pSoldier->sDestination == sGridno) ubSuccess = TRUE; else ubGottaCancel = TRUE; } if (ubGottaCancel) { // can't get close, gotta abort the movement! CancelAIAction(pSoldier,FORCE); // tell the player doing the escorting that civilian has stopped //EscortedMoveCanceled(pSoldier,COMMUNICATE); } } } return(ubSuccess); }
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 ); }