mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
-added underslung/attached GLs to AI inventory and enabled AI to use them :)
-rewrote the AI sniper code to take advantage of readying weapons. Added new SNIPER order for soldiers that's assigned when a soldier has a sniper rifle (80% chance) or a scope (40% chance). -spreadsheet update git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@216 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+1
-1
@@ -23,7 +23,7 @@ INT16 zVersionLabel[256] = { L"Beta v. 0.98" };
|
||||
#else
|
||||
|
||||
//RELEASE BUILD VERSION
|
||||
INT16 zVersionLabel[256] = { L"Release v1.13.215" };
|
||||
INT16 zVersionLabel[256] = { L"Release v1.13.216" };
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4630,7 +4630,7 @@ BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos )
|
||||
|
||||
pSoldier->sLastTarget = sXPos + (MAXCOL * sYPos);
|
||||
DeductPoints( pSoldier, (INT16)(sAPCost - sAPCostToReady), 0 );
|
||||
|
||||
|
||||
HandleSight( pSoldier, SIGHT_LOOK );
|
||||
|
||||
return( TRUE );
|
||||
|
||||
@@ -1534,7 +1534,11 @@ void ChooseSpecialWeaponsForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8
|
||||
// CreateItem( 298, (INT8)(50 + Random( 51 )), &Object );
|
||||
// PlaceObjectInSoldierCreateStruct( pp, &Object );
|
||||
|
||||
if (fGrenadeLauncher)
|
||||
if ( IsGrenadeLauncherAttached(&pp->Inv[HANDPOS]) ) //Madd: if there's a grenade launcher attached to the gun, then use that instead of giving him another one
|
||||
{
|
||||
itemGrenadeLauncher = GetAttachedGrenadeLauncher(&pp->Inv[HANDPOS]);
|
||||
}
|
||||
else if (fGrenadeLauncher)
|
||||
{
|
||||
itemGrenadeLauncher = PickARandomItem ( GRENADELAUNCHER );
|
||||
// give grenade launcher
|
||||
|
||||
@@ -125,7 +125,7 @@ enum
|
||||
ONCALL, // helps buddies anywhere within the sector
|
||||
SEEKENEMY, // not tied down to any one particular spot
|
||||
RNDPTPATROL, // patrols randomly using patrolGrids
|
||||
//SNIPER, // snipes
|
||||
SNIPER, // snipes
|
||||
MAXORDERS
|
||||
};
|
||||
|
||||
|
||||
@@ -3253,6 +3253,8 @@ BOOLEAN InternalSoldierReadyWeapon( SOLDIERTYPE *pSoldier, UINT8 sFacingDir, BOO
|
||||
|
||||
}
|
||||
|
||||
HandleSight(pSoldier, SIGHT_LOOK );
|
||||
|
||||
return( fReturnVal );
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,26 @@ void RandomizeNewSoldierStats( SOLDIERCREATE_STRUCT *pCreateStruct )
|
||||
pCreateStruct->bAIMorale = MORALE_FEARLESS;
|
||||
}
|
||||
|
||||
void DecideToAssignSniperOrders( SOLDIERCREATE_STRUCT * pp )
|
||||
{
|
||||
//Madd: decide if soldier should be a sniper
|
||||
|
||||
// 30% of anybody w/a scope and decent range being a sniper, 80% chance of a guy w/a sniper rifle being a sniper
|
||||
if ( (GunRange(&pp->Inv[HANDPOS]) >= 40 && IsScoped(&pp->Inv[HANDPOS]) && Random(100) < 30) || ( Weapon[pp->Inv[HANDPOS].usItem].ubWeaponType == GUN_SN_RIFLE && Random(100) < 80 ) )
|
||||
{
|
||||
pp->bOrders = SNIPER;
|
||||
|
||||
if (pp->bAttitude == BRAVEAID)
|
||||
pp->bAttitude = BRAVESOLO;
|
||||
|
||||
if (pp->bAttitude == CUNNINGAID)
|
||||
pp->bAttitude = CUNNINGSOLO;
|
||||
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Sniper Created") );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *pubID )
|
||||
{
|
||||
SOLDIERTYPE Soldier;
|
||||
@@ -1651,6 +1671,8 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
|
||||
if( !bp->fDetailedPlacement && ubSoldierClass != SOLDIER_CLASS_NONE && ubSoldierClass != SOLDIER_CLASS_CREATURE && ubSoldierClass != SOLDIER_CLASS_MINER )
|
||||
GenerateRandomEquipment( pp, ubSoldierClass, bp->bRelativeEquipmentLevel);
|
||||
|
||||
DecideToAssignSniperOrders(pp);
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenBasicPlacementInfo done"));
|
||||
}
|
||||
|
||||
@@ -1810,13 +1832,14 @@ void CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo(
|
||||
//return;
|
||||
}
|
||||
}
|
||||
if ( !gGameOptions.fGunNut )
|
||||
{
|
||||
ReplaceExtendedGuns( pp, bp->ubSoldierClass );
|
||||
}
|
||||
//if ( !gGameOptions.fGunNut )
|
||||
//{
|
||||
// ReplaceExtendedGuns( pp, bp->ubSoldierClass );
|
||||
//}
|
||||
if( bp->ubSoldierClass != SOLDIER_CLASS_NONE && bp->ubSoldierClass != SOLDIER_CLASS_CREATURE && bp->ubSoldierClass != SOLDIER_CLASS_MINER )
|
||||
{
|
||||
GenerateRandomEquipment( pp, bp->ubSoldierClass, bp->bRelativeEquipmentLevel);
|
||||
DecideToAssignSniperOrders(pp);
|
||||
}
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo done"));
|
||||
@@ -2103,6 +2126,7 @@ SOLDIERTYPE* TacticalCreateArmyTroop()
|
||||
pSoldier->sNoiseGridno = (INT16) (CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
|
||||
pSoldier->ubNoiseVolume = MAX_MISC_NOISE_DURATION;
|
||||
}
|
||||
|
||||
return( pSoldier );
|
||||
}
|
||||
|
||||
@@ -2146,6 +2170,7 @@ SOLDIERTYPE* TacticalCreateEliteEnemy()
|
||||
pSoldier->sNoiseGridno = (INT16)(CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
|
||||
pSoldier->ubNoiseVolume = MAX_MISC_NOISE_DURATION;
|
||||
}
|
||||
|
||||
return( pSoldier );
|
||||
}
|
||||
|
||||
@@ -2208,7 +2233,9 @@ SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass )
|
||||
//bp.bAttitude = AGGRESSIVE;
|
||||
bp.bBodyType = -1;
|
||||
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
|
||||
return TacticalCreateSoldier( &pp, &ubID );
|
||||
pSoldier = TacticalCreateSoldier( &pp, &ubID );
|
||||
|
||||
return pSoldier;
|
||||
}
|
||||
|
||||
SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType )
|
||||
|
||||
@@ -410,6 +410,7 @@ void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT q
|
||||
{
|
||||
strcpy( AniParams.zCachedFile, "TILECACHE\\BULLET_TRACER.STI" );
|
||||
AniParams.uiFlags |= ANITILE_LIGHT;
|
||||
AniParams.sDelay = 0;
|
||||
}
|
||||
|
||||
CreateAnimationTile( &AniParams );
|
||||
|
||||
@@ -830,7 +830,8 @@ void HandleSight(SOLDIERTYPE *pSoldier, UINT8 ubSightFlags)
|
||||
else if ( gGameOptions.ubDifficultyLevel >= DIF_LEVEL_MEDIUM )
|
||||
{
|
||||
// don't allow admins to radio
|
||||
if ( pSoldier->bTeam == ENEMY_TEAM && gTacticalStatus.Team[ ENEMY_TEAM ].bAwareOfOpposition && pSoldier->ubSoldierClass != SOLDIER_CLASS_ADMINISTRATOR )
|
||||
//Madd: Huh? why not admins? removed.
|
||||
if ( pSoldier->bTeam == ENEMY_TEAM && gTacticalStatus.Team[ ENEMY_TEAM ].bAwareOfOpposition ) //&& pSoldier->ubSoldierClass != SOLDIER_CLASS_ADMINISTRATOR )
|
||||
{
|
||||
RadioSightings(pSoldier,EVERYBODY, pSoldier->bTeam );
|
||||
}
|
||||
|
||||
+13
-2
@@ -2000,6 +2000,8 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
// reset this field, too
|
||||
pSoldier->bLastAttackHit = FALSE;
|
||||
|
||||
UINT16 usHandItem = pSoldier->inv[HANDPOS].usItem;
|
||||
|
||||
#ifdef TESTAICONTROL
|
||||
if (gfTurnBasedAI || gTacticalStatus.fAutoBandageMode)
|
||||
{
|
||||
@@ -2348,7 +2350,11 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
SimulMessage(tempstr,3000,NODECRYPT);
|
||||
}
|
||||
#endif
|
||||
iRetCode = HandleItem( pSoldier, pSoldier->usActionData, pSoldier->bTargetLevel, pSoldier->inv[HANDPOS].usItem, FALSE );
|
||||
|
||||
if ( pSoldier->bAction == AI_ACTION_TOSS_PROJECTILE && IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS]) )
|
||||
usHandItem = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS]);
|
||||
|
||||
iRetCode = HandleItem( pSoldier, pSoldier->usActionData, pSoldier->bTargetLevel, usHandItem, FALSE );
|
||||
if ( iRetCode != ITEM_HANDLE_OK)
|
||||
{
|
||||
if ( iRetCode != ITEM_HANDLE_BROKEN ) // if the item broke, this is 'legal' and doesn't need reporting
|
||||
@@ -2546,6 +2552,11 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
ActionDone( pSoldier );
|
||||
break;
|
||||
|
||||
case AI_ACTION_RAISE_GUN: //Madd: action added for snipers to ready weapon and use vision range bonuses
|
||||
SoldierReadyWeapon(pSoldier);
|
||||
HandleSight(pSoldier, SIGHT_LOOK | SIGHT_RADIO);
|
||||
break;
|
||||
|
||||
case AI_ACTION_CLIMB_ROOF:
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Executing: AI_ACTION_CLIMB_ROOF");
|
||||
|
||||
@@ -2632,7 +2643,7 @@ void CheckForChangingOrders(SOLDIERTYPE *pSoldier)
|
||||
// crank up ONGUARD to CLOSEPATROL, and CLOSEPATROL to FARPATROL
|
||||
pSoldier->bOrders++; // increase roaming range by 1 category
|
||||
}
|
||||
else if ( pSoldier->bTeam == MILITIA_TEAM )
|
||||
else if ( pSoldier->bTeam == MILITIA_TEAM && pSoldier->bOrders != SNIPER )
|
||||
{
|
||||
// go on alert!
|
||||
pSoldier->bOrders = SEEKENEMY;
|
||||
|
||||
+19
-3
@@ -40,6 +40,9 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier)
|
||||
|
||||
usInHand = pSoldier->inv[HANDPOS].usItem;
|
||||
|
||||
if ( IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS]) )
|
||||
usInHand = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS]);
|
||||
|
||||
// if he's got a MORTAR in his hand, make sure he has a MORTARSHELL avail.
|
||||
if (Item[usInHand].mortar )
|
||||
{
|
||||
@@ -129,6 +132,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
|
||||
ubBestChanceToHit = ubBestAimTime = ubChanceToHit = 0;
|
||||
|
||||
pSoldier->usAttackingWeapon = pSoldier->inv[HANDPOS].usItem;
|
||||
pSoldier->bWeaponMode = WM_NORMAL;
|
||||
|
||||
ubBurstAPs = CalcAPsToBurst( CalcActionPoints( pSoldier ), &(pSoldier->inv[HANDPOS]) );
|
||||
|
||||
@@ -469,6 +473,9 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
usInHand = pSoldier->inv[HANDPOS].usItem;
|
||||
usGrenade = NOTHING;
|
||||
|
||||
if ( IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS]) )
|
||||
usInHand = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS]);
|
||||
|
||||
if ( EXPLOSIVE_GUN( usInHand ) )
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"explosive gun");
|
||||
@@ -1001,7 +1008,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
else
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: checking chance for launcher to beat cover");
|
||||
ubChanceToGetThrough = 100 * CalculateLaunchItemChanceToGetThrough( pSoldier, &(pSoldier->inv[ HANDPOS ] ), sGridNo, bOpponentLevel[ubLoop], 0, &sEndGridNo, TRUE, &bEndLevel, FALSE ); //NumMessage("Chance to get through = ",ubChanceToGetThrough);
|
||||
ubChanceToGetThrough = 100 * CalculateLaunchItemChanceToGetThrough( pSoldier, &(pSoldier->inv[ bPayloadPocket ] ), sGridNo, bOpponentLevel[ubLoop], 0, &sEndGridNo, TRUE, &bEndLevel, FALSE ); //NumMessage("Chance to get through = ",ubChanceToGetThrough);
|
||||
// if we can't possibly get through all the cover
|
||||
if (ubChanceToGetThrough == 0 )
|
||||
{
|
||||
@@ -1979,6 +1986,8 @@ void CheckIfTossPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CheckIfTossPossible");
|
||||
UINT8 ubMinAPcost;
|
||||
|
||||
pSoldier->bWeaponMode = WM_NORMAL;
|
||||
|
||||
if ( TANK( pSoldier ) )
|
||||
{
|
||||
pBestThrow->bWeaponIn = FindCannon(pSoldier);//FindObj( pSoldier, TANK_CANNON );
|
||||
@@ -1993,8 +2002,15 @@ void CheckIfTossPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
pBestThrow->bWeaponIn = FindRocketLauncherOrCannon( pSoldier );
|
||||
if ( pBestThrow->bWeaponIn == NO_SLOT )
|
||||
{
|
||||
// no rocket launcher, consider grenades
|
||||
pBestThrow->bWeaponIn = FindThrowableGrenade( pSoldier );
|
||||
//no rocket launcher -- let's look for an underslung/attached GL
|
||||
INT8 bGunSlot = FindAIUsableObjClass( pSoldier, IC_GUN );
|
||||
if ( bGunSlot != NO_SLOT && IsGrenadeLauncherAttached(&pSoldier->inv[bGunSlot]) )
|
||||
{
|
||||
pBestThrow->bWeaponIn = bGunSlot;
|
||||
pSoldier->bWeaponMode = WM_ATTACHED_GL;
|
||||
}
|
||||
else // no rocket launcher or attached GL, consider grenades
|
||||
pBestThrow->bWeaponIn = FindThrowableGrenade( pSoldier );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+248
-190
@@ -47,6 +47,8 @@ UINT32 guiRedSeekCounter = 0, guiRedHelpCounter = 0; guiRedHideCounter = 0;
|
||||
#define MIN_FLANK_DIST_RED 10 * STRAIGHT_RATIO
|
||||
#define MAX_FLANK_DIST_RED 40 * STRAIGHT_RATIO
|
||||
|
||||
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady );
|
||||
|
||||
void DoneScheduleAction( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
pSoldier->fAIFlags &= (~AI_CHECK_SCHEDULE);
|
||||
@@ -667,13 +669,17 @@ INT8 DecideActionNamedNPC( SOLDIERTYPE * pSoldier )
|
||||
|
||||
INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
DOUBLE iChance, iSneaky = 10;
|
||||
INT8 bInWater,bInGas;
|
||||
DOUBLE iChance, iSneaky = 10;
|
||||
INT16 sBestCover;
|
||||
INT32 iCoverPercentBetter;
|
||||
INT8 bInWater,bInGas;
|
||||
#ifdef DEBUGDECISIONS
|
||||
STR16 tempstr;
|
||||
#endif
|
||||
|
||||
BOOLEAN fCivilian = (PTR_CIVILIAN && (pSoldier->ubCivilianGroup == NON_CIV_GROUP || pSoldier->bNeutral || (pSoldier->ubBodyType >= FATCIV && pSoldier->ubBodyType <= CRIPPLECIV) ) );
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen"));
|
||||
|
||||
BOOLEAN fCivilian = (PTR_CIVILIAN && (pSoldier->ubCivilianGroup == NON_CIV_GROUP || pSoldier->bNeutral || (pSoldier->ubBodyType >= FATCIV && pSoldier->ubBodyType <= CRIPPLECIV) ) );
|
||||
BOOLEAN fCivilianOrMilitia = PTR_CIV_OR_MILITIA;
|
||||
|
||||
gubNPCPathCount = 0;
|
||||
@@ -820,7 +826,11 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// POINT PATROL: move towards next point unless getting a bit winded
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -836,7 +846,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
pSoldier->bNextAction = AI_ACTION_WAIT;
|
||||
pSoldier->usNextActionData = RealtimeDelay( pSoldier );
|
||||
}
|
||||
return(AI_ACTION_POINT_PATROL);
|
||||
return(AI_ACTION_POINT_PATROL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -869,6 +879,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
// WHEN LEFT IN WATER OR GAS, GO TO NEAREST REACHABLE SPOT OF UNGASSED LAND
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: get out of water and gas"));
|
||||
|
||||
if (bInWater || bInGas)
|
||||
{
|
||||
@@ -891,6 +902,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
// REST IF RUNNING OUT OF BREATH
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: rest if running out of breath"));
|
||||
// if our breath is running a bit low, and we're not in the way or in water
|
||||
if ((pSoldier->bBreath < 75) && !bInWater)
|
||||
{
|
||||
@@ -902,7 +914,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// TAKE SNIPER POSITION: determine % chance to climb onto a building
|
||||
// CLIMB A BUILDING
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!fCivilian)
|
||||
@@ -920,6 +932,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
case POINTPATROL: iChance = -20; break;
|
||||
case FARPATROL: iChance += -30; break;
|
||||
case SEEKENEMY: iChance += -20; break;
|
||||
case SNIPER: iChance += 70; break;
|
||||
}
|
||||
|
||||
// modify for attitude
|
||||
@@ -942,13 +955,6 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
// reduce chance for any injury, less likely to hop up if hurt
|
||||
iChance -= (pSoldier->bLifeMax - pSoldier->bLife);
|
||||
|
||||
INT8 bSlot = FindAIUsableObjClass( pSoldier, IC_GUN );
|
||||
if ( GunRange(&pSoldier->inv[bSlot]) >= 30 && IsScoped(&pSoldier->inv[bSlot]) )
|
||||
iChance += 40;
|
||||
|
||||
if ( Weapon[pSoldier->inv[bSlot].usItem].ubWeaponType == GUN_SN_RIFLE )
|
||||
iChance *= 2;
|
||||
|
||||
// reduce chance if breath is down
|
||||
//iChance -= (100 - pSoldier->bBreath); // don't care
|
||||
|
||||
@@ -963,17 +969,6 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
if ( CanClimbFromHere ( pSoldier, fUp ) )
|
||||
{
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is climbing roof",pSoldier->ubID) );
|
||||
if ( GunRange(&pSoldier->inv[bSlot]) >= 30 && IsScoped(&pSoldier->inv[bSlot]) )
|
||||
{
|
||||
pSoldier->sniper = 1;
|
||||
if ( !sniperwarning )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Watch out for snipers..." );
|
||||
//SayQuoteFromAnyBodyInSector( QUOTE_WEARY_SLASH_SUSPUCIOUS );
|
||||
sniperwarning = TRUE;
|
||||
}
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is now a sniper",pSoldier->ubID) );
|
||||
}
|
||||
return( AI_ACTION_CLIMB_ROOF );
|
||||
}
|
||||
else
|
||||
@@ -988,165 +983,199 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// SNIPERS GET TO COVER, EVERYONE INTO THE DARK
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
if ( (pSoldier->bOrders == SNIPER || InLightAtNight( pSoldier->sGridNo, pSoldier->bLevel )) && pSoldier->bActionPoints >= MinPtsToMove(pSoldier) )
|
||||
{
|
||||
sBestCover = FindBestNearbyCover(pSoldier,pSoldier->bAIMorale,&iCoverPercentBetter);
|
||||
if( sBestCover != NOWHERE)
|
||||
{
|
||||
pSoldier->usActionData = sBestCover;
|
||||
return(AI_ACTION_TAKE_COVER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// RANDOM PATROL: determine % chance to start a new patrol route
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!gubNPCPathCount) // try to limit pathing in Green AI
|
||||
{
|
||||
|
||||
iChance = 25 + pSoldier->bBypassToGreen;
|
||||
|
||||
// set base chance according to orders
|
||||
switch (pSoldier->bOrders)
|
||||
if (!gubNPCPathCount) // try to limit pathing in Green AI
|
||||
{
|
||||
case STATIONARY: iChance += -20; break;
|
||||
case ONGUARD: iChance += -15; break;
|
||||
case ONCALL: break;
|
||||
case CLOSEPATROL: iChance += +15; break;
|
||||
case RNDPTPATROL:
|
||||
case POINTPATROL: iChance = 0; break;
|
||||
/*
|
||||
if ( !gfTurnBasedAI )
|
||||
{
|
||||
// realtime deadlock... increase chance!
|
||||
iChance = 110;// more than 100 in case person is defensive
|
||||
}
|
||||
else if ( pSoldier->bInitialActionPoints < pSoldier->bActionPoints ) // could be less because of carried-over points
|
||||
{
|
||||
// CJC: allow pt patrol guys to do a random move in case
|
||||
// of a deadlock provided they haven't done anything yet this turn
|
||||
iChance= 0;
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case FARPATROL: iChance += +25; break;
|
||||
case SEEKENEMY: iChance += -10; break;
|
||||
}
|
||||
|
||||
// modify chance of patrol (and whether it's a sneaky one) by attitude
|
||||
switch (pSoldier->bAttitude)
|
||||
{
|
||||
case DEFENSIVE: iChance += -10; break;
|
||||
case BRAVESOLO: iChance += 5; break;
|
||||
case BRAVEAID: break;
|
||||
case CUNNINGSOLO: iChance += 5; iSneaky += 10; break;
|
||||
case CUNNINGAID: iSneaky += 5; break;
|
||||
case AGGRESSIVE: iChance += 10; iSneaky += -5; break;
|
||||
case ATTACKSLAYONLY: iChance += 10; iSneaky += -5; break;
|
||||
}
|
||||
iChance = 25 + pSoldier->bBypassToGreen;
|
||||
|
||||
// reduce chance for any injury, less likely to wander around when hurt
|
||||
iChance -= (pSoldier->bLifeMax - pSoldier->bLife);
|
||||
|
||||
// reduce chance if breath is down, less likely to wander around when tired
|
||||
iChance -= (100 - pSoldier->bBreath);
|
||||
|
||||
|
||||
// if we're in water with land miles (> 25 tiles) away,
|
||||
// OR if we roll under the chance calculated
|
||||
if (bInWater || ((INT16) PreRandom(100) < iChance))
|
||||
{
|
||||
pSoldier->usActionData = RandDestWithinRange(pSoldier);
|
||||
|
||||
if (pSoldier->usActionData != NOWHERE)
|
||||
{
|
||||
pSoldier->usActionData = GoAsFarAsPossibleTowards( pSoldier, pSoldier->usActionData, AI_ACTION_RANDOM_PATROL );
|
||||
}
|
||||
|
||||
if (pSoldier->usActionData != NOWHERE)
|
||||
// set base chance according to orders
|
||||
switch (pSoldier->bOrders)
|
||||
{
|
||||
#ifdef DEBUGDECISIONS
|
||||
sprintf((CHAR *)tempstr,"%s - RANDOM PATROL to grid %d",pSoldier->name,pSoldier->usActionData);
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (!gfTurnBasedAI)
|
||||
case STATIONARY: iChance += -20; break;
|
||||
case ONGUARD: iChance += -15; break;
|
||||
case ONCALL: break;
|
||||
case CLOSEPATROL: iChance += +15; break;
|
||||
case RNDPTPATROL:
|
||||
case POINTPATROL: iChance = 0; break;
|
||||
/*
|
||||
if ( !gfTurnBasedAI )
|
||||
{
|
||||
// realtime deadlock... increase chance!
|
||||
iChance = 110;// more than 100 in case person is defensive
|
||||
}
|
||||
else if ( pSoldier->bInitialActionPoints < pSoldier->bActionPoints ) // could be less because of carried-over points
|
||||
{
|
||||
// CJC: allow pt patrol guys to do a random move in case
|
||||
// of a deadlock provided they haven't done anything yet this turn
|
||||
iChance= 0;
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case FARPATROL: iChance += +25; break;
|
||||
case SEEKENEMY: iChance += -10; break;
|
||||
case SNIPER: iChance += -90; break;
|
||||
}
|
||||
|
||||
// modify chance of patrol (and whether it's a sneaky one) by attitude
|
||||
switch (pSoldier->bAttitude)
|
||||
{
|
||||
case DEFENSIVE: iChance += -10; break;
|
||||
case BRAVESOLO: iChance += 5; break;
|
||||
case BRAVEAID: break;
|
||||
case CUNNINGSOLO: iChance += 5; iSneaky += 10; break;
|
||||
case CUNNINGAID: iSneaky += 5; break;
|
||||
case AGGRESSIVE: iChance += 10; iSneaky += -5; break;
|
||||
case ATTACKSLAYONLY: iChance += 10; iSneaky += -5; break;
|
||||
}
|
||||
|
||||
// reduce chance for any injury, less likely to wander around when hurt
|
||||
iChance -= (pSoldier->bLifeMax - pSoldier->bLife);
|
||||
|
||||
// reduce chance if breath is down, less likely to wander around when tired
|
||||
iChance -= (100 - pSoldier->bBreath);
|
||||
|
||||
|
||||
// if we're in water with land miles (> 25 tiles) away,
|
||||
// OR if we roll under the chance calculated
|
||||
if (bInWater || ((INT16) PreRandom(100) < iChance))
|
||||
{
|
||||
pSoldier->usActionData = RandDestWithinRange(pSoldier);
|
||||
|
||||
if (pSoldier->usActionData != NOWHERE)
|
||||
{
|
||||
pSoldier->usActionData = GoAsFarAsPossibleTowards( pSoldier, pSoldier->usActionData, AI_ACTION_RANDOM_PATROL );
|
||||
}
|
||||
|
||||
if (pSoldier->usActionData != NOWHERE)
|
||||
{
|
||||
// wait after this...
|
||||
pSoldier->bNextAction = AI_ACTION_WAIT;
|
||||
pSoldier->usNextActionData = RealtimeDelay( pSoldier );
|
||||
}
|
||||
return(AI_ACTION_RANDOM_PATROL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gubNPCPathCount) // try to limit pathing in Green AI
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SEEK FRIEND: determine %chance for man to pay a friendly visit
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
iChance = 25 + pSoldier->bBypassToGreen;
|
||||
|
||||
// set base chance and maximum seeking distance according to orders
|
||||
switch (pSoldier->bOrders)
|
||||
{
|
||||
case STATIONARY: iChance += -20; break;
|
||||
case ONGUARD: iChance += -15; break;
|
||||
case ONCALL: break;
|
||||
case CLOSEPATROL: iChance += +10; break;
|
||||
case RNDPTPATROL:
|
||||
case POINTPATROL: iChance = -10; break;
|
||||
case FARPATROL: iChance += +20; break;
|
||||
case SEEKENEMY: iChance += -10; break;
|
||||
}
|
||||
|
||||
// modify for attitude
|
||||
switch (pSoldier->bAttitude)
|
||||
{
|
||||
case DEFENSIVE: break;
|
||||
case BRAVESOLO: iChance /= 2; break; // loners
|
||||
case BRAVEAID: iChance += 10; break; // friendly
|
||||
case CUNNINGSOLO: iChance /= 2; break; // loners
|
||||
case CUNNINGAID: iChance += 10; break; // friendly
|
||||
case AGGRESSIVE: break;
|
||||
case ATTACKSLAYONLY: break;
|
||||
}
|
||||
|
||||
// reduce chance for any injury, less likely to wander around when hurt
|
||||
iChance -= (pSoldier->bLifeMax - pSoldier->bLife);
|
||||
|
||||
// reduce chance if breath is down
|
||||
iChance -= (100 - pSoldier->bBreath); // very likely to wait when exhausted
|
||||
|
||||
|
||||
if ((INT16) PreRandom(100) < iChance)
|
||||
{
|
||||
if (RandomFriendWithin(pSoldier))
|
||||
{
|
||||
if ( pSoldier->usActionData == GoAsFarAsPossibleTowards( pSoldier, pSoldier->usActionData, AI_ACTION_SEEK_FRIEND ) )
|
||||
{
|
||||
|
||||
#ifdef DEBUGDECISIONS
|
||||
sprintf((CHAR *)tempstr,"%s - SEEK FRIEND at grid %d",pSoldier->name,pSoldier->usActionData);
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (fCivilianOrMilitia && !gfTurnBasedAI)
|
||||
{
|
||||
// pause at the end of the walk!
|
||||
#ifdef DEBUGDECISIONS
|
||||
sprintf((CHAR *)tempstr,"%s - RANDOM PATROL to grid %d",pSoldier->name,pSoldier->usActionData);
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (!gfTurnBasedAI)
|
||||
{
|
||||
// wait after this...
|
||||
pSoldier->bNextAction = AI_ACTION_WAIT;
|
||||
pSoldier->usNextActionData = (UINT16) REALTIME_CIV_AI_DELAY;
|
||||
}
|
||||
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
pSoldier->usNextActionData = RealtimeDelay( pSoldier );
|
||||
}
|
||||
return(AI_ACTION_RANDOM_PATROL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gubNPCPathCount) // try to limit pathing in Green AI
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SEEK FRIEND: determine %chance for man to pay a friendly visit
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
iChance = 25 + pSoldier->bBypassToGreen;
|
||||
|
||||
// set base chance and maximum seeking distance according to orders
|
||||
switch (pSoldier->bOrders)
|
||||
{
|
||||
case STATIONARY: iChance += -20; break;
|
||||
case ONGUARD: iChance += -15; break;
|
||||
case ONCALL: break;
|
||||
case CLOSEPATROL: iChance += +10; break;
|
||||
case RNDPTPATROL:
|
||||
case POINTPATROL: iChance = -10; break;
|
||||
case FARPATROL: iChance += +20; break;
|
||||
case SEEKENEMY: iChance += -10; break;
|
||||
case SNIPER: iChance += -100; break; // Madd: Snipers have no friends :(
|
||||
}
|
||||
|
||||
// modify for attitude
|
||||
switch (pSoldier->bAttitude)
|
||||
{
|
||||
case DEFENSIVE: break;
|
||||
case BRAVESOLO: iChance /= 2; break; // loners
|
||||
case BRAVEAID: iChance += 10; break; // friendly
|
||||
case CUNNINGSOLO: iChance /= 2; break; // loners
|
||||
case CUNNINGAID: iChance += 10; break; // friendly
|
||||
case AGGRESSIVE: break;
|
||||
case ATTACKSLAYONLY: break;
|
||||
}
|
||||
|
||||
// reduce chance for any injury, less likely to wander around when hurt
|
||||
iChance -= (pSoldier->bLifeMax - pSoldier->bLife);
|
||||
|
||||
// reduce chance if breath is down
|
||||
iChance -= (100 - pSoldier->bBreath); // very likely to wait when exhausted
|
||||
|
||||
|
||||
if ((INT16) PreRandom(100) < iChance)
|
||||
{
|
||||
if (RandomFriendWithin(pSoldier))
|
||||
{
|
||||
if ( pSoldier->usActionData == GoAsFarAsPossibleTowards( pSoldier, pSoldier->usActionData, AI_ACTION_SEEK_FRIEND ) )
|
||||
{
|
||||
|
||||
#ifdef DEBUGDECISIONS
|
||||
sprintf((CHAR *)tempstr,"%s - SEEK FRIEND at grid %d",pSoldier->name,pSoldier->usActionData);
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (fCivilianOrMilitia && !gfTurnBasedAI)
|
||||
{
|
||||
// pause at the end of the walk!
|
||||
pSoldier->bNextAction = AI_ACTION_WAIT;
|
||||
pSoldier->usNextActionData = (UINT16) REALTIME_CIV_AI_DELAY;
|
||||
}
|
||||
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SNIPERS LIKE TO CROUCH (even in green)
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: Snipers like to crouch"));
|
||||
// if not in water and not already crouched, try to crouch down first
|
||||
if (pSoldier->bOrders == SNIPER && !PTR_CROUCHED && IsValidStance( pSoldier, ANIM_CROUCH ) )
|
||||
{
|
||||
if (!gfTurnBasedAI || (GetAPsToChangeStance( pSoldier, ANIM_CROUCH ) <= pSoldier->bActionPoints))
|
||||
{
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: Sniper is crouching"));
|
||||
pSoldier->usActionData = ANIM_CROUCH;
|
||||
pSoldier->sniper = 0;
|
||||
return(AI_ACTION_CHANGE_STANCE);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// LOOK AROUND: determine %chance for man to turn in place
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: Soldier deciding to turn"));
|
||||
if (!gfTurnBasedAI || GetAPsToLook( pSoldier ) <= pSoldier->bActionPoints)
|
||||
{
|
||||
// avoid 2 consecutive random turns in a row
|
||||
if (pSoldier->bLastAction != AI_ACTION_CHANGE_FACING)
|
||||
if (pSoldier->bLastAction != AI_ACTION_CHANGE_FACING)
|
||||
{
|
||||
iChance = 25 + pSoldier->bBypassToGreen;
|
||||
|
||||
@@ -1160,6 +1189,8 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
if (pSoldier->bAttitude == DEFENSIVE)
|
||||
iChance += 25;
|
||||
|
||||
if ( pSoldier->bOrders == SNIPER )
|
||||
iChance += 60;
|
||||
|
||||
if ((INT16)PreRandom(100) < iChance)
|
||||
{
|
||||
@@ -1195,11 +1226,28 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
pSoldier->usNextActionData = RealtimeDelay( pSoldier );
|
||||
}
|
||||
|
||||
return(AI_ACTION_CHANGE_FACING);
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: Soldier is turning"));
|
||||
return(AI_ACTION_CHANGE_FACING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SNIPER - RAISE WEAPON TO SCAN AREA
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: Snipers like to raise weapons"));
|
||||
if ( pSoldier->bOrders == SNIPER && pSoldier->sniper == 0 ) //for some reason this check doesn't work: && pSoldier->usAnimState != PickSoldierReadyAnimation( pSoldier, FALSE ) )
|
||||
{
|
||||
if (!gfTurnBasedAI || GetAPsToReadyWeapon( pSoldier, READY_RIFLE_CROUCH ) <= pSoldier->bActionPoints)
|
||||
{
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: Sniper is raising weapon"));
|
||||
pSoldier->sniper = 1;
|
||||
return(AI_ACTION_RAISE_GUN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1291,6 +1339,8 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
// set base chance according to orders
|
||||
if ((pSoldier->bOrders == STATIONARY) || (pSoldier->bOrders == ONGUARD))
|
||||
iChance = 50;
|
||||
else if ( pSoldier->bOrders == SNIPER )
|
||||
iChance = 80;
|
||||
else // all other orders
|
||||
iChance = 25;
|
||||
|
||||
@@ -1345,6 +1395,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
case POINTPATROL: break;
|
||||
case FARPATROL: iChance += -10; break;
|
||||
case SEEKENEMY: iChance += -20; break;
|
||||
case SNIPER: iChance += -80; break; //Madd: sniper contacts are supposed to be automatically reported
|
||||
}
|
||||
|
||||
// modify base chance according to attitude
|
||||
@@ -1487,6 +1538,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
case POINTPATROL: break;
|
||||
case FARPATROL: iChance += 10; break;
|
||||
case SEEKENEMY: iChance += 25; break;
|
||||
case SNIPER: iChance += -50; break;
|
||||
}
|
||||
|
||||
// modify chance of patrol (and whether it's a sneaky one) by attitude
|
||||
@@ -1522,7 +1574,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (fClimb && pSoldier->sniper == 0)//&& pSoldier->usActionData == sNoiseGridNo)
|
||||
if ( fClimb )//&& pSoldier->usActionData == sNoiseGridNo)
|
||||
{
|
||||
// need to climb AND have enough APs to get there this turn
|
||||
BOOLEAN fUp = TRUE;
|
||||
@@ -1530,17 +1582,12 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
fUp = FALSE;
|
||||
|
||||
if (!fUp)
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d, (sniper = %d), is climbing down",pSoldier->ubID,pSoldier->sniper) );
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d, is climbing down",pSoldier->ubID) );
|
||||
|
||||
if ( CanClimbFromHere ( pSoldier, fUp ) )
|
||||
{
|
||||
if (IsActionAffordable(pSoldier) && pSoldier->bActionPoints >= ( AP_CLIMBROOF + MinAPsToAttack( pSoldier, sNoiseGridNo, ADDTURNCOST)))
|
||||
{
|
||||
if ( pSoldier->bAttitude == DEFENSIVE )
|
||||
{
|
||||
pSoldier->sniper = 1;
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is now a sniper",pSoldier->ubID) );
|
||||
}
|
||||
return( AI_ACTION_CLIMB_ROOF );
|
||||
}
|
||||
}
|
||||
@@ -1637,6 +1684,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
case POINTPATROL: iChance += -10; break;
|
||||
case FARPATROL: break;
|
||||
case SEEKENEMY: iChance += 10; break;
|
||||
case SNIPER: iChance += -70; break;
|
||||
}
|
||||
|
||||
// modify chance of patrol (and whether it's a sneaky one) by attitude
|
||||
@@ -1666,7 +1714,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (fClimb && pSoldier->sniper == 0)//&& pSoldier->usActionData == sClosestFriend)
|
||||
if ( fClimb )//&& pSoldier->usActionData == sClosestFriend)
|
||||
{
|
||||
// need to climb AND have enough APs to get there this turn
|
||||
BOOLEAN fUp = TRUE;
|
||||
@@ -1674,17 +1722,12 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
fUp = FALSE;
|
||||
|
||||
if (!fUp)
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d, (sniper = %d), is climbing down",pSoldier->ubID,pSoldier->sniper) );
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is climbing down",pSoldier->ubID) );
|
||||
|
||||
if ( CanClimbFromHere ( pSoldier, fUp ) )
|
||||
{
|
||||
if (IsActionAffordable(pSoldier) )
|
||||
{
|
||||
if ( pSoldier->bAttitude == DEFENSIVE )
|
||||
{
|
||||
pSoldier->sniper = 1;
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is now a sniper",pSoldier->ubID) );
|
||||
}
|
||||
return( AI_ACTION_CLIMB_ROOF );
|
||||
}
|
||||
}
|
||||
@@ -1731,6 +1774,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
case POINTPATROL: break;
|
||||
case FARPATROL: iChance += -5; break;
|
||||
case SEEKENEMY: iChance += -20; break;
|
||||
case SNIPER: iChance += 70; break;
|
||||
}
|
||||
|
||||
// modify chance (and whether it's sneaky) by attitude
|
||||
@@ -1774,7 +1818,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SWITCH TO GREEN: determine if soldier acts as if nothing at all was wrong
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
if ((INT16)PreRandom(100) < 50 )
|
||||
if ((INT16)PreRandom(100) < 50 || pSoldier->bOrders == SNIPER )
|
||||
{
|
||||
#ifdef RECORDNET
|
||||
fprintf(NetDebugFile,"\tDecideActionYellow: guynum %d ignores noise, switching to GREEN AI...\n",pSoldier->ubID);
|
||||
@@ -2156,6 +2200,9 @@ INT32 iCoverPercentBetter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// SNIPER!
|
||||
CheckIfShotPossible(pSoldier,&BestShot,FALSE);
|
||||
|
||||
@@ -2184,7 +2231,7 @@ INT32 iCoverPercentBetter;
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("decideactionred: weapon in slot #%d",BestShot.bWeaponIn));
|
||||
OBJECTTYPE * gun = &pSoldier->inv[BestShot.bWeaponIn];
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("decideactionred: men in sector %d, ubspotters called by %d, nobody %d",gTacticalStatus.Team[pSoldier->bTeam].bMenInSector,gTacticalStatus.ubSpottersCalledForBy,NOBODY ));
|
||||
if ( ( IsScoped(gun) && GunRange(gun) > 30 ) &&
|
||||
if ( (( IsScoped(gun) && GunRange(gun) > 30 ) || pSoldier->bOrders == SNIPER ) &&
|
||||
(gTacticalStatus.Team[pSoldier->bTeam].bMenInSector > 1) &&
|
||||
(gTacticalStatus.ubSpottersCalledForBy == NOBODY))
|
||||
|
||||
@@ -2206,7 +2253,7 @@ INT32 iCoverPercentBetter;
|
||||
CheckIfShotPossible(pSoldier,&BestShot,TRUE);
|
||||
|
||||
//must have a small chance to hit and the opponent must be on the ground (can't suppress guys on the roof)
|
||||
if ( BestShot.ubPossible && BestShot.ubChanceToReallyHit < 50 && Menptr[BestShot.ubOpponent].bLevel == 0 )
|
||||
if ( BestShot.ubPossible && BestShot.ubChanceToReallyHit < 50 && Menptr[BestShot.ubOpponent].bLevel == 0 && pSoldier->bOrders != SNIPER )
|
||||
{
|
||||
// then do it!
|
||||
|
||||
@@ -2410,6 +2457,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
case POINTPATROL: iChance += -5; break;
|
||||
case FARPATROL: iChance += -10; break;
|
||||
case SEEKENEMY: iChance += -20; break;
|
||||
case SNIPER: iChance += -40; break; // Sniper contacts should be reported automatically
|
||||
}
|
||||
|
||||
// modify base chance according to attitude
|
||||
@@ -2595,6 +2643,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
case FARPATROL: bSeekPts += 0; bHelpPts += 0; bHidePts += 0; bWatchPts += 0; break;
|
||||
case ONCALL: bSeekPts += 0; bHelpPts += +1; bHidePts += -1; bWatchPts += 0; break;
|
||||
case SEEKENEMY: bSeekPts += +1; bHelpPts += 0; bHidePts += -1; bWatchPts += -1; break;
|
||||
case SNIPER: bSeekPts += -3; bHelpPts += -1; bHidePts += +2; bWatchPts += +1; break;
|
||||
}
|
||||
|
||||
// modify tendencies according to attitude
|
||||
@@ -2612,7 +2661,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
//Madd: make militia less likely to go running headlong into trouble
|
||||
if ( pSoldier->bTeam == MILITIA_TEAM )
|
||||
{
|
||||
bSeekPts += -1; bHelpPts += 0; bHidePts += +1; bWatchPts += +1;
|
||||
bSeekPts += -1; bHelpPts += 0; bHidePts += +1; bWatchPts += +0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2641,8 +2690,8 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
// if there is an opponent reachable
|
||||
if (sClosestDisturbance != NOWHERE && gAnimControl[ pSoldier->usAnimState ].ubHeight != ANIM_PRONE )
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: seek opponent");
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// SEEK CLOSEST DISTURBANCE: GO DIRECTLY TOWARDS CLOSEST KNOWN OPPONENT
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -2672,7 +2721,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (fClimb && pSoldier->sniper == 0)//&& pSoldier->usActionData == sClosestDisturbance)
|
||||
if (fClimb)//&& pSoldier->usActionData == sClosestDisturbance)
|
||||
{
|
||||
// need to climb AND have enough APs to get there this turn
|
||||
BOOLEAN fUp = TRUE;
|
||||
@@ -2680,7 +2729,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
fUp = FALSE;
|
||||
|
||||
if (!fUp)
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d, (sniper = %d), is climbing down",pSoldier->ubID,pSoldier->sniper) );
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is climbing down",pSoldier->ubID) );
|
||||
|
||||
if ( CanClimbFromHere ( pSoldier, fUp ) )
|
||||
{
|
||||
@@ -2888,7 +2937,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
AIPopMessage(tempstr);
|
||||
#endif
|
||||
|
||||
if (fClimb && pSoldier->sniper == 0)//&& pSoldier->usActionData == sClosestFriend)
|
||||
if ( fClimb )//&& pSoldier->usActionData == sClosestFriend)
|
||||
{
|
||||
// need to climb AND have enough APs to get there this turn
|
||||
BOOLEAN fUp = TRUE;
|
||||
@@ -2896,7 +2945,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: radio red alert?");
|
||||
fUp = FALSE;
|
||||
|
||||
if (!fUp)
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d, (sniper = %d), is climbing down",pSoldier->ubID,pSoldier->sniper) );
|
||||
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Soldier %d is climbing down",pSoldier->ubID) );
|
||||
|
||||
if ( CanClimbFromHere ( pSoldier, fUp ) )
|
||||
{
|
||||
@@ -4063,9 +4112,9 @@ bCanAttack = FALSE;
|
||||
|
||||
|
||||
// smart guys more likely to try to stay alive, dolts more likely to shoot!
|
||||
if (pSoldier->bWisdom >= 80)
|
||||
if (pSoldier->bWisdom >= 50) //Madd: reduced the wisdom required to want to live...
|
||||
iDefense += 10;
|
||||
else if (pSoldier->bWisdom < 50)
|
||||
else if (pSoldier->bWisdom < 30)
|
||||
iDefense -= 10;
|
||||
|
||||
// some orders are more offensive, others more defensive
|
||||
@@ -4073,6 +4122,8 @@ bCanAttack = FALSE;
|
||||
iOffense += 10;
|
||||
else if ((pSoldier->bOrders == STATIONARY) || (pSoldier->bOrders == ONGUARD))
|
||||
iDefense += 10;
|
||||
else if (pSoldier->bOrders == SNIPER)
|
||||
iDefense += 30;
|
||||
|
||||
switch (pSoldier->bAttitude)
|
||||
{
|
||||
@@ -4407,7 +4458,7 @@ bCanAttack = FALSE;
|
||||
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("DecideActionBlack: Check for GL Bursts, is launcher capable? = %d, rtpcombat? = %d, bestattackaction = %d",IsGunBurstCapable( pSoldier, BestAttack.bWeaponIn, FALSE ),pSoldier->bRTPCombat,ubBestAttackAction ));
|
||||
if (ubBestAttackAction == AI_ACTION_TOSS_PROJECTILE && IsGunBurstCapable( pSoldier, BestAttack.bWeaponIn, FALSE ) &&
|
||||
if (ubBestAttackAction == AI_ACTION_TOSS_PROJECTILE && (Item[pSoldier->inv[BestAttack.bWeaponIn].usItem].usItemClass == IC_LAUNCHER && IsGunBurstCapable( pSoldier, BestAttack.bWeaponIn, FALSE )) &&
|
||||
(pSoldier->bTeam != gbPlayerNum || pSoldier->bRTPCombat == RTP_COMBAT_AGGRESSIVE) )
|
||||
{
|
||||
|
||||
@@ -4706,6 +4757,7 @@ bCanAttack = FALSE;
|
||||
case POINTPATROL: iChance += -5; break;
|
||||
case FARPATROL: iChance += -10; break;
|
||||
case SEEKENEMY: iChance += -20; break;
|
||||
case SNIPER: iChance += -80; break;
|
||||
}
|
||||
|
||||
// modify base chance according to attitude
|
||||
@@ -4787,10 +4839,16 @@ INT8 DecideAction(SOLDIERTYPE *pSoldier)
|
||||
UINT32 uiStartTime, uiEndTime;
|
||||
#endif
|
||||
|
||||
if ( !sniperwarning && pSoldier->bOrders == SNIPER )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Watch out for snipers..." );
|
||||
sniperwarning = TRUE;
|
||||
}
|
||||
|
||||
if (!biggunwarning && FindRocketLauncherOrCannon(pSoldier) != NO_SLOT )
|
||||
{
|
||||
biggunwarning = TRUE;
|
||||
//TODO: does this work ok here?
|
||||
//TODO: don't say this again after reloading a savegame
|
||||
SayQuoteFromAnyBodyInSector( QUOTE_WEARY_SLASH_SUSPUCIOUS );
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ typedef enum
|
||||
AI_ACTION_END_COWER_AND_MOVE, // sort of dummy value, special for civilians who are to go somewhere at end of battle
|
||||
AI_ACTION_TRAVERSE_DOWN, // move down a level
|
||||
AI_ACTION_OFFER_SURRENDER, // offer surrender to the player
|
||||
AI_ACTION_RAISE_GUN,
|
||||
} ActionType;
|
||||
|
||||
|
||||
|
||||
@@ -316,6 +316,7 @@ void DeleteAniTiles( )
|
||||
|
||||
DeleteAniTile( pNode );
|
||||
}
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("DeleteAniTiles done") );
|
||||
}
|
||||
|
||||
|
||||
@@ -382,7 +383,9 @@ void DeleteAniTile( ANITILE *pAniTile )
|
||||
}
|
||||
if ( pAniNode->uiFlags & ANITILE_LIGHT && pAniNode->lightSprite >= 0 )
|
||||
{
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@1 Destroying light sprite %d", pAniNode->lightSprite) );
|
||||
LightSpriteDestroy(pAniNode->lightSprite);
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@1 Light sprite destroyed") );
|
||||
}
|
||||
|
||||
if ( ( pAniNode->uiFlags & ANITILE_CACHEDTILE ) )
|
||||
@@ -453,7 +456,9 @@ void DeleteAniTile( ANITILE *pAniTile )
|
||||
}
|
||||
}
|
||||
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ freeing up animation memory") );
|
||||
MemFree( pAniNode );
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ DeleteAniTile: done") );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -613,16 +618,13 @@ void UpdateAniTiles( )
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pNode->uiFlags & ANITILE_LIGHT && pNode->lightSprite >= 0 )
|
||||
{
|
||||
LightSpriteDestroy(pAniNode->lightSprite);
|
||||
}
|
||||
|
||||
// Delete from world!
|
||||
DeleteAniTile( pNode );
|
||||
|
||||
// Turn back on redunency checks!
|
||||
gTacticalStatus.uiFlags &= (~NOHIDE_REDUNDENCY);
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("UpdateAniTiles: tile deleted, flags updated - done") );
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -714,6 +716,7 @@ void UpdateAniTiles( )
|
||||
{
|
||||
// Delete from world!
|
||||
DeleteAniTile( pNode );
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("UpdateAniTiles: tile deleted - done") );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1846,7 +1846,7 @@ DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("physics.cpp line 1750"));
|
||||
fGLauncher = TRUE;
|
||||
sMinRange = MIN_MORTAR_RANGE/2;
|
||||
|
||||
if (gGameSettings.fOptions[TOPTION_GL_HIGH_ANGLE])
|
||||
if ( (gGameSettings.fOptions[TOPTION_GL_HIGH_ANGLE] && pSoldier->bTeam == OUR_TEAM) || ( pSoldier->bTeam == ENEMY_TEAM && gGameOptions.ubDifficultyLevel >= DIF_LEVEL_HARD ) )
|
||||
dDegrees *= 2;
|
||||
//fLauncher = TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user