- New Feature: enemy assassins disguise as militia and can ambush player mercs

- Fix: invalid GridNo for mounting weapons

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5753 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2012-12-30 19:20:36 +00:00
parent 3e859f91a8
commit e193f05865
31 changed files with 600 additions and 139 deletions
+53
View File
@@ -1459,6 +1459,59 @@ INT32 ClosestPC( SOLDIERTYPE *pSoldier, INT32 * psDistance )
return( sGridNo );
}
// Flugente: like ClosestPC(...), but does not account for covert or not visible mercs
INT32 ClosestUnDisguisedPC( SOLDIERTYPE *pSoldier, INT32 * psDistance )
{
// used by NPCs... find the closest PC
// NOTE: skips EPCs!
UINT8 ubLoop;
SOLDIERTYPE *pTargetSoldier;
INT32 sMinDist = WORLD_MAX;
INT32 sDist;
INT32 sGridNo = NOWHERE;
// Loop through all mercs on player team
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( ; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++)
{
pTargetSoldier = Menptr + ubLoop;
if (!pTargetSoldier->bActive || !pTargetSoldier->bInSector)
continue;
// if not conscious, skip him
if (pTargetSoldier->stats.bLife < OKLIFE)
continue;
if ( AM_AN_EPC( pTargetSoldier ) )
continue;
if ( pTargetSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
continue;
sDist = PythSpacesAway(pSoldier->sGridNo,pTargetSoldier->sGridNo);
// if this PC is not visible to the soldier, then add a penalty to the distance
// so that we weight in favour of visible mercs
if ( pTargetSoldier->bTeam != pSoldier->bTeam && pSoldier->aiData.bOppList[ ubLoop ] != SEEN_CURRENTLY )
continue;
if (sDist < sMinDist)
{
sMinDist = sDist;
sGridNo = pTargetSoldier->sGridNo;
}
}
if ( psDistance )
{
*psDistance = sMinDist;
}
return( sGridNo );
}
INT32 FindClosestClimbPointAvailableToAI( SOLDIERTYPE * pSoldier, INT32 sStartGridNo, INT32 sDesiredGridNo, BOOLEAN fClimbUp )
{
INT32 sGridNo;
+1 -1
View File
@@ -440,7 +440,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
//NumMessage("SHOT AttackValue = ",iAttackValue / 1000);
// special stuff for assassins to ignore militia more
if ( pSoldier->ubProfile >= JIM && pSoldier->ubProfile <= TYRONE && pOpponent->bTeam == MILITIA_TEAM )
if ( pSoldier->IsAssassin() && pOpponent->bTeam == MILITIA_TEAM )
{
iAttackValue /= 2;
}
+61 -19
View File
@@ -662,14 +662,8 @@ INT8 DecideActionNamedNPC( SOLDIERTYPE * pSoldier )
}
}
switch( pSoldier->ubProfile )
if ( pSoldier->IsAssassin() )
{
case JIM:
case JACK:
case OLAF:
case RAY:
case OLGA:
case TYRONE:
sDesiredMercLoc = ClosestPC( pSoldier, &sDesiredMercDist );
if (!TileIsOutOfBounds(sDesiredMercLoc))
@@ -691,9 +685,6 @@ INT8 DecideActionNamedNPC( SOLDIERTYPE * pSoldier )
}
}
}
break;
default:
break;
}
return( AI_ACTION_NONE );
@@ -838,9 +829,36 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
}
if (pSoldier->ubProfile != NO_PROFILE)
if ( pSoldier->ubProfile != NO_PROFILE || pSoldier->IsAssassin() )
{
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
if ( pSoldier->ubProfile != NO_PROFILE )
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
else
{
INT32 sDesiredMercDist;
INT32 sDesiredMercLoc = ClosestUnDisguisedPC( pSoldier, &sDesiredMercDist );
if (!TileIsOutOfBounds(sDesiredMercLoc))
{
if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 )
{
AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID );
// now wait a bit!
pSoldier->aiData.usActionData = 5000;
pSoldier->aiData.bAction = AI_ACTION_WAIT;
}
else
{
pSoldier->aiData.usActionData = GoAsFarAsPossibleTowards( pSoldier, sDesiredMercLoc, AI_ACTION_APPROACH_MERC );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
pSoldier->aiData.bAction = AI_ACTION_APPROACH_MERC;
}
}
}
}
if ( pSoldier->aiData.bAction != AI_ACTION_NONE )
{
return( pSoldier->aiData.bAction );
@@ -852,9 +870,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
// turn off counter so we don't check it again
pSoldier->uiTimeSinceLastSpoke = 0;
}
}
// if not in the way, do nothing most of the time
@@ -1440,18 +1456,44 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
// ******************
// REAL TIME NPC CODE
// ******************
if (pSoldier->ubProfile != NO_PROFILE)
if (pSoldier->ubProfile != NO_PROFILE || pSoldier->IsAssassin() )
{
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
if ( pSoldier->ubProfile != NO_PROFILE )
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
else
{
INT32 sDesiredMercDist;
INT32 sDesiredMercLoc = ClosestUnDisguisedPC( pSoldier, &sDesiredMercDist );
// Flugente: if this guy is disguised, do not consider him
if (!TileIsOutOfBounds(sDesiredMercLoc))
{
if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 )
{
AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID );
// now wait a bit!
pSoldier->aiData.usActionData = 5000;
pSoldier->aiData.bAction = AI_ACTION_WAIT;
}
else
{
pSoldier->aiData.usActionData = GoAsFarAsPossibleTowards( pSoldier, sDesiredMercLoc, AI_ACTION_APPROACH_MERC );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
pSoldier->aiData.bAction = AI_ACTION_APPROACH_MERC;
}
}
}
}
if ( pSoldier->aiData.bAction != AI_ACTION_NONE )
{
return( pSoldier->aiData.bAction );
}
}
}
}
// determine the most important noise heard, and its relative value
+1
View File
@@ -162,6 +162,7 @@ INT8 ClosestPanicTrigger( SOLDIERTYPE * pSoldier );
INT32 ClosestKnownOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel);
INT32 ClosestPC( SOLDIERTYPE *pSoldier, INT32 * psDistance );
INT32 ClosestUnDisguisedPC( SOLDIERTYPE *pSoldier, INT32 * psDistance ); // Flugente: like ClosestPC(...), but does not account for covert or not visible mercs
BOOLEAN CanAutoBandage( BOOLEAN fDoFullCheck );
void DebugAI( STR szOutput );