Exemplo n.º 1
0
UINT16 RealtimeDelay( SOLDIERTYPE * pSoldier )
{
	if ( PTR_CIV_OR_MILITIA && !(pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
	{
		return( (UINT16) REALTIME_CIV_AI_DELAY );
	}
	else if ( CREATURE_OR_BLOODCAT( pSoldier ) && !( pSoldier->aiData.bHunting ) )
	{
		return( (UINT16) REALTIME_CREATURE_AI_DELAY );
	}
	else
	{

		if ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP )
		{
			//DBrot: More Rooms
			//UINT8		ubRoom;
			UINT16 usRoom;

			if ( InARoom( pSoldier->sGridNo, &usRoom ) && IN_BROTHEL( usRoom ) )
			{
				return( (UINT16) (REALTIME_AI_DELAY / 3) );
			}
		}

		return( (UINT16) REALTIME_AI_DELAY );
	}

}
Exemplo n.º 2
0
void BoxingMovementCheck( SOLDIERTYPE * pSoldier )
{
	//DBrot: More Rooms
	//UINT8 ubRoom;
	UINT16	usRoom;

	if ( InARoom( pSoldier->sGridNo, &usRoom ) && usRoom == BOXING_RING)
	{
		// someone moving in/into the ring
		CountPeopleInBoxingRingAndDoActions();
	}
	else if ( ( gTacticalStatus.bBoxingState == BOXING ) && ( pSoldier->flags.uiStatusFlags & SOLDIER_BOXER ) )
	{
		// boxer stepped out of the ring!
		BoxingPlayerDisqualified( pSoldier, BOXER_OUT_OF_RING );
		// add the history record here.
		AddHistoryToPlayersLog( HISTORY_DISQUALIFIED_BOXING, pSoldier->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY );
		// make not a boxer any more
		pSoldier->DeleteBoxingFlag( );
		pSoldier->flags.uiStatusFlags &= (~SOLDIER_PCUNDERAICONTROL);
	}
}
Exemplo n.º 3
0
UINT8 CountPeopleInBoxingRing( void )
{
	SOLDIERTYPE * pSoldier;
	UINT32 uiLoop;
	//DBrot: More Rooms
	//UINT8 ubRoom;
	UINT16	usRoom;
	UINT8 ubTotalInRing = 0;

	for ( uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop )
	{
		pSoldier = MercSlots[ uiLoop ];

		if ( pSoldier != NULL )
		{
			if ( InARoom( pSoldier->sGridNo, &usRoom ) && usRoom == BOXING_RING)
			{
				++ubTotalInRing;
			}
		}
	}

	return( ubTotalInRing );
}
Exemplo n.º 4
0
INT16 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT16 sDesGrid, INT8 bReserveAPs, INT8 bAction, INT8 fFlags )
{
	INT16 sLoop,sAPCost;
	INT16 sTempDest,sGoToGrid;
	INT16 sOrigin;
	UINT16 usMaxDist;
	UINT8 ubDirection,ubDirsLeft,ubDirChecked[8],fFound = FALSE;
	INT8 bAPsLeft, fPathFlags;
	UINT8 ubRoomRequired = 0, ubTempRoom;

	if ( bReserveAPs == -1 )
	{
		// default reserve points
		if ( CREATURE_OR_BLOODCAT( pSoldier ) )
		{
			bReserveAPs = 0;
		}
		else
		{
			bReserveAPs = MAX_AP_CARRIED;
		}
	}

	sTempDest = -1;

	// obtain maximum roaming distance from soldier's sOrigin
	usMaxDist = RoamingRange(pSoldier,&sOrigin);

	if ( pSoldier->bOrders <= CLOSEPATROL && (pSoldier->bTeam == CIV_TEAM || pSoldier->ubProfile != NO_PROFILE ) )
	{
		if ( InARoom( pSoldier->usPatrolGrid[0], &ubRoomRequired ) )
		{
			// make sure this doesn't interfere with pathing for scripts
			if ( pSoldier->sAbsoluteFinalDestination != NOWHERE )
			{
				ubRoomRequired = 0;
			}
		}
	}

	pSoldier->usUIMovementMode = DetermineMovementMode(pSoldier, bAction );
	if ( pSoldier->usUIMovementMode == RUNNING && fFlags & FLAG_CAUTIOUS )
	{
		pSoldier->usUIMovementMode = WALKING;
	}

#ifdef DEBUGDECISIONS
	sprintf(tempstr,"%s wants to go towards %d (has range %d)",pSoldier->name,sDesGrid,usMaxDist);
	AIPopMessage(tempstr);
#endif

	// if soldier is ALREADY at the desired destination, quit right away
	if (sDesGrid == pSoldier->sGridNo)
	{
		return(NOWHERE);
	}

	// don't try to approach go after noises or enemies actually in water
	// would be too easy to throw rocks in water, etc. & distract the AI
	if (Water(sDesGrid))
	{
		return(NOWHERE);
	}

	fPathFlags = 0;
	if ( CREATURE_OR_BLOODCAT( pSoldier ) )
	{	/*
		if ( PythSpacesAway( pSoldier->sGridNo, sDesGrid ) <= PATH_CLOSE_RADIUS )
		{
			// then do a limited range path search and see if we can get there
			gubNPCDistLimit = 10;
			if ( !LegalNPCDestination( pSoldier, sDesGrid, ENSURE_PATH, NOWATER, fPathFlags) )
			{
				gubNPCDistLimit = 0;
				return( NOWHERE );
			}
			else
			{
				// allow attempt to path without 'good enough' flag on
				gubNPCDistLimit = 0;
			}
		}
		else
		{
		*/
			fPathFlags = PATH_CLOSE_GOOD_ENOUGH;
		//}
	}

	// first step: try to find an OK destination at or near the desired gridno
	if (!LegalNPCDestination(pSoldier,sDesGrid,ENSURE_PATH,NOWATER,fPathFlags))
	{
#ifdef DEBUGDECISIONS
		AIPopMessage("destination Grid # itself not valid, looking around it");
#endif
		if ( CREATURE_OR_BLOODCAT( pSoldier ) )
		{
			// we tried to get close, failed; abort!
			return( NOWHERE );
		}
		else
		{
			// else look at the 8 nearest gridnos to sDesGrid for a valid destination

			// clear ubDirChecked flag for all 8 directions
			for (ubDirection = 0; ubDirection < 8; ubDirection++)
				ubDirChecked[ubDirection] = FALSE;

			ubDirsLeft = 8;

			// examine all 8 spots around 'sDesGrid'
			// keep looking while directions remain and a satisfactory one not found
			for (ubDirsLeft = 8; ubDirsLeft != 0; ubDirsLeft--)
			{
				if (fFound)
				{
					break;
				}
				// randomly select a direction which hasn't been 'checked' yet
				do
				{
					ubDirection = (UINT8) Random(8);
				}
				while (ubDirChecked[ubDirection]);

				ubDirChecked[ubDirection] = TRUE;

				// determine the gridno 1 tile away from current friend in this direction
				sTempDest = NewGridNo(sDesGrid,DirectionInc( (INT16)(ubDirection + 1) ));

				// if that's out of bounds, ignore it & check next direction
				if (sTempDest == sDesGrid)
					continue;

				if (LegalNPCDestination(pSoldier,sTempDest,ENSURE_PATH,NOWATER,0))
				{
					fFound = TRUE;            // found a spot

#ifdef DEBUGDECISIONS
					AINumMessage("Found a spot!  ubDirection = ",ubDirection + 1);
#endif

					break;                   // stop checking in other directions
				}
			}

			if (!fFound)
			{
#ifdef DEBUGDECISIONS
				AINumMessage("Couldn't find OK destination around grid #",sDesGrid);
#endif

				return(NOWHERE);
			}

			// found a good grid #, this becomes our actual desired grid #
			sDesGrid = sTempDest;
		}
	}

 // HAVE FOUND AN OK destination AND PLOTTED A VALID BEST PATH TO IT


#ifdef DEBUGDECISIONS
 AINumMessage("Chosen legal destination is gridno ",sDesGrid);
 AINumMessage("Tracing along path, pathRouteToGo = ",pSoldier->pathRouteToGo);
#endif

 sGoToGrid = pSoldier->sGridNo;      // start back where soldier is standing now
 sAPCost = 0;		      // initialize path cost counter

 // we'll only go as far along the plotted route as is within our
 // permitted roaming range, and we'll stop as soon as we're down to <= 5 APs

 for (sLoop = 0; sLoop < (pSoldier->usPathDataSize - pSoldier->usPathIndex); sLoop++)
  {
   // what is the next gridno in the path?

	 //sTempDest = NewGridNo( sGoToGrid,DirectionInc( (INT16) (pSoldier->usPathingData[sLoop] + 1) ) );
	 sTempDest = NewGridNo( sGoToGrid,DirectionInc( (INT16) (pSoldier->usPathingData[sLoop]) ) );
   //NumMessage("sTempDest = ",sTempDest);

   // this should NEVER be out of bounds
   if (sTempDest == sGoToGrid)
    {
#ifdef BETAVERSION
     sprintf(tempstr,"GoAsFarAsPossibleTowards: ERROR - gridno along valid route is invalid!  guynum %d, sTempDest = %d",pSoldier->ubID,sTempDest);

#ifdef RECORDNET
     fprintf(NetDebugFile,"\n\t%s\n",tempstr);
#endif

     PopMessage(tempstr);
     SaveGame(ERROR_SAVE);
#endif

     break;           // quit here, sGoToGrid is where we are going
    }

   // if this takes us beyond our permitted "roaming range"
   if (SpacesAway(sOrigin,sTempDest) > usMaxDist)
     break;           // quit here, sGoToGrid is where we are going


	 if ( ubRoomRequired )
	 {
		if ( !( InARoom( sTempDest, &ubTempRoom ) && ubTempRoom == ubRoomRequired ) )
		{
		 // quit here, limited by room!
		 break;
		}
	 }

   if ( (fFlags & FLAG_STOPSHORT) && SpacesAway( sDesGrid, sTempDest ) <= STOPSHORTDIST )
	 {
     break;           // quit here, sGoToGrid is where we are going
	 }

   // if this gridno is NOT a legal NPC destination
   // DONT'T test path again - that would replace the traced path! - Ian
   // NOTE: It's OK to go *THROUGH* water to try and get to the destination!
   if (!LegalNPCDestination(pSoldier,sTempDest,IGNORE_PATH,WATEROK,0))
     break;           // quit here, sGoToGrid is where we are going


   // CAN'T CALL PathCost() HERE! IT CALLS findBestPath() and overwrites
   //       pathRouteToGo !!!  Gotta calculate the cost ourselves - Ian
   //
   //ubAPsLeft = pSoldier->bActionPoints - PathCost(pSoldier,sTempDest,FALSE,FALSE,FALSE,FALSE,FALSE);

	 if (gfTurnBasedAI)
	 {
		 // if we're just starting the "costing" process (first gridno)
		 if (sLoop == 0)
			{
			/*
			 // first, add any additional costs - such as intermediate animations, etc.
			 switch(pSoldier->anitype[pSoldier->anim])
				{
				 // in theory, no NPC should ever be in one of these animations as
				 // things stand (they don't medic anyone), but leave it for robustness
				 case START_AID   :
				 case GIVING_AID  : sAnimCost = AP_STOP_FIRST_AID;
					break;

				 case TWISTOMACH  :
				 case COLLAPSED   : sAnimCost = AP_GET_UP;
					break;

				 case TWISTBACK   :
				 case UNCONSCIOUS : sAnimCost = (AP_ROLL_OVER + AP_GET_UP);
					break;

				 default          : sAnimCost = 0;
				}

			 // this is our first cost
			 sAPCost += sAnimCost;
			 */

			 if (pSoldier->usUIMovementMode == RUNNING)
			 {
				sAPCost += AP_START_RUN_COST;
			 }
			}

		 // ATE: Direction here?
		 sAPCost += EstimateActionPointCost( pSoldier, sTempDest, (INT8) pSoldier->usPathingData[sLoop], pSoldier->usUIMovementMode, (INT8) sLoop, (INT8) pSoldier->usPathDataSize );

		 bAPsLeft = pSoldier->bActionPoints - sAPCost;
	 }

	 // if after this, we have <= 5 APs remaining, that's far enough, break out
	 // (the idea is to preserve APs so we can crouch or react if
	 // necessary, and benefit from the carry-over next turn if not needed)
	 // This routine is NOT used by any GREEN AI, so such caution is warranted!

	 if ( gfTurnBasedAI && (bAPsLeft < bReserveAPs) )
		 break;
	 else
		{
		 sGoToGrid = sTempDest;    // we're OK up to here

		 // if exactly 5 APs left, don't bother checking any further
		 if ( gfTurnBasedAI && (bAPsLeft == bReserveAPs) )
			 break;
		}		
  }


 // if it turned out we couldn't go even 1 tile towards the desired gridno
 if (sGoToGrid == pSoldier->sGridNo)
  {
#ifdef DEBUGDECISIONS
   sprintf(tempstr,"%s will go NOWHERE, path doesn't meet criteria",pSoldier->name);
   AIPopMessage(tempstr);
#endif

   return(NOWHERE);             // then go nowhere
  }
 else
  {
   // possible optimization - stored path IS good if we're going all the way
   if (sGoToGrid == sDesGrid)
	 {
     pSoldier->bPathStored = TRUE;
		 pSoldier->sFinalDestination = sGoToGrid;
	 }
	 else if ( pSoldier->usPathIndex == 0 )
	 {
		// we can hack this surely! -- CJC
     pSoldier->bPathStored = TRUE; 
		 pSoldier->sFinalDestination = sGoToGrid;
		 pSoldier->usPathDataSize = sLoop + 1;
	 }

#ifdef DEBUGDECISIONS
		ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"%d to %d with %d APs left", pSoldier->ubID, sGoToGrid, pSoldier->bActionPoints );
 #endif


		return( sGoToGrid );
  }
}
Exemplo n.º 5
0
void ExitBoxing( void )
{
	//DBrot: More Rooms
	//UINT8						ubRoom;
	UINT16				usRoom;
	SOLDIERTYPE*		pSoldier;
	UINT32				uiLoop;
	UINT8				ubPass;

	// find boxers and turn them neutral again

	// first time through loop, look for AI guy, then for PC guy.... for stupid
	// oppcnt/alert status reasons
	for( ubPass = 0; ubPass < 2; ++ubPass )
	{
		// because boxer could die, loop through all soldier ptrs
		for ( uiLoop = 0; uiLoop < gTacticalStatus.Team[ CIV_TEAM ].bLastID; ++uiLoop )
		{
			pSoldier = MercPtrs[ uiLoop ];

			if ( pSoldier != NULL )
			{
				if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_BOXER ) && InARoom( pSoldier->sGridNo, &usRoom ) && usRoom == BOXING_RING )
				{
					if ( pSoldier->flags.uiStatusFlags & SOLDIER_PC )
					{
						if ( ubPass == 0 ) // pass 0, only handle AI
						{
							continue;
						}
						// put guy under AI control temporarily
						pSoldier->flags.uiStatusFlags |= SOLDIER_PCUNDERAICONTROL;
						//SB: this flag don't allow merc leave the ring
						pSoldier->flags.uiStatusFlags &= ~SOLDIER_ENGAGEDINACTION;
					}
					else
					{
						if ( ubPass == 1 ) // pass 1, only handle PCs
						{
							continue;
						}
						// reset AI boxer to neutral
						SetSoldierNeutral( pSoldier );
						RecalculateOppCntsDueToBecomingNeutral( pSoldier );
					}
					CancelAIAction( pSoldier, TRUE );
					pSoldier->aiData.bAlertStatus = STATUS_GREEN;
					pSoldier->aiData.bUnderFire = 0;

					// HEADROCK HAM 3.6: Make sure all boxers' APs have been reset to a reasonable number. Otherwise,
                    // the AI combatant may fail several conditions in subsequent functions, and fail to leave the ring
                    // as a result.
                    if (pSoldier->bActionPoints < (APBPConstants[AP_MAXIMUM]*6)/10)
                    {
                        pSoldier->bActionPoints = (APBPConstants[AP_MAXIMUM]*6)/10;
                    }

					// if necessary, revive boxer so he can leave ring
					if (pSoldier->stats.bLife > 0 && (pSoldier->stats.bLife < OKLIFE || pSoldier->bBreath < OKBREATH ) )
					{
						pSoldier->stats.bLife = __max( OKLIFE * 2, pSoldier->stats.bLife );
						if (pSoldier->bBreath < 100)
						{
							// deduct -ve BPs to grant some BPs back (properly)
							DeductPoints( pSoldier, 0, (INT16) - ( (100 - pSoldier->bBreath) * 100 ) );
						}
						pSoldier->BeginSoldierGetup( );
					}
				}
			}
		}
	}

	DeleteTalkingMenu();

	EndAllAITurns();

	if ( CheckForEndOfCombatMode( FALSE ) )
	{
		EndTopMessage();
		
		#ifdef NEWMUSIC
		GlobalSoundID  = MusicSoundValues[ SECTOR( gWorldSectorX, gWorldSectorY ) ].SoundTacticalNothing[gbWorldSectorZ];
		if ( MusicSoundValues[ SECTOR( gWorldSectorX, gWorldSectorY ) ].SoundTacticalNothing[gbWorldSectorZ] != -1 )
			SetMusicModeID( MUSIC_TACTICAL_NOTHING, MusicSoundValues[ SECTOR( gWorldSectorX, gWorldSectorY ) ].SoundTacticalNothing[gbWorldSectorZ] );	
		else
		#endif
		SetMusicMode( MUSIC_TACTICAL_NOTHING );

		// Lock UI until we get out of the ring
		guiPendingOverrideEvent = LU_BEGINUILOCK;
	}
}
Exemplo n.º 6
0
void CountPeopleInBoxingRingAndDoActions( void )
{
	UINT32				uiLoop;
	UINT8				ubTotalInRing = 0;
	//DBrot: More Rooms
	UINT16				usRoom;
	UINT16				ubPlayersInRing = 0;
	SOLDIERTYPE *		pSoldier;
	SOLDIERTYPE *		pInRing[2] = { NULL, NULL };
	SOLDIERTYPE *		pNonBoxingPlayer = NULL;

	for ( uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop )
	{
		pSoldier = MercSlots[ uiLoop ];

		if ( pSoldier != NULL )
		{
			if ( InARoom( pSoldier->sGridNo, &usRoom ) && usRoom == BOXING_RING)
			{
				if ( ubTotalInRing < 2 )
				{
					pInRing[ ubTotalInRing ] = pSoldier;
				}
				++ubTotalInRing;

				if ( pSoldier->flags.uiStatusFlags & SOLDIER_PC )
				{
					++ubPlayersInRing;

					if ( !pNonBoxingPlayer && !(pSoldier->flags.uiStatusFlags & SOLDIER_BOXER) )
					{
						pNonBoxingPlayer = pSoldier;
					}
				}
			}
		}
	}

	if ( ubPlayersInRing > 1 )
	{
		// boxing match just became invalid!
		if ( gTacticalStatus.bBoxingState <= PRE_BOXING )
		{
			BoxingPlayerDisqualified( pNonBoxingPlayer, NON_BOXER_IN_RING );
			// set to not in boxing or it won't be handled otherwise
			SetBoxingState( NOT_BOXING );
		}
		else
		{
			BoxingPlayerDisqualified( pNonBoxingPlayer, NON_BOXER_IN_RING );
		}

		return;
	}

	if ( gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER )
	{
		if ( ubTotalInRing == 1 && ubPlayersInRing == 1 )
		{
			// time to go to pre-boxing
			SetBoxingState( PRE_BOXING );
			PickABoxer();
		}
	}
	else
	{
		// if pre-boxing, check for two people (from different teams!) in the ring
		if (gTacticalStatus.bBoxingState == PRE_BOXING)
		{
			if (ubTotalInRing == 2 && ubPlayersInRing == 1)
			{
				// ladieees and gennleman, we have a fight!
				for (uiLoop = 0; uiLoop < 2; ++uiLoop)
				{
					if (!(pInRing[uiLoop]->flags.uiStatusFlags & SOLDIER_BOXER))
					{
						// set as boxer!
						pInRing[uiLoop]->flags.uiStatusFlags |= SOLDIER_BOXER;
					}
				}
				// start match!
				SetBoxingState(BOXING);
				gfLastBoxingMatchWonByPlayer = FALSE;

#ifdef JA2TESTVERSION
				ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Boxer APs %d %d", pInRing[0]->bActionPoints, pInRing[1]->bActionPoints );
#endif
				// give the first turn to a randomly chosen boxer
				EnterCombatMode(pInRing[Random(2)]->bTeam);
			}
		}
		/*
		else
		{
		// check to see if the player has more than one person in the ring
		if ( ubPlayersInRing > 1 )
		{
		// boxing match just became invalid!
		BoxingPlayerDisqualified( pNonBoxingPlayer, NON_BOXER_IN_RING );
		return;
		}
		}
		*/
	}
}
Exemplo n.º 7
0
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 );

}
Exemplo n.º 8
0
void RTHandleAI( SOLDIERTYPE * pSoldier )
{
#ifdef AI_PROFILING
	INT32 iLoop;
#endif

	if ((pSoldier->aiData.bAction != AI_ACTION_NONE) && pSoldier->aiData.bActionInProgress)
	{
		// if action should remain in progress
		if (ActionInProgress(pSoldier))
		{
			#ifdef DEBUGBUSY
				AINumMessage("Busy with action, skipping guy#",pSoldier->ubID);
			#endif
			// let it continue
			return;
		}
	}

	// Flugente: prisoners of war don't do anything
	if ( pSoldier->usSoldierFlagMask & SOLDIER_POW )
		return;

	// if man has nothing to do
	if (pSoldier->aiData.bAction == AI_ACTION_NONE)
	{
		if (pSoldier->aiData.bNextAction == AI_ACTION_NONE)
		{
			// make sure this flag is turned off (it already should be!)
			pSoldier->aiData.bActionInProgress = FALSE;

			// truly nothing to do!
			RefreshAI( pSoldier );
		}

		// Since we're NEVER going to "continue" along an old path at this point,
		// then it would be nice place to reinitialize "pathStored" flag for
		// insurance purposes.
		//
		// The "pathStored" variable controls whether it's necessary to call
		// findNewPath() after you've called NewDest(). Since the AI calls
		// findNewPath() itself, a speed gain can be obtained by avoiding
		// redundancy.
		//
		// The "normal" way for pathStored to be reset is inside
		// SetNewCourse() [which gets called after NewDest()].
		//
		// The only reason we would NEED to reinitialize it here is if I've
		// incorrectly set pathStored to TRUE in a process that doesn't end up
		// calling NewDest()
		pSoldier->pathing.bPathStored = FALSE;

		// decide on the next action
#ifdef AI_PROFILING
		for (iLoop = 0; iLoop < 1000; iLoop++)
#endif
		{
			if (pSoldier->aiData.bNextAction != AI_ACTION_NONE)
			{
				if ( pSoldier->aiData.bNextAction == AI_ACTION_END_COWER_AND_MOVE )
				{
					if ( pSoldier->flags.uiStatusFlags & SOLDIER_COWERING )
					{
						pSoldier->aiData.bAction = AI_ACTION_STOP_COWERING;
						pSoldier->aiData.usActionData = ANIM_STAND;
					}
					else if ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight < ANIM_STAND )
					{
						// stand up!
						pSoldier->aiData.bAction = AI_ACTION_CHANGE_STANCE;
						pSoldier->aiData.usActionData = ANIM_STAND;
					}
					else
					{
						pSoldier->aiData.bAction = AI_ACTION_NONE;
					}
					if ( pSoldier->sGridNo == pSoldier->aiData.usNextActionData )
					{
						// no need to walk after this
						pSoldier->aiData.bNextAction = AI_ACTION_NONE;
						pSoldier->aiData.usNextActionData = NOWHERE;
					}
					else
					{
						pSoldier->aiData.bNextAction = AI_ACTION_WALK;
						// leave next-action-data as is since that's where we want to go
					}
				}
				else
				{
					// do the next thing we have to do...
					pSoldier->aiData.bAction = pSoldier->aiData.bNextAction;
					pSoldier->aiData.usActionData = pSoldier->aiData.usNextActionData;
					pSoldier->bTargetLevel = pSoldier->aiData.bNextTargetLevel;
					pSoldier->aiData.bNextAction = AI_ACTION_NONE;
					pSoldier->aiData.usNextActionData = 0;
					pSoldier->aiData.bNextTargetLevel = 0;
				}
				if (pSoldier->aiData.bAction == AI_ACTION_PICKUP_ITEM)
				{
					// the item pool index was stored in the special data field
					pSoldier->aiData.uiPendingActionData1 = pSoldier->iNextActionSpecialData;
				}
			}			
			else if (!TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination))
			{
				if ( ACTING_ON_SCHEDULE( pSoldier ) )
				{
					pSoldier->aiData.bAction = AI_ACTION_SCHEDULE_MOVE;
				}
				else
				{
					pSoldier->aiData.bAction = AI_ACTION_WALK;
				}
				pSoldier->aiData.usActionData = pSoldier->sAbsoluteFinalDestination;
			}
			else
			{
				if (!(gTacticalStatus.uiFlags & ENGAGED_IN_CONV))
				{
                    if(!pSoldier->ai_masterplan_) // if the Soldier has no plan, create one
                    {
                        if(pSoldier->bAIIndex == 0) // not yet initialized, use bTeam+1 as default
                            pSoldier->bAIIndex = pSoldier->bTeam + 1;
                        AI::tactical::AIInputData ai_input;
                        AI::tactical::PlanFactoryLibrary* plan_lib(AI::tactical::PlanFactoryLibrary::instance());
                        pSoldier->ai_masterplan_ = plan_lib->create_plan(pSoldier->bAIIndex, pSoldier, ai_input);
                    }
                    AI::tactical::PlanInputData plan_input(false, gTacticalStatus);
                    pSoldier->ai_masterplan_->execute(plan_input);
				}
			}
		}
		// if he chose to continue doing nothing
		if (pSoldier->aiData.bAction == AI_ACTION_NONE)
		{
			#ifdef RECORDNET
				fprintf(NetDebugFile,"\tMOVED BECOMING TRUE: Chose to do nothing, guynum %d\n",pSoldier->ubID);
			#endif

			// do a standard wait before doing anything else!
			pSoldier->aiData.bAction = AI_ACTION_WAIT;
			//if (PTR_CIVILIAN && pSoldier->aiData.bAlertStatus != STATUS_BLACK)
			if ( PTR_CIV_OR_MILITIA && !(pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
			{
				pSoldier->aiData.usActionData = (UINT16) REALTIME_CIV_AI_DELAY;
			}
			else if ( CREATURE_OR_BLOODCAT( pSoldier ) && !( pSoldier->aiData.bHunting ) )
			{
				pSoldier->aiData.usActionData = (UINT16) REALTIME_CREATURE_AI_DELAY;
			}
			else
			{
				pSoldier->aiData.usActionData = (UINT16) REALTIME_AI_DELAY;
				if ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP )
				{
					//DBrot: More Rooms
					//UINT8		ubRoom;
					UINT16 usRoom;

					if ( InARoom( pSoldier->sGridNo, &usRoom ) && IN_BROTHEL( usRoom ) )
					{
						pSoldier->aiData.usActionData /= 3;
					}

				}
			}
		}
		else if (pSoldier->aiData.bAction == AI_ACTION_ABSOLUTELY_NONE)
		{
			pSoldier->aiData.bAction = AI_ACTION_NONE;
		}

	}

	// to get here, we MUST have an action selected, but not in progress...
	NPCDoesAct(pSoldier);

	// perform the chosen action
	pSoldier->aiData.bActionInProgress = ExecuteAction(pSoldier); // if started, mark us as busy
}
Exemplo n.º 9
0
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);
}