mirror of
https://github.com/1dot13/source.git
synced 2026-08-12 14:10:23 +02:00
CalcBestThrow:
- for mortars and grenade launchers, first try to find non smoke grenade/shell - don't use mortar in building or underground - don't use grenade launcher underground - blinded soldier cannot use mortar/grenade launcher - when calculating safety margin, correctly use BuddyItem defined for single shot RPG - limit ubSafetyMargin to TACTICAL_RANGE / 2 in case radius set too high in XML - use flares only at night - use ValidOpponent() check to determine opponent - use new knowledge functions - allow attacking recently seen/heard opponents with mortar/grenade launcher - improved code to spare grenade, don't spare: non lethal grenades, if some friends killed, when under attack, STATIONART/SNIPER, when on the roof, when there are friends under attack nearby - increase possible distance from opponent when opponent in a building or when using gas grenade - improved check for gas/smoke when using gas/smoke grenade - don't use smoke grenade if there's already smoke nearby (it can spread to this tile later) - improved code for AP to attack calculation - when attacking enemy in a building with mortar, allow shooting on the roof above the enemy, hoping that roof will collapse - limit RPG use, unless can hit several enemies, shooting at tank or opponent is in a room - soldiers should use RPGs against tanks/jeeps more often - modify smoke attack value depending on range (less effective if too far from opponent) Red AI: - improved code to prepare throw attack - added code to change stance before throwing if needed Black AI: - simplified code to change stance before shooting, always change stance first if needed - improved code to prepare attack, added code to change stance before throwing if needed CalcBestShot: - always change stance first, then turn - don't allow going prone and turning at the same time New AI functions: - NightLight - DuskLight - InSmokeNearby - CountTeamUnderAttack - SectorCurfew - TeamPercentKilled - TeamHighPercentKilled - ArmyPercentKilled - ArmyPercentKilledTolerance - Knowledge - KnownLocation - KnownLevel - UsePersonalKnowledge - PersonalKnowledge - KnownPersonalLocation - KnownPersonalLevel - PublicKnowledge - KnownPublicLocation - KnownPublicLevel git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8791 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+277
-1
@@ -45,7 +45,9 @@
|
||||
// InWaterOrGas - gas stuff
|
||||
// RoamingRange - point patrol stuff
|
||||
|
||||
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOLEAN fHipStance );
|
||||
// sevenfm
|
||||
extern UINT16 PickSoldierReadyAnimation(SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOLEAN fHipStance);
|
||||
extern SECTOR_EXT_DATA SectorExternalData[256][4];
|
||||
|
||||
UINT8 Urgency[NUM_STATUS_STATES][NUM_MORALE_STATES] =
|
||||
{
|
||||
@@ -4067,6 +4069,34 @@ UINT8 CountFriendsBlack( SOLDIERTYPE *pSoldier, INT32 sClosestOpponent )
|
||||
return ubFriendCount;
|
||||
}
|
||||
|
||||
// count friends under fire or with shock
|
||||
UINT8 CountTeamUnderAttack(INT8 bTeam, INT32 sGridNo, INT16 sDistance)
|
||||
{
|
||||
SOLDIERTYPE * pFriend;
|
||||
UINT8 ubFriendCount = 0;
|
||||
|
||||
// safety check
|
||||
if (bTeam >= MAXTEAMS)
|
||||
return 0;
|
||||
|
||||
// Run through each friendly.
|
||||
for (UINT8 iCounter = gTacticalStatus.Team[bTeam].bFirstID; iCounter <= gTacticalStatus.Team[bTeam].bLastID; iCounter++)
|
||||
{
|
||||
pFriend = MercPtrs[iCounter];
|
||||
|
||||
if (pFriend &&
|
||||
pFriend->bActive &&
|
||||
pFriend->stats.bLife >= OKLIFE &&
|
||||
PythSpacesAway(sGridNo, pFriend->sGridNo) <= sDistance &&
|
||||
(pFriend->aiData.bUnderFire || pFriend->aiData.bShock > 0))
|
||||
{
|
||||
ubFriendCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return ubFriendCount;
|
||||
}
|
||||
|
||||
// check if we have a prone sight cover from known enemies at spot
|
||||
BOOLEAN ProneSightCoverAtSpot(SOLDIERTYPE *pSoldier, INT32 sSpot, BOOLEAN fUnlimited)
|
||||
{
|
||||
@@ -5310,6 +5340,41 @@ BOOLEAN InSmoke(INT32 sGridNo, INT8 bLevel)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN InSmokeNearby(INT32 sGridNo, INT8 bLevel)
|
||||
{
|
||||
if (TileIsOutOfBounds(sGridNo))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gpWorldLevelData[sGridNo].ubExtFlags[bLevel] & (MAPELEMENT_EXT_SMOKE))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT8 ubDirection;
|
||||
INT32 sTempGridNo;
|
||||
UINT8 ubMovementCost;
|
||||
|
||||
// check adjacent reachable tiles
|
||||
for (ubDirection = 0; ubDirection < NUM_WORLD_DIRECTIONS; ubDirection++)
|
||||
{
|
||||
sTempGridNo = NewGridNo(sGridNo, DirectionInc(ubDirection));
|
||||
|
||||
if (sTempGridNo != sGridNo)
|
||||
{
|
||||
ubMovementCost = gubWorldMovementCosts[sTempGridNo][ubDirection][bLevel];
|
||||
|
||||
if (ubMovementCost < TRAVELCOST_BLOCKED &&
|
||||
gpWorldLevelData[sTempGridNo].ubExtFlags[bLevel] & (MAPELEMENT_EXT_SMOKE))
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN CorpseWarning(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel)
|
||||
{
|
||||
CHECKF(pSoldier);
|
||||
@@ -5505,3 +5570,214 @@ BOOLEAN AICheckShortWeaponRange(SOLDIERTYPE *pSoldier)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN NightLight(void)
|
||||
{
|
||||
//if( GetTimeOfDayAmbientLightLevel() >= NORMAL_LIGHTLEVEL_DAY + 2 )
|
||||
if (gubEnvLightValue >= NORMAL_LIGHTLEVEL_NIGHT - 3)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN DuskLight(void)
|
||||
{
|
||||
// average between day and night
|
||||
if (gubEnvLightValue >= (NORMAL_LIGHTLEVEL_NIGHT + NORMAL_LIGHTLEVEL_DAY) / 2)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN UsePersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
|
||||
{
|
||||
INT8 bPersonalKnowledge;
|
||||
INT8 bPublicKnowledge;
|
||||
|
||||
if (!pSoldier || ubOpponentID == NOBODY)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bPersonalKnowledge = PersonalKnowledge(pSoldier, ubOpponentID);
|
||||
bPublicKnowledge = PublicKnowledge(pSoldier->bTeam, ubOpponentID);
|
||||
|
||||
if (gubKnowledgeValue[bPublicKnowledge - OLDEST_HEARD_VALUE][bPersonalKnowledge - OLDEST_HEARD_VALUE] > 0 ||
|
||||
bPersonalKnowledge != NOT_HEARD_OR_SEEN &&
|
||||
TileIsOutOfBounds(KnownPublicLocation(pSoldier->bTeam, ubOpponentID)) &&
|
||||
!TileIsOutOfBounds(KnownPersonalLocation(pSoldier, ubOpponentID)))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INT8 Knowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
|
||||
{
|
||||
if (!pSoldier || ubOpponentID == NOBODY)
|
||||
{
|
||||
return NOT_HEARD_OR_SEEN;
|
||||
}
|
||||
|
||||
if (UsePersonalKnowledge(pSoldier, ubOpponentID))
|
||||
{
|
||||
return PersonalKnowledge(pSoldier, ubOpponentID);
|
||||
}
|
||||
|
||||
return PublicKnowledge(pSoldier->bTeam, ubOpponentID);
|
||||
}
|
||||
|
||||
INT32 KnownLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
|
||||
{
|
||||
if (!pSoldier || ubOpponentID == NOBODY)
|
||||
{
|
||||
return NOWHERE;
|
||||
}
|
||||
|
||||
if (UsePersonalKnowledge(pSoldier, ubOpponentID))
|
||||
{
|
||||
return KnownPersonalLocation(pSoldier, ubOpponentID);
|
||||
}
|
||||
|
||||
return KnownPublicLocation(pSoldier->bTeam, ubOpponentID);
|
||||
}
|
||||
|
||||
INT8 KnownLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
|
||||
{
|
||||
if (!pSoldier || ubOpponentID == NOBODY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (UsePersonalKnowledge(pSoldier, ubOpponentID))
|
||||
{
|
||||
return KnownPersonalLevel(pSoldier, ubOpponentID);
|
||||
}
|
||||
|
||||
return KnownPublicLevel(pSoldier->bTeam, ubOpponentID);
|
||||
}
|
||||
|
||||
INT8 PersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
|
||||
{
|
||||
if (!pSoldier || ubOpponentID == NOBODY)
|
||||
{
|
||||
return NOT_HEARD_OR_SEEN;
|
||||
}
|
||||
|
||||
return pSoldier->aiData.bOppList[ubOpponentID];
|
||||
}
|
||||
|
||||
INT32 KnownPersonalLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
|
||||
{
|
||||
if (!pSoldier || ubOpponentID == NOBODY)
|
||||
{
|
||||
return NOWHERE;
|
||||
}
|
||||
/*if(PersonalKnowledge(pSoldier, ubOpponentID) == NOT_HEARD_OR_SEEN)
|
||||
{
|
||||
return NOWHERE;
|
||||
}*/
|
||||
|
||||
return gsLastKnownOppLoc[pSoldier->ubID][ubOpponentID];
|
||||
}
|
||||
|
||||
INT8 KnownPersonalLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
|
||||
{
|
||||
if (!pSoldier || ubOpponentID == NOBODY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gbLastKnownOppLevel[pSoldier->ubID][ubOpponentID];
|
||||
}
|
||||
|
||||
INT8 PublicKnowledge(UINT8 bTeam, UINT8 ubOpponentID)
|
||||
{
|
||||
if (bTeam >= MAXTEAMS || ubOpponentID == NOBODY)
|
||||
{
|
||||
return NOT_HEARD_OR_SEEN;
|
||||
}
|
||||
|
||||
return gbPublicOpplist[bTeam][ubOpponentID];
|
||||
}
|
||||
|
||||
INT32 KnownPublicLocation(UINT8 bTeam, UINT8 ubOpponentID)
|
||||
{
|
||||
if (bTeam >= MAXTEAMS || ubOpponentID == NOBODY)
|
||||
{
|
||||
return NOWHERE;
|
||||
}
|
||||
/*if (PublicKnowledge(bTeam, ubOpponentID) == NOT_HEARD_OR_SEEN)
|
||||
{
|
||||
return NOWHERE;
|
||||
}*/
|
||||
|
||||
return gsPublicLastKnownOppLoc[bTeam][ubOpponentID];
|
||||
}
|
||||
|
||||
INT8 KnownPublicLevel(UINT8 bTeam, UINT8 ubOpponentID)
|
||||
{
|
||||
if (bTeam >= MAXTEAMS || ubOpponentID == NOBODY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gbPublicLastKnownOppLevel[bTeam][ubOpponentID];
|
||||
}
|
||||
|
||||
UINT8 ArmyPercentKilled(void)
|
||||
{
|
||||
if (gTacticalStatus.Team[ENEMY_TEAM].bMenInSector + gTacticalStatus.ubArmyGuysKilled == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 100 * gTacticalStatus.ubArmyGuysKilled / (gTacticalStatus.Team[ENEMY_TEAM].bMenInSector + gTacticalStatus.ubArmyGuysKilled);
|
||||
}
|
||||
|
||||
UINT8 TeamPercentKilled(INT8 bTeam)
|
||||
{
|
||||
if (bTeam == ENEMY_TEAM)
|
||||
{
|
||||
return ArmyPercentKilled();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOLEAN TeamHighPercentKilled(INT8 bTeam)
|
||||
{
|
||||
if (bTeam == ENEMY_TEAM && ArmyPercentKilled() > ArmyPercentKilledTolerance())
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// decide how many soldiers can be killed before alarm will be raised
|
||||
UINT8 ArmyPercentKilledTolerance(void)
|
||||
{
|
||||
// 50% at day, 25% at night, 25-33% for restricted sectors
|
||||
return 100 / (2 + SectorCurfew(TRUE));
|
||||
}
|
||||
|
||||
UINT8 SectorCurfew(BOOLEAN fNight)
|
||||
{
|
||||
UINT8 ubSectorId = SECTOR(gWorldSectorX, gWorldSectorY);
|
||||
UINT8 ubSectorData = 0;
|
||||
|
||||
ubSectorData = SectorExternalData[ubSectorId][gbWorldSectorZ].usCurfewValue;
|
||||
|
||||
if (fNight && NightLight()) // suspicious at night
|
||||
ubSectorData = max(ubSectorData, 1);
|
||||
|
||||
if (gbWorldSectorZ > 0) // underground we are always suspicious
|
||||
ubSectorData = max(ubSectorData, 2);
|
||||
|
||||
return ubSectorData;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user