mirror of
https://github.com/1dot13/source.git
synced 2026-08-26 14:30:26 +02:00
New feature: radio operator trait allows calling in artillery, requesting reinforcements, scanning for enemies and a few other skills.
Also includes mechansim for easy implementation of new skills. For more info see http://www.bears-pit.com/board/ubbthreads.php/topics/327348.html#Post327348 Requires GameDir >= r1848. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6547 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -298,3 +298,24 @@ FLOAT AICalcRecoilForShot( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon, UINT8 ubS
|
||||
|
||||
// HEADROCK HAM 4: Calculate average recoil offset for a shot.
|
||||
FLOAT AICalcRecoilForShot( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon, UINT8 ubShotNum);
|
||||
|
||||
// Flugente AI functions
|
||||
typedef BOOLEAN (*SOLDIER_CONDITION)( SOLDIERTYPE *pSoldier );
|
||||
|
||||
// determine a gridno that would allow us to hit as many enemies as possible given an effect with radius aRadius tiles
|
||||
// return true if sufficent gridno is found
|
||||
// pGridNo will be the GridNo
|
||||
// aRadius is the area effect radius to use
|
||||
// uCheckFriends: 0 - do not consider friends at all 1 - consider with negative weight else: ignore any location that might also hit friends
|
||||
// sucess only if at a rating of at least aMinRating can be achieved
|
||||
// any enemy soldiers not fulfilling cond will be excluded from this calculation
|
||||
// if an enemy soldier fulfils taboo, make sure to not hit him at all!
|
||||
BOOLEAN GetBestAoEGridNo(SOLDIERTYPE *pSoldier, INT32* pGridNo, INT16 aRadius, UINT8 uCheckFriends, UINT8 aMinRating, SOLDIER_CONDITION cond, SOLDIER_CONDITION taboo);
|
||||
|
||||
// Get the ID of the farthest opponent we can see, with an optional minimum range
|
||||
// puID - ID of the farthest opponent pSoldier can see
|
||||
// sRange - only return true and give an idea if opponent found is further away than this
|
||||
BOOLEAN GetFarthestOpponent(SOLDIERTYPE *pSoldier, UINT8* puID, INT16 sRange);
|
||||
|
||||
// are there more allies than friends in adjacent sectors?
|
||||
BOOLEAN MoreFriendsThanEnemiesinNearbysectors(UINT8 ausTeam, INT16 aX, INT16 aY, INT8 aZ);
|
||||
@@ -2286,6 +2286,15 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
break;
|
||||
|
||||
case AI_ACTION_USE_SKILL:
|
||||
{
|
||||
UINT8 ubID = WhoIsThere2( pSoldier->aiData.usActionData, 0 );
|
||||
|
||||
pSoldier->UseSkill(pSoldier->usAISkillUse, pSoldier->aiData.usActionData, ubID);
|
||||
ActionDone( pSoldier );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef BETAVERSION
|
||||
NumMessage("ExecuteAction - Illegal action type = ",pSoldier->aiData.bAction);
|
||||
@@ -2365,6 +2374,10 @@ void ATTACKTYPE::InitAttackType(ATTACKTYPE *pAttack)//dnl ch69 140913
|
||||
|
||||
void HandleInitialRedAlert( INT8 bTeam, UINT8 ubCommunicate)
|
||||
{
|
||||
// Flugente radio operator: if the sector is jammed, no radio communication possible
|
||||
if ( SectorJammed() )
|
||||
return;
|
||||
|
||||
/*
|
||||
if (ubCommunicate)
|
||||
{
|
||||
|
||||
@@ -589,6 +589,10 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier)
|
||||
bMinPointsNeeded = APBPConstants[AP_HANDCUFF];
|
||||
break;
|
||||
|
||||
case AI_ACTION_USE_SKILL:
|
||||
bMinPointsNeeded = 10; // TODO
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef BETAVERSION
|
||||
//NumMessage("AffordableAction - Illegal action type = ",pSoldier->aiData.bAction);
|
||||
@@ -1909,9 +1913,8 @@ BOOLEAN InWaterGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo )
|
||||
|
||||
BOOLEAN InGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo )
|
||||
{
|
||||
|
||||
// smoke
|
||||
if (gpWorldLevelData[sGridNo].ubExtFlags[ pSoldier->pathing.bLevel ] & MAPELEMENT_EXT_SMOKE)
|
||||
if (gpWorldLevelData[sGridNo].ubExtFlags[ pSoldier->pathing.bLevel ] & (MAPELEMENT_EXT_SMOKE|MAPELEMENT_EXT_SIGNAL_SMOKE) )
|
||||
return TRUE;
|
||||
|
||||
return InGas(pSoldier,sGridNo);
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#include "message.h"
|
||||
#include "Vehicles.h"
|
||||
#include "Soldier Functions.h"//dnl ch69 140913
|
||||
#include "Reinforcement.h" // added by Flugente
|
||||
#include "Town Militia.h" // added by Flugente
|
||||
#include "Queen Command.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
extern INT16 DirIncrementer[8];
|
||||
@@ -3191,3 +3194,284 @@ UINT8 UnderFire::Chance(INT8 bTeam)
|
||||
}
|
||||
return(cth);
|
||||
}
|
||||
|
||||
// Flugente AI functions
|
||||
// determine a gridno that would allow us to hit as many enemies as possible given an effect with radius aRadius tiles
|
||||
// return true if sufficent gridno is found
|
||||
// pGridNo will be the GridNo
|
||||
// aRadius is the area effect radius to use
|
||||
// uCheckFriends: 0 - do not consider friends at all 1 - consider with negative weight else: ignore any location that might also hit friends
|
||||
// sucess only if at a rating of at least aMinRating can be achieved
|
||||
// any enemy soldiers not fulfilling cond will be excluded from this calculation
|
||||
// if an enemy soldier fulfils taboo, make sure to not hit him at all!
|
||||
BOOLEAN GetBestAoEGridNo(SOLDIERTYPE *pSoldier, INT32* pGridNo, INT16 aRadius, UINT8 uCheckFriends, UINT8 aMinRating, SOLDIER_CONDITION cond, SOLDIER_CONDITION taboo)
|
||||
{
|
||||
UINT8 ubLoop, ubLoop2;
|
||||
INT32 sGridNo, sFriendTile[MAXMERCS], sOpponentTile[MAXMERCS], sTabooTile[MAXMERCS];
|
||||
UINT8 ubFriendCnt = 0,ubOpponentCnt = 0, ubTabooCnt = 0, ubOpponentID[MAXMERCS];
|
||||
INT32 bMaxLeft,bMaxRight,bMaxUp,bMaxDown, i, j;
|
||||
INT8 bPersOL, bPublOL;
|
||||
SOLDIERTYPE *pFriend;
|
||||
static INT16 sExcludeTile[100]; // This array is for storing tiles that we have
|
||||
UINT8 ubNumExcludedTiles = 0; // already considered, to prevent duplication of effort
|
||||
|
||||
INT32 lowestX = 999999;
|
||||
INT32 highestX = 0;
|
||||
INT32 lowestY = 999999;
|
||||
INT32 highestY = 0;
|
||||
|
||||
// make lists of enemies and friends
|
||||
for (ubLoop = 0; ubLoop < guiNumMercSlots; ++ubLoop)
|
||||
{
|
||||
pFriend = MercSlots[ubLoop];
|
||||
|
||||
if ( !pFriend || !pFriend->bActive || !pFriend->bInSector )
|
||||
continue;
|
||||
|
||||
if (pFriend->stats.bLife == 0)
|
||||
continue;
|
||||
|
||||
// dying or captured friends are 'helpless' anyway, we are willing to sacrifice them :-)
|
||||
if ( uCheckFriends && pSoldier->bSide == pFriend->bSide && pFriend->stats.bLife > OKLIFE && !(pFriend->bSoldierFlagMask & SOLDIER_POW) )
|
||||
{
|
||||
// active friend, remember where he is so that we DON'T blow him up!
|
||||
// this includes US, since we don't want to blow OURSELVES up either
|
||||
sFriendTile[ubFriendCnt] = pFriend->sGridNo;
|
||||
ubFriendCnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if an enemy fulfills taboo, we will remember his tile and be careful not to ever hit it!
|
||||
if ( taboo(pFriend) )
|
||||
{
|
||||
sTabooTile[ubTabooCnt] = pFriend->sGridNo;
|
||||
++ubTabooCnt;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special stuff for Carmen the bounty hunter
|
||||
if (pSoldier->aiData.bAttitude == ATTACKSLAYONLY && pFriend->ubProfile != 64)
|
||||
continue;
|
||||
|
||||
// check wether this guy fulfills the target condition
|
||||
if ( !cond(pFriend) )
|
||||
continue;
|
||||
|
||||
bPersOL = pSoldier->aiData.bOppList[pFriend->ubID];
|
||||
bPublOL = gbPublicOpplist[pSoldier->bTeam][pFriend->ubID];
|
||||
|
||||
if ( bPersOL == SEEN_CURRENTLY || bPublOL == SEEN_CURRENTLY )
|
||||
{
|
||||
// active KNOWN opponent, remember where he is so that we DO blow him up!
|
||||
sOpponentTile[ubOpponentCnt] = pFriend->sGridNo;
|
||||
}
|
||||
else if ( bPersOL == SEEN_LAST_TURN || bPersOL == HEARD_LAST_TURN )
|
||||
{
|
||||
// cheat; only allow throw if person is REALLY within 2 tiles of where last seen
|
||||
if ( SpacesAway( pFriend->sGridNo, gsLastKnownOppLoc[ pSoldier->ubID ][ pFriend->ubID ] ) < 3 )
|
||||
{
|
||||
sOpponentTile[ubOpponentCnt] = gsLastKnownOppLoc[ pSoldier->ubID ][ pFriend->ubID ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// also remember who he is (which soldier #)
|
||||
ubOpponentID[ubOpponentCnt] = pFriend->ubID;
|
||||
|
||||
// update lowest and highest x and y values
|
||||
lowestX = min(lowestX, sOpponentTile[ubOpponentCnt] % MAXCOL );
|
||||
highestX = max(highestX, sOpponentTile[ubOpponentCnt] % MAXCOL );
|
||||
lowestY = min(lowestY, sOpponentTile[ubOpponentCnt] / MAXCOL );
|
||||
highestY = max(highestY, sOpponentTile[ubOpponentCnt] / MAXCOL );
|
||||
|
||||
ubOpponentCnt++;
|
||||
}
|
||||
}
|
||||
|
||||
// no/not enough enemies found -> no area effect location advisable
|
||||
if ( !ubOpponentCnt || ubOpponentCnt < aMinRating )
|
||||
return FALSE;
|
||||
|
||||
BOOLEAN fGridNoFound = FALSE;
|
||||
INT32 bestGridNo = -1;
|
||||
INT8 bestGridNoCnt = aMinRating;
|
||||
|
||||
INT32 currentSoldierGridNo = -1;
|
||||
|
||||
INT8 enemiesnear = 0;
|
||||
INT8 friendsnear = 0;
|
||||
|
||||
// look at the squares near each known opponent and try to find the one
|
||||
// place where a tossed projectile would do the most harm to the opponents
|
||||
// while avoiding one's friends
|
||||
for (ubLoop = 0; ubLoop < ubOpponentCnt; ++ubLoop)
|
||||
{
|
||||
currentSoldierGridNo = sOpponentTile[ubLoop];
|
||||
|
||||
// determine maximum horizontal limits
|
||||
bMaxLeft = max(currentSoldierGridNo % MAXCOL - aRadius, lowestX);
|
||||
bMaxRight = min(currentSoldierGridNo % MAXCOL + aRadius, highestX);
|
||||
|
||||
// determine maximum vertical limits
|
||||
bMaxDown = max(currentSoldierGridNo / MAXCOL - aRadius, lowestY);
|
||||
bMaxUp = min(currentSoldierGridNo / MAXCOL + aRadius, highestY);
|
||||
|
||||
// evaluate every tile for its opponent-damaging potential
|
||||
for (i = bMaxLeft; i <= bMaxRight; ++i)
|
||||
{
|
||||
for (j = bMaxDown; j <= bMaxUp; ++j)
|
||||
{
|
||||
// calculate the next potential gridno near this opponent
|
||||
sGridNo = i + (MAXCOL * j);
|
||||
|
||||
// this shouldn't ever happen
|
||||
if ((sGridNo < 0) || (sGridNo >= GRIDSIZE))
|
||||
continue;
|
||||
|
||||
if ( PythSpacesAway( currentSoldierGridNo, sGridNo ) > aRadius )
|
||||
continue;
|
||||
|
||||
// if this tile is taboo, don't even think about targetting it!
|
||||
for (ubLoop2 = 0; ubLoop2 < ubTabooCnt; ++ubLoop2)
|
||||
{
|
||||
if (sTabooTile[ubLoop2] == sGridNo)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to see if we have considered this tile before:
|
||||
for (ubLoop2 = 0; ubLoop2 < ubNumExcludedTiles; ++ubLoop2)
|
||||
{
|
||||
if (sExcludeTile[ubLoop2] == sGridNo)
|
||||
continue;
|
||||
}
|
||||
|
||||
// add this tile to the list of alreay checked tiles
|
||||
if ( ubNumExcludedTiles < 100 )
|
||||
{
|
||||
sExcludeTile[ubNumExcludedTiles] = sGridNo;
|
||||
++ubNumExcludedTiles;
|
||||
}
|
||||
|
||||
// loop over all enemies and friends to determine how many are in range
|
||||
enemiesnear = 0;
|
||||
friendsnear = 0;
|
||||
|
||||
// check whether there are any friends near this gridno
|
||||
for (ubLoop2 = 0; ubLoop2 < ubFriendCnt; ++ubLoop2)
|
||||
{
|
||||
if ( PythSpacesAway(sFriendTile[ubLoop2], sGridNo) <= aRadius )
|
||||
++friendsnear;
|
||||
}
|
||||
|
||||
// ignore this location if friends are found and we want to absolutely ignore friendly fire
|
||||
if ( friendsnear && uCheckFriends > 1 )
|
||||
continue;
|
||||
|
||||
// check whether there are any enemies near this gridno
|
||||
for (ubLoop2 = 0; ubLoop2 < ubOpponentCnt; ++ubLoop2)
|
||||
{
|
||||
if ( PythSpacesAway(sOpponentTile[ubLoop2], sGridNo) <= aRadius )
|
||||
{
|
||||
++enemiesnear;
|
||||
}
|
||||
}
|
||||
|
||||
if ( enemiesnear - friendsnear >= bestGridNoCnt )
|
||||
{
|
||||
bestGridNoCnt = enemiesnear - friendsnear;
|
||||
|
||||
bestGridNo = sGridNo;
|
||||
fGridNoFound = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*pGridNo = bestGridNo;
|
||||
|
||||
return fGridNoFound;
|
||||
}
|
||||
|
||||
// Get the ID of the farthest opponent we can see, with an optional minimum range
|
||||
// puID - ID of the farthest opponent pSoldier can see
|
||||
// sRange - only return an true and give an idea if opponent found is further away than this
|
||||
BOOLEAN GetFarthestOpponent(SOLDIERTYPE *pSoldier, UINT8* puID, INT16 sRange)
|
||||
{
|
||||
INT32 sGridNo;
|
||||
UINT32 uiLoop;
|
||||
INT32 iRange = 0;;
|
||||
INT8 *pbPersOL;
|
||||
SOLDIERTYPE * pOpp;
|
||||
BOOLEAN found = FALSE;
|
||||
|
||||
*puID = NOBODY;
|
||||
|
||||
// look through this man's personal & public opplists for opponents known
|
||||
for (uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop)
|
||||
{
|
||||
pOpp = MercSlots[ uiLoop ];
|
||||
|
||||
// if this merc is inactive, at base, on assignment, or dead
|
||||
if (!pOpp)
|
||||
{
|
||||
continue; // next merc
|
||||
}
|
||||
|
||||
// if this merc is neutral/on same side, he's not an opponent
|
||||
if ( CONSIDERED_NEUTRAL( pSoldier, pOpp ) || (pSoldier->bSide == pOpp->bSide))
|
||||
{
|
||||
continue; // next merc
|
||||
}
|
||||
|
||||
// Special stuff for Carmen the bounty hunter
|
||||
if (pSoldier->aiData.bAttitude == ATTACKSLAYONLY && pOpp->ubProfile != 64)
|
||||
{
|
||||
continue; // next opponent
|
||||
}
|
||||
|
||||
pbPersOL = pSoldier->aiData.bOppList + pOpp->ubID;
|
||||
|
||||
// if this opponent is not seen personally
|
||||
if (*pbPersOL != SEEN_CURRENTLY)
|
||||
{
|
||||
continue; // next merc
|
||||
}
|
||||
|
||||
// since we're dealing with seen people, use exact gridnos
|
||||
sGridNo = pOpp->sGridNo;
|
||||
|
||||
// if we are standing at that gridno(!, obviously our info is old...)
|
||||
if (sGridNo == pSoldier->sGridNo)
|
||||
{
|
||||
continue; // next merc
|
||||
}
|
||||
|
||||
// I hope this will be good enough; otherwise we need a fractional/world-units-based 2D distance function
|
||||
//sRange = PythSpacesAway( pSoldier->sGridNo, sGridNo);
|
||||
iRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo );
|
||||
|
||||
if (iRange > sRange)
|
||||
{
|
||||
sRange = iRange;
|
||||
*puID = uiLoop;
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return( found );
|
||||
}
|
||||
|
||||
// are there more allies than friends in adjacent sectors?
|
||||
BOOLEAN MoreFriendsThanEnemiesinNearbysectors(UINT8 ausTeam, INT16 aX, INT16 aY, INT8 aZ)
|
||||
{
|
||||
UINT16 enemyteam = NumEnemiesInFiveSectors(aX, aY) - NumEnemiesInAnySector(aX, aY, aZ);
|
||||
UINT16 militiateam = CountAllMilitiaInFiveSectors(aX, aY) - CountAllMilitiaInSector(aX, aY);
|
||||
|
||||
if ( ausTeam == ENEMY_TEAM )
|
||||
return (enemyteam > militiateam);
|
||||
|
||||
return (militiateam > enemyteam);
|
||||
}
|
||||
@@ -2609,6 +2609,43 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
return(AI_ACTION_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: trait skills
|
||||
// if we are a radio operator
|
||||
if ( HAS_SKILL_TRAIT( pSoldier, RADIO_OPERATOR_NT ) > 0 && pSoldier->CanUseSkill(SKILLS_RADIO_ARTILLERY, TRUE) )
|
||||
{
|
||||
UINT32 tmp;
|
||||
INT32 skilltargetgridno = 0;
|
||||
|
||||
// call reinforcements if we haven't yet done so
|
||||
if ( !gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition && MoreFriendsThanEnemiesinNearbysectors(pSoldier->bTeam, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ) )
|
||||
{
|
||||
// if frequencies are jammed...
|
||||
if ( SectorJammed() )
|
||||
{
|
||||
// if we are jamming, turn it off, otherwise, bad luck...
|
||||
if ( pSoldier->IsJamming() )
|
||||
{
|
||||
pSoldier->usAISkillUse = SKILLS_RADIO_TURNOFF;
|
||||
pSoldier->aiData.usActionData = skilltargetgridno;
|
||||
return(AI_ACTION_USE_SKILL);
|
||||
}
|
||||
}
|
||||
// frequencies are clear, lets call for help
|
||||
else
|
||||
{
|
||||
// raise alarm!
|
||||
return( AI_ACTION_RED_ALERT );
|
||||
}
|
||||
}
|
||||
// if we can't call in artillery, jam frequencies, so that the palyer can't use radio skills
|
||||
else if ( !pSoldier->IsJamming() && !pSoldier->CanAnyArtilleryStrikeBeOrdered(&tmp) )
|
||||
{
|
||||
pSoldier->usAISkillUse = SKILLS_RADIO_JAM;
|
||||
pSoldier->aiData.usActionData = skilltargetgridno;
|
||||
return(AI_ACTION_USE_SKILL);
|
||||
}
|
||||
}
|
||||
}
|
||||
//RELOADING
|
||||
|
||||
@@ -3990,6 +4027,10 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
return(AI_ACTION_NONE);
|
||||
}
|
||||
|
||||
// Flugente: dummies if we do not want to check for any conditions or taboos
|
||||
BOOLEAN SoldierCondTrue(SOLDIERTYPE *pSoldier) { return TRUE; }
|
||||
BOOLEAN SoldierCondFalse(SOLDIERTYPE *pSoldier) { return FALSE; }
|
||||
|
||||
INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
INT32 iCoverPercentBetter, iOffense, iDefense, iChance;
|
||||
@@ -4363,6 +4404,64 @@ INT16 ubMinAPCost;
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: trait skills
|
||||
// if we are a radio operator
|
||||
if ( HAS_SKILL_TRAIT( pSoldier, RADIO_OPERATOR_NT ) > 0 && pSoldier->CanUseSkill(SKILLS_RADIO_ARTILLERY, TRUE) )
|
||||
{
|
||||
// check: would it be possible to call in artillery from neighbouring sectors?
|
||||
UINT32 tmp;
|
||||
INT32 skilltargetgridno = 0;
|
||||
// can we call in artillery?
|
||||
if ( pSoldier->CanAnyArtilleryStrikeBeOrdered(&tmp) )
|
||||
{
|
||||
// if frequencies are jammed...
|
||||
if ( SectorJammed() )
|
||||
{
|
||||
// if we are jamming, turn it off, otherwise, bad luck...
|
||||
if ( pSoldier->IsJamming() )
|
||||
{
|
||||
pSoldier->usAISkillUse = SKILLS_RADIO_TURNOFF;
|
||||
pSoldier->aiData.usActionData = skilltargetgridno;
|
||||
return(AI_ACTION_USE_SKILL);
|
||||
}
|
||||
}
|
||||
// frequencies are clear, order a strike
|
||||
else if ( GetBestAoEGridNo(pSoldier, &skilltargetgridno, max(1, gSkillTraitValues.usVOMortarRadius - 2), 1, 2, SoldierCondTrue, SoldierCondFalse) )
|
||||
{
|
||||
pSoldier->usAISkillUse = SKILLS_RADIO_ARTILLERY;
|
||||
pSoldier->aiData.usActionData = skilltargetgridno;
|
||||
return(AI_ACTION_USE_SKILL);
|
||||
}
|
||||
}
|
||||
// no access to artillery... we can still call reinforcements if we haven't yet done so
|
||||
else if ( !gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition && MoreFriendsThanEnemiesinNearbysectors(pSoldier->bTeam, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ) )
|
||||
{
|
||||
// if frequencies are jammed...
|
||||
if ( SectorJammed() )
|
||||
{
|
||||
// if we are jamming, turn it off, otherwise, bad luck...
|
||||
if ( pSoldier->IsJamming() )
|
||||
{
|
||||
pSoldier->usAISkillUse = SKILLS_RADIO_TURNOFF;
|
||||
pSoldier->aiData.usActionData = skilltargetgridno;
|
||||
return(AI_ACTION_USE_SKILL);
|
||||
}
|
||||
}
|
||||
// frequencies are clear, lets call for help
|
||||
else
|
||||
{
|
||||
// raise alarm!
|
||||
return( AI_ACTION_RED_ALERT );
|
||||
}
|
||||
}
|
||||
// if we can't call in artillery or reinforcements, then nobody else from our team can. So we better jam communications, so that the player cannot use these skills either
|
||||
else if ( !pSoldier->IsJamming() )
|
||||
{
|
||||
pSoldier->usAISkillUse = SKILLS_RADIO_JAM;
|
||||
pSoldier->aiData.usActionData = skilltargetgridno;
|
||||
return(AI_ACTION_USE_SKILL);
|
||||
}
|
||||
}
|
||||
|
||||
BestShot.ubPossible = FALSE; // by default, assume Shooting isn't possible
|
||||
BestThrow.ubPossible = FALSE; // by default, assume Throwing isn't possible
|
||||
|
||||
@@ -103,6 +103,7 @@ typedef enum
|
||||
|
||||
AI_ACTION_JUMP_WINDOW, // added by Flugente: jump through a window
|
||||
AI_ACTION_FREE_PRISONER, // added by Flugente: free a prisoner
|
||||
AI_ACTION_USE_SKILL, // added by Flugente: perform a skill, which one is stored in usAISkillUse
|
||||
} ActionType;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user