AI suppression fire improvements.

CalcBestShot:
- added standard check for valid opponent
- use standard knowledge functions
- blind soldier can only attack seen/heard personally
- determine suppression fire (shooting at target nobody sees currently)
- don't shoot if target location is seen and empty
- no fire on unseen opponents with throwing knives
- only enemy team can use blind suppression fire
- only try to suppress alive and conscious human targets
- additional check to limit shooting through walls
- alt weapon holding scope mode is used only when ubAllowAlternativeWeaponHolding == 3
- hip firing allowed only for human bodytypes
- take into account direction when checking stance
- shoot heavy guns in standing stance only when using hip fire
- penalize suppression fire

Red AI suppression fire:
- check valid target
- check weapon/ammo requirements
- check that soldier is not sniper
- check friendly fire chance
- reduce chance to shoot if target is beyond weapon range
- check that we have spare ammo

Improved code to prepare suppression fire:
- change stance first of needed
- allow shooting with aiming
- reserve APs to hide if no cover or enemy is close
- added debug messages

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8878 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Sevenfm
2020-08-06 07:53:12 +00:00
parent e9107eab34
commit 93c41f2f97
4 changed files with 379 additions and 117 deletions
+78
View File
@@ -5790,3 +5790,81 @@ UINT8 SectorCurfew(BOOLEAN fNight)
return ubSectorData;
}
INT32 RandomizeLocation(INT32 sSpot, INT8 bLevel, UINT8 ubTimes, SOLDIERTYPE *pSightSoldier)
{
if (TileIsOutOfBounds(sSpot))
{
return NOWHERE;
}
UINT8 ubDirection;
UINT8 ubMovementCost;
INT32 sTempSpot;
INT32 sSpotArray[NUM_WORLD_DIRECTIONS + 1];
UINT8 ubSpots;
for (UINT8 ubCnt = 0; ubCnt < ubTimes; ubCnt++)
{
// store original location
ubSpots = 1;
sSpotArray[0] = sSpot;
// find adjacent locations
for (ubDirection = 0; ubDirection < NUM_WORLD_DIRECTIONS; ubDirection++)
{
sTempSpot = NewGridNo(sSpot, DirectionInc(ubDirection));
if (sTempSpot != sSpot)
{
ubMovementCost = gubWorldMovementCosts[sTempSpot][ubDirection][bLevel];
if (ubMovementCost < TRAVELCOST_BLOCKED &&
IsLocationSittableExcludingPeople(sTempSpot, bLevel) &&
(!pSightSoldier || SoldierToVirtualSoldierLineOfSightTest(pSightSoldier, sTempSpot, bLevel, ANIM_STAND, TRUE, NO_DISTANCE_LIMIT)))
{
sSpotArray[ubSpots] = sTempSpot;
ubSpots++;
}
}
}
// find random location
sSpot = sSpotArray[Random(ubSpots)];
// stop if could not find any adjacent spot
if (ubSpots < 2)
{
break;
}
}
return sSpot;
}
INT32 RandomizeOpponentLocation(INT32 sSpot, SOLDIERTYPE *pOpponent, INT16 sMaxDistance)
{
if (TileIsOutOfBounds(sSpot))
{
return NOWHERE;
}
INT8 bXOffset, bYOffset;
INT32 sRandomSpot;
if (sMaxDistance > 0)
{
for (INT cnt = 0; cnt < min(sMaxDistance * 2, 100); cnt++)
{
bXOffset = Random(sMaxDistance * 2 + 1) - sMaxDistance;
bYOffset = Random(sMaxDistance * 2 + 1) - sMaxDistance;
sRandomSpot = sSpot + bXOffset + (MAXCOL * bYOffset);
if (!TileIsOutOfBounds(sRandomSpot) && NewOKDestination(pOpponent, sRandomSpot, FALSE, pOpponent->pathing.bLevel))
{
return sRandomSpot;
}
}
}
return sSpot;
}