mirror of
https://github.com/1dot13/source.git
synced 2026-09-16 14:47:17 +02:00
Various AI improvements.
FindThrowableGrenade: allows to specify type and damage of searched grenade. New counter SOLDIER_COUNTER_RETREAT allows to set number of turns which soldier will try to retreat and take cover. FindBestNearbyCover: use PrepareThreatlist as unified function to make list of all known opponents. Militia Control: - start retreating mode for 2 turns when ordering retreat - replace AI_ACTION_RUN_AWAY with AI_ACTION_TAKE_COVER order so that militia do not retreat from sector New AI behavior: - soldier can use smoke grenade to cover himself when under fire - soldier can use use smoke grenade on his friend to cover him - if soldier used smoke, he starts retreat mode for 2 turns - added retreat code to Red, Black AI - improved Main Red AI for civilians (they only run away) Improved suppression code: - less chance of suppression when opponent has high shock level - prefer using suppression fire when soldier is in cover git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8879 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+76
-18
@@ -1870,48 +1870,106 @@ INT8 FindGLGrenade( SOLDIERTYPE * pSoldier )
|
||||
return( NO_SLOT );
|
||||
}
|
||||
|
||||
INT8 FindThrowableGrenade( SOLDIERTYPE * pSoldier )
|
||||
INT8 FindThrowableGrenade(SOLDIERTYPE * pSoldier, UINT8 ubGrenadeType, UINT8 ubMinDamage)
|
||||
{
|
||||
INT8 bLoop;
|
||||
BOOLEAN fCheckForFlares = FALSE;
|
||||
UINT16 usItem;
|
||||
INT8 invsize = (INT8)pSoldier->inv.size();
|
||||
UINT8 ubDamage;
|
||||
|
||||
// JA2Gold: give some priority to looking for flares when at night
|
||||
// this is AI only so we can put in some customization for night
|
||||
if (GetTimeOfDayAmbientLightLevel() == NORMAL_LIGHTLEVEL_NIGHT)
|
||||
// sevenfm: use flare only if cannot see opponent
|
||||
if (NightLight() &&
|
||||
pSoldier->aiData.bOppCnt == 0 &&
|
||||
ubGrenadeType == EXPLOSV_ANY_TYPE &&
|
||||
Chance(50))
|
||||
{
|
||||
if (pSoldier->stats.bLife > (pSoldier->stats.bLifeMax / 2))
|
||||
{
|
||||
fCheckForFlares = TRUE;
|
||||
}
|
||||
fCheckForFlares = TRUE;
|
||||
}
|
||||
|
||||
INT8 invsize = (INT8)pSoldier->inv.size();
|
||||
INT8 bFoundSlot = NO_SLOT;
|
||||
UINT8 ubType;
|
||||
UINT8 ubFoundType;
|
||||
|
||||
if (fCheckForFlares)
|
||||
for (bLoop = 0; bLoop < invsize; ++bLoop)
|
||||
{
|
||||
// Do a priority check for flares first
|
||||
for (bLoop = 0; bLoop < invsize; ++bLoop)
|
||||
if (pSoldier->inv[bLoop].exists() == true)
|
||||
{
|
||||
if (pSoldier->inv[bLoop].exists() == true) {
|
||||
if ( Item[pSoldier->inv[ bLoop ].usItem].flare )
|
||||
usItem = pSoldier->inv[bLoop].usItem;
|
||||
ubType = (UINT8)Explosive[Item[usItem].ubClassIndex].ubType;
|
||||
ubDamage = Explosive[Item[usItem].ubClassIndex].ubDamage;
|
||||
|
||||
if ((Item[usItem].usItemClass & IC_GRENADE) &&
|
||||
Item[usItem].ubCursor == TOSSCURS &&
|
||||
GetLauncherFromLaunchable(usItem) == NOTHING &&
|
||||
(!Item[usItem].flare || NightLight()) &&
|
||||
ubDamage >= ubMinDamage &&
|
||||
(ubGrenadeType == EXPLOSV_ANY_TYPE || ubType == ubGrenadeType))
|
||||
{
|
||||
// return if flare grenade has priority
|
||||
if (fCheckForFlares && Item[usItem].flare)
|
||||
{
|
||||
return( bLoop );
|
||||
return bLoop;
|
||||
}
|
||||
|
||||
// return if found needed type
|
||||
if (ubType == ubGrenadeType)
|
||||
{
|
||||
return bLoop;
|
||||
}
|
||||
|
||||
// always prefer normal type
|
||||
// smoke grenades have low priority
|
||||
// mustard gas has priority over tear gas
|
||||
if (bFoundSlot == NO_SLOT ||
|
||||
ubType == EXPLOSV_NORMAL && ubFoundType != EXPLOSV_NORMAL ||
|
||||
ubType != EXPLOSV_SMOKE && ubFoundType == EXPLOSV_SMOKE ||
|
||||
ubType == EXPLOSV_MUSTGAS && ubFoundType == EXPLOSV_TEARGAS)
|
||||
{
|
||||
bFoundSlot = bLoop;
|
||||
ubFoundType = ubType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(bFoundSlot);
|
||||
}
|
||||
|
||||
UINT8 CountThrowableGrenades(SOLDIERTYPE * pSoldier, UINT8 ubGrenadeType, UINT8 ubMinDamage)
|
||||
{
|
||||
INT8 bLoop;
|
||||
UINT16 usItem;
|
||||
INT8 invsize = (INT8)pSoldier->inv.size();
|
||||
UINT8 ubDamage;
|
||||
|
||||
INT8 bFoundSlot = NO_SLOT;
|
||||
UINT8 ubType;
|
||||
//UINT8 ubFoundType;
|
||||
UINT8 ubCnt = 0;
|
||||
|
||||
for (bLoop = 0; bLoop < invsize; ++bLoop)
|
||||
{
|
||||
if (pSoldier->inv[bLoop].exists() == true) {
|
||||
if ( (Item[ pSoldier->inv[ bLoop ].usItem ].usItemClass & IC_GRENADE) && // Try this check instead, to avoid tossing RPG rounds !GLGrenadeInSlot( pSoldier, bLoop ) &&
|
||||
GetLauncherFromLaunchable( pSoldier->inv[ bLoop ].usItem) == NOTHING )
|
||||
if (pSoldier->inv[bLoop].exists() == true)
|
||||
{
|
||||
usItem = pSoldier->inv[bLoop].usItem;
|
||||
ubType = (UINT8)Explosive[Item[usItem].ubClassIndex].ubType;
|
||||
ubDamage = Explosive[Item[usItem].ubClassIndex].ubDamage;
|
||||
|
||||
if ((Item[usItem].usItemClass & IC_GRENADE) &&
|
||||
Item[usItem].ubCursor == TOSSCURS &&
|
||||
GetLauncherFromLaunchable(usItem) == NOTHING &&
|
||||
ubDamage >= ubMinDamage &&
|
||||
(ubGrenadeType == EXPLOSV_ANY_TYPE || ubType == ubGrenadeType))
|
||||
{
|
||||
return( bLoop );
|
||||
ubCnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return( NO_SLOT );
|
||||
|
||||
return ubCnt;
|
||||
}
|
||||
|
||||
INT16 FindAttachmentSlot( OBJECTTYPE* pObj, UINT16 usItem, UINT8 subObject)
|
||||
|
||||
+19
-1
@@ -16,6 +16,23 @@ class SOLDIERTYPE;
|
||||
#define NIGHTSIGHTGOGGLES_BONUS 2 * STRAIGHT_RATIO
|
||||
#define UVGOGGLES_BONUS 4 * STRAIGHT_RATIO
|
||||
|
||||
enum
|
||||
{
|
||||
EXPLOSV_NORMAL,
|
||||
EXPLOSV_STUN,
|
||||
EXPLOSV_TEARGAS,
|
||||
EXPLOSV_MUSTGAS,
|
||||
EXPLOSV_FLARE,
|
||||
EXPLOSV_NOISE,
|
||||
EXPLOSV_SMOKE,
|
||||
EXPLOSV_CREATUREGAS,
|
||||
EXPLOSV_BURNABLEGAS,
|
||||
EXPLOSV_FLASHBANG,
|
||||
EXPLOSV_SIGNAL_SMOKE,
|
||||
EXPLOSV_SMOKE_DEBRIS,
|
||||
EXPLOSV_ANY_TYPE,
|
||||
};
|
||||
|
||||
extern UINT8 SlotToPocket[7];
|
||||
extern BOOLEAN WeaponInHand( SOLDIERTYPE * pSoldier );
|
||||
|
||||
@@ -31,7 +48,8 @@ extern INT8 FindEmptySlotWithin(SOLDIERTYPE * pSoldier, INT8 bLower, INT8 bUpper
|
||||
extern INT8 FindObjInObjRange(SOLDIERTYPE * pSoldier, UINT16 usItem1, UINT16 usItem2);
|
||||
extern INT8 FindLaunchable(SOLDIERTYPE * pSoldier, UINT16 usWeapon);
|
||||
extern INT8 FindGLGrenade(SOLDIERTYPE * pSoldier);
|
||||
extern INT8 FindThrowableGrenade(SOLDIERTYPE * pSoldier);
|
||||
extern INT8 FindThrowableGrenade(SOLDIERTYPE * pSoldier, UINT8 ubGrenadeType = EXPLOSV_ANY_TYPE, UINT8 ubMinDamaga = 0);
|
||||
extern UINT8 CountThrowableGrenades(SOLDIERTYPE * pSoldier, UINT8 ubGrenadeType = EXPLOSV_ANY_TYPE, UINT8 ubMinDamaga = 0);
|
||||
extern INT8 FindUsableObj(SOLDIERTYPE * pSoldier, UINT16 usItem);
|
||||
|
||||
void DeleteObj(OBJECTTYPE * pObj );
|
||||
|
||||
@@ -1378,6 +1378,8 @@ void MilitiaControlMenuBtnCallBack( MOUSE_REGION * pRegion, INT32 iReason )
|
||||
pTMilitiaSoldier->aiData.bAttitude = DEFENSIVE;
|
||||
pTMilitiaSoldier->usUIMovementMode = RUNNING;
|
||||
|
||||
pTMilitiaSoldier->RetreatCounterStart(2);
|
||||
|
||||
// set up next action to run away
|
||||
sActionGridNo = FindSpotMaxDistFromOpponents( pTMilitiaSoldier );
|
||||
|
||||
@@ -1385,7 +1387,10 @@ void MilitiaControlMenuBtnCallBack( MOUSE_REGION * pRegion, INT32 iReason )
|
||||
|
||||
if (!TileIsOutOfBounds(pTMilitiaSoldier->aiData.usNextActionData))
|
||||
{
|
||||
pTMilitiaSoldier->aiData.bNextAction = AI_ACTION_RUN_AWAY;
|
||||
// sevenfm: use TAKE_COVER order to stop soldier from retreating
|
||||
pTMilitiaSoldier->aiData.bNextAction = AI_ACTION_TAKE_COVER;
|
||||
//pTMilitiaSoldier->aiData.bNextAction = AI_ACTION_RUN_AWAY;
|
||||
|
||||
pTMilitiaSoldier->aiData.usActionData = ANIM_STAND;
|
||||
|
||||
// SEND PENDING ACTION
|
||||
@@ -1635,14 +1640,7 @@ void MilitiaControlMenuBtnCallBack( MOUSE_REGION * pRegion, INT32 iReason )
|
||||
pTeamSoldier->aiData.bAttitude = DEFENSIVE;
|
||||
pTeamSoldier->usUIMovementMode = RUNNING;
|
||||
|
||||
//// set up next action to run away
|
||||
//pTeamSoldier->usNextActionData = FindSpotMaxDistFromOpponents( pTeamSoldier );
|
||||
|
||||
//if ( !TileIsOutOfBounds(pTeamSoldier->usNextActionData) )
|
||||
//{
|
||||
// pTeamSoldier->bNextAction = AI_ACTION_RUN_AWAY;
|
||||
// pTeamSoldier->usActionData = ANIM_STAND;
|
||||
//}
|
||||
pTeamSoldier->RetreatCounterStart(2);
|
||||
|
||||
// set up next action to run away
|
||||
sActionGridNo = FindSpotMaxDistFromOpponents( pTeamSoldier );
|
||||
@@ -1651,7 +1649,10 @@ void MilitiaControlMenuBtnCallBack( MOUSE_REGION * pRegion, INT32 iReason )
|
||||
|
||||
if ( !TileIsOutOfBounds(pTeamSoldier->aiData.usNextActionData) )
|
||||
{
|
||||
pTeamSoldier->aiData.bNextAction = AI_ACTION_RUN_AWAY;
|
||||
// sevenfm: use TAKE_COVER order to stop soldier from retreating
|
||||
//pTeamSoldier->aiData.bNextAction = AI_ACTION_RUN_AWAY;
|
||||
pTeamSoldier->aiData.bNextAction = AI_ACTION_TAKE_COVER;
|
||||
|
||||
pTeamSoldier->aiData.usActionData = ANIM_STAND;
|
||||
|
||||
// SEND PENDING ACTION
|
||||
|
||||
@@ -25864,3 +25864,42 @@ BOOLEAN SOLDIERTYPE::IsFlanking(void)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT8 SOLDIERTYPE::ShockLevelPercent(void)
|
||||
{
|
||||
if (gGameExternalOptions.ubMaxSuppressionShock == 0)
|
||||
return 0;
|
||||
|
||||
return min(100, 100 * this->aiData.bShock / gGameExternalOptions.ubMaxSuppressionShock);
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::TakenLargeHit(void)
|
||||
{
|
||||
if (this->usSoldierFlagMask2 & SOLDIER_TAKEN_LARGE_HIT)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::IsCowering(void)
|
||||
{
|
||||
if (this->usAnimState == COWERING || this->usAnimState == COWERING_PRONE)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::RetreatCounterStart(UINT16 usValue)
|
||||
{
|
||||
usSkillCounter[SOLDIER_COUNTER_RETREAT] = max(usValue, usSkillCounter[SOLDIER_COUNTER_RETREAT]);
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::RetreatCounterStop(void)
|
||||
{
|
||||
usSkillCounter[SOLDIER_COUNTER_RETREAT] = 0;
|
||||
}
|
||||
|
||||
UINT16 SOLDIERTYPE::RetreatCounterValue(void)
|
||||
{
|
||||
return usSkillCounter[SOLDIER_COUNTER_RETREAT];
|
||||
}
|
||||
|
||||
@@ -631,6 +631,7 @@ enum {
|
||||
SOLDIER_COUNTER_RADIO_ARTILLERY, // there is actually no need for an artillery timer, but we use one to forbid the same AI guy ordering multiple strikes at once
|
||||
SOLDIER_COUNTER_SPOTTER, // used to determine wether we are a spotter
|
||||
SOLDIER_COUNTER_ROLE_OBSERVED, // every turn that the player observes an enemy, the enemies counter is increased. If it is high enough, we know his role
|
||||
SOLDIER_COUNTER_RETREAT, // use to retreat from position
|
||||
|
||||
SOLDIER_COUNTER_MAX = 20, // enough space for fillers
|
||||
};
|
||||
@@ -1862,6 +1863,14 @@ public:
|
||||
|
||||
// sevenfm: service functions
|
||||
BOOLEAN IsFlanking(void);
|
||||
BOOLEAN CheckInitialAP(void);
|
||||
UINT8 ShockLevelPercent(void);
|
||||
BOOLEAN TakenLargeHit(void);
|
||||
BOOLEAN IsCowering(void);
|
||||
|
||||
void RetreatCounterStart(UINT16 usValue);
|
||||
void RetreatCounterStop(void);
|
||||
UINT16 RetreatCounterValue(void);
|
||||
|
||||
// Flugente: prisoner system
|
||||
BOOLEAN CanProcessPrisoners();
|
||||
@@ -1875,9 +1884,6 @@ public:
|
||||
// Flugente: are we an assassin?
|
||||
BOOLEAN IsAssassin();
|
||||
|
||||
// sevenfm: service functions
|
||||
BOOLEAN CheckInitialAP(void);
|
||||
|
||||
// Flugente: multi-turn actions
|
||||
UINT8 GetMultiTurnAction();
|
||||
void StartMultiTurnAction( UINT8 usActionType, INT32 asGridNo );
|
||||
|
||||
@@ -4734,7 +4734,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea
|
||||
UINT8 ubCounterattackChance = EffectiveDexterity(pTargetSoldier, FALSE) * (100 + pTargetSoldier->bBreath) / 200;
|
||||
|
||||
// halve chance for counterattack if boxer was hit recently
|
||||
if (pTargetSoldier->usSoldierFlagMask2 & SOLDIER_TAKEN_LARGE_HIT)
|
||||
if (pTargetSoldier->TakenLargeHit())
|
||||
ubCounterattackChance /= 2;
|
||||
|
||||
// sevenfm: possibly counterattack when boxing
|
||||
|
||||
@@ -265,22 +265,6 @@ typedef struct
|
||||
CHAR8 shotAnimation[MAX_ANIMATION_FILENAME_LEN];
|
||||
} AMMOTYPE;
|
||||
|
||||
enum
|
||||
{
|
||||
EXPLOSV_NORMAL,
|
||||
EXPLOSV_STUN,
|
||||
EXPLOSV_TEARGAS,
|
||||
EXPLOSV_MUSTGAS,
|
||||
EXPLOSV_FLARE,
|
||||
EXPLOSV_NOISE,
|
||||
EXPLOSV_SMOKE,
|
||||
EXPLOSV_CREATUREGAS,
|
||||
EXPLOSV_BURNABLEGAS,
|
||||
EXPLOSV_FLASHBANG,
|
||||
EXPLOSV_SIGNAL_SMOKE,
|
||||
EXPLOSV_SMOKE_DEBRIS,
|
||||
};
|
||||
|
||||
#define AMMO_DAMAGE_ADJUSTMENT_BUCKSHOT( x ) (x / 4)
|
||||
#define NUM_BUCKSHOT_PELLETS 9
|
||||
|
||||
|
||||
Reference in New Issue
Block a user