Changes to covert operations feature (by sevenfm): If the new skill setting COVERT_STRIPIFUNCOVERED is FALSE,

- we can only disguise successfully if we haven't been seen recently (last 3 turns)
- disabled automatic clothes stripping when uncovered
- redisguise automatically if spy haven't been seen by enemy recently and wears correct clothes

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8210 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2016-05-12 22:27:54 +00:00
parent e43d1b3fb3
commit 284910e2d5
12 changed files with 245 additions and 88 deletions
+106 -7
View File
@@ -1084,7 +1084,7 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK,
// sevenfm: only if we don't know enemy location or noise source is close and we have not seen enemy recently
if (iPathCost != 0 &&
!AICheckIsFlanking(pSoldier) &&
(TileIsOutOfBounds(sClosestDisturbance) || iPathCost < iShortestPath && !GuySawEnemyThisTurnOrBefore(pSoldier)))
(TileIsOutOfBounds( sClosestDisturbance ) || iPathCost < iShortestPath && !GuySawEnemy( pSoldier )) )
{
if (fClimbingNecessary)
{
@@ -1119,7 +1119,7 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK,
// sevenfm: only if we don't know enemy location or noise source is close and we have not seen enemy recently
if (iPathCost != 0 &&
!AICheckIsFlanking(pSoldier) &&
(TileIsOutOfBounds(sClosestDisturbance) || iPathCost < iShortestPath && !GuySawEnemyThisTurnOrBefore(pSoldier)))
(TileIsOutOfBounds(sClosestDisturbance) || iPathCost < iShortestPath && !GuySawEnemy(pSoldier)))
{
if (fClimbingNecessary)
{
@@ -1767,22 +1767,45 @@ INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT32 sDestGridNo, INT
return( sPathCost );
}
BOOLEAN GuySawEnemyThisTurnOrBefore( SOLDIERTYPE * pSoldier )
BOOLEAN GuySawEnemy( SOLDIERTYPE * pSoldier, UINT8 ubMax )
{
UINT8 ubTeamLoop;
UINT8 ubIDLoop;
SOLDIERTYPE *pOpponent;
for ( ubTeamLoop = 0; ubTeamLoop < MAXTEAMS; ubTeamLoop++ )
for ( ubTeamLoop = 0; ubTeamLoop < MAXTEAMS; ++ubTeamLoop )
{
if(!gTacticalStatus.Team[ubTeamLoop].bTeamActive)//dnl ch58 070913 skip any inactive teams
continue;
if ( gTacticalStatus.Team[ ubTeamLoop ].bSide != pSoldier->bSide )
{
// consider guys in this team, which isn't on our side
for ( ubIDLoop = gTacticalStatus.Team[ ubTeamLoop ].bFirstID; ubIDLoop <= gTacticalStatus.Team[ ubTeamLoop ].bLastID; ubIDLoop++ )
for ( ubIDLoop = gTacticalStatus.Team[ ubTeamLoop ].bFirstID; ubIDLoop <= gTacticalStatus.Team[ ubTeamLoop ].bLastID; ++ubIDLoop )
{
pOpponent = MercPtrs[ubIDLoop];
// if this merc is inactive, at base, on assignment, or dead
if (!pOpponent)
{
continue;
}
// if this merc is neutral/on same side, he's not an opponent
if ( CONSIDERED_NEUTRAL( pSoldier, pOpponent ) || (pSoldier->bSide == pOpponent->bSide) )
{
continue;
}
// sevenfm: ignore empty vehicles
if( pOpponent->ubWhatKindOfMercAmI == MERC_TYPE__VEHICLE && GetNumberInVehicle( pOpponent->bVehicleID ) == 0 )
{
continue;
}
// if this guy SAW an enemy recently...
if ( pSoldier->aiData.bOppList[ ubIDLoop ] >= SEEN_CURRENTLY )
if( pSoldier->aiData.bOppList[ ubIDLoop ] >= SEEN_CURRENTLY &&
pSoldier->aiData.bOppList[ ubIDLoop ] <= ubMax )
{
return( TRUE );
}
@@ -1832,7 +1855,7 @@ INT32 ClosestReachableFriendInTrouble(SOLDIERTYPE *pSoldier, BOOLEAN * pfClimbin
// CJC: restrict "last one to radio" to only if that guy saw us this turn or last turn
// if this friend is not under fire, and isn't the last one to radio
if ( ! ( pFriend->aiData.bUnderFire || (pFriend->ubID == gTacticalStatus.Team[pFriend->bTeam].ubLastMercToRadio && GuySawEnemyThisTurnOrBefore( pFriend ) ) ) )
if ( !(pFriend->aiData.bUnderFire || (pFriend->ubID == gTacticalStatus.Team[pFriend->bTeam].ubLastMercToRadio && GuySawEnemy( pFriend ))) )
{
continue; // next merc
}
@@ -3867,3 +3890,79 @@ BOOLEAN SightCoverAtSpot( SOLDIERTYPE *pSoldier, INT32 sSpot )
return TRUE;
}
BOOLEAN EnemySeenSoldierRecently( SOLDIERTYPE *pSoldier, UINT8 ubMax )
{
UINT32 uiLoop;
SOLDIERTYPE *pOpponent;
//loop through all the enemies and determine the cover
for ( uiLoop = 0; uiLoop<guiNumMercSlots; ++uiLoop )
{
pOpponent = MercSlots[uiLoop];
// if this merc is inactive, at base, on assignment, dead, unconscious
if ( !pOpponent || pOpponent->stats.bLife < OKLIFE )
{
continue; // next merc
}
// if this man is neutral / on the same side, he's not an opponent
if ( CONSIDERED_NEUTRAL( pSoldier, pOpponent ) || (pSoldier->bSide == pOpponent->bSide) )
{
continue; // next merc
}
// sevenfm: ignore empty vehicles
if ( pOpponent->ubWhatKindOfMercAmI == MERC_TYPE__VEHICLE && GetNumberInVehicle( pOpponent->bVehicleID ) == 0 )
{
continue;
}
// if opponent is collapsed/breath collapsed
if ( pOpponent->bCollapsed || pOpponent->bBreathCollapsed )
{
continue;
}
// check that this opponent sees us
if ( pOpponent->aiData.bOppList[pSoldier->ubID] >= SEEN_CURRENTLY &&
pOpponent->aiData.bOppList[pSoldier->ubID] <= ubMax )
{
return(TRUE);
}
}
return FALSE;
}
UINT8 CountTeamSeeSoldier( INT8 bTeam, SOLDIERTYPE *pSoldier )
{
SOLDIERTYPE *pFriend;
UINT8 ubFriends = 0;
CHECKF( pSoldier );
if ( bTeam >= MAXTEAMS )
return 0;
for ( UINT16 cnt = gTacticalStatus.Team[bTeam].bFirstID; cnt <= gTacticalStatus.Team[bTeam].bLastID; ++cnt )
{
pFriend = MercPtrs[cnt];
if ( pFriend->bActive &&
pFriend->bInSector &&
pFriend->stats.bLife >= OKLIFE &&
!pFriend->bCollapsed &&
!pFriend->bBreathCollapsed )
{
if ( pFriend->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY ||
pFriend->aiData.bOppList[pSoldier->ubID] == SEEN_THIS_TURN )
{
++ubFriends;
}
}
}
return ubFriends;
}
+8 -8
View File
@@ -3462,7 +3462,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
}
if( !TileIsOutOfBounds(sFlankGridNo) &&
!GuySawEnemyThisTurnOrBefore(pSoldier) &&
!GuySawEnemy(pSoldier) &&
!pSoldier->aiData.bUnderFire &&
!Water(pSoldier->sGridNo, pSoldier->pathing.bLevel) &&
pSoldier->bInitialActionPoints >= APBPConstants[AP_MINIMUM] &&
@@ -3626,7 +3626,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
}
// sevenfm: don't help if seen enemy recently or under fire
if( GuySawEnemyThisTurnOrBefore(pSoldier) || pSoldier->aiData.bUnderFire )
if( GuySawEnemy(pSoldier) || pSoldier->aiData.bUnderFire )
{
bHelpPts -= 10;
}
@@ -3658,7 +3658,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
// if there is an opponent reachable
// sevenfm: allow seeking in prone stance if we haven't seen enemy for several turns
if (!TileIsOutOfBounds(sClosestDisturbance) &&
( gAnimControl[ pSoldier->usAnimState ].ubHeight != ANIM_PRONE || !GuySawEnemyThisTurnOrBefore(pSoldier) ) )
(gAnimControl[pSoldier->usAnimState].ubHeight != ANIM_PRONE || !GuySawEnemy( pSoldier )) )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: seek opponent");
//////////////////////////////////////////////////////////////////////
@@ -3750,7 +3750,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
( pSoldier->aiData.bOrders == SEEKENEMY ||
pSoldier->aiData.bOrders == FARPATROL ||
pSoldier->aiData.bOrders == CLOSEPATROL && NightTime() ) &&
(!GuySawEnemyThisTurnOrBefore( pSoldier ) || fOvercrowded ) &&
(!GuySawEnemy( pSoldier ) || fOvercrowded ) &&
!Water(pSoldier->sGridNo, pSoldier->pathing.bLevel) &&
pSoldier->bActionPoints >= APBPConstants[AP_MINIMUM] &&
( CountFriendsInDirection( pSoldier, sClosestDisturbance ) > 1 || NightTime() || fOvercrowded) )
@@ -10261,7 +10261,7 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK )
}
if ( !TileIsOutOfBounds( sFlankGridNo ) &&
!GuySawEnemyThisTurnOrBefore( pSoldier ) &&
!GuySawEnemy( pSoldier ) &&
!pSoldier->aiData.bUnderFire &&
!Water( pSoldier->sGridNo, pSoldier->pathing.bLevel ) &&
pSoldier->bInitialActionPoints >= APBPConstants[AP_MINIMUM] &&
@@ -10379,7 +10379,7 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK )
}
// sevenfm: don't help if seen enemy recently or under fire
if ( GuySawEnemyThisTurnOrBefore( pSoldier ) || pSoldier->aiData.bUnderFire )
if ( GuySawEnemy( pSoldier ) || pSoldier->aiData.bUnderFire )
{
bHelpPts -= 10;
}
@@ -10411,7 +10411,7 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK )
// if there is an opponent reachable
// sevenfm: allow seeking in prone stance if we haven't seen enemy for several turns
if ( !TileIsOutOfBounds( sClosestDisturbance ) &&
(gAnimControl[pSoldier->usAnimState].ubHeight != ANIM_PRONE || !GuySawEnemyThisTurnOrBefore( pSoldier )) )
(gAnimControl[pSoldier->usAnimState].ubHeight != ANIM_PRONE || !GuySawEnemy( pSoldier )) )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "ArmedVehicleDecideActionRed: seek opponent" );
//////////////////////////////////////////////////////////////////////
@@ -10460,7 +10460,7 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK )
(pSoldier->aiData.bOrders == SEEKENEMY ||
pSoldier->aiData.bOrders == FARPATROL ||
pSoldier->aiData.bOrders == CLOSEPATROL && NightTime( )) &&
(!GuySawEnemyThisTurnOrBefore( pSoldier ) || fOvercrowded) &&
(!GuySawEnemy( pSoldier ) || fOvercrowded) &&
!Water( pSoldier->sGridNo, pSoldier->pathing.bLevel ) &&
pSoldier->bActionPoints >= APBPConstants[AP_MINIMUM] &&
(CountFriendsInDirection( pSoldier, sClosestDisturbance ) > 1 || NightTime( ) || fOvercrowded) )
+16 -6
View File
@@ -12,6 +12,8 @@
#include "Soldier macros.h"
#endif
extern SECTOR_EXT_DATA SectorExternalData[256][4];
void CallAvailableEnemiesTo( INT32 sGridNo )
{
INT32 iLoop;
@@ -176,8 +178,15 @@ INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
pbPersOL = pSoldier->aiData.bOppList;
pbPublOL = gbPublicOpplist[pSoldier->bTeam];
// sevenfm: sector information
UINT8 sectordata = 0;
if ( gbWorldSectorZ > 0 ) // underground we are always suspicious
sectordata = 2;
else
sectordata = SectorExternalData[SECTOR( gWorldSectorX, gWorldSectorY )][gbWorldSectorZ].usCurfewValue;
// look through this man's personal & public opplists for opponents heard
for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
for (uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop)
{
pTemp = MercSlots[ uiLoop ];
@@ -195,7 +204,11 @@ INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
// green AI state: always ignore
// yellow AI state: 50% chance to ignore
if ( pSoldier->aiData.bAlertStatus == STATUS_GREEN || (pSoldier->aiData.bAlertStatus == STATUS_YELLOW && Random(2) ) )
continue; // next merc
continue;
// sevenfm: ignore noise if some friends already see opponent
if ( CountTeamSeeSoldier( pSoldier->bTeam, pTemp ) > sectordata )
continue;
}
pbPersOL = pSoldier->aiData.bOppList + pTemp->ubID;
@@ -232,7 +245,6 @@ INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
bBestLevel = gbPublicLastKnownOppLevel[pSoldier->bTeam][pTemp->ubID];
}
}
}
// if any "misc. noise" was also heard recently
@@ -258,8 +270,7 @@ INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
pSoldier->aiData.ubNoiseVolume = 0;
}
}
// if any recent PUBLIC "misc. noise" is also known
if ( (pSoldier->bTeam != CIV_TEAM) || ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
{
@@ -280,7 +291,6 @@ INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
}
}
}
}
if (!TileIsOutOfBounds(sBestGridNo) && pfReachable )
+4 -1
View File
@@ -278,12 +278,15 @@ UINT8 GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTe
INT16 MaxNormalVisionDistance( void );
UINT8 MinFlankDirections( SOLDIERTYPE *pSoldier );
UINT8 CountFriendsInDirection( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo );
BOOLEAN GuySawEnemyThisTurnOrBefore( SOLDIERTYPE * pSoldier );
BOOLEAN GuySawEnemy( SOLDIERTYPE * pSoldier, UINT8 ubMax = SEEN_3_TURNS_AGO );
UINT8 CountNearbyFriends( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance );
UINT8 CountNearbyFriendsLastAttackHit( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance );
UINT8 CountFriendsFlankSameSpot( SOLDIERTYPE *pSoldier );
UINT8 CountFriendsBlack( SOLDIERTYPE *pSoldier, INT32 sClosestOpponent = NOWHERE );
BOOLEAN EnemySeenSoldierRecently( SOLDIERTYPE *pSoldier, UINT8 ubMax = SEEN_3_TURNS_AGO );
UINT8 CountTeamSeeSoldier( INT8 bTeam, SOLDIERTYPE *pSoldier );
BOOLEAN AICheckFriendsNoContact( SOLDIERTYPE *pSoldier );
BOOLEAN AICheckIsFlanking( SOLDIERTYPE *pSoldier );