mirror of
https://github.com/1dot13/source.git
synced 2026-08-19 14:20:30 +02:00
Moving Tanks Feature (by anv)
- feature: tanks can move around in tactical. Set with Tactical Gameplay Settings > ENEMY_TANKS_CAN_MOVE. - feature: tanks can ignore chance to get through and destroy enemy cover even if it probably won't hit anyone behind it. Set with Tactical Gameplay Settings > ENEMY_TANKS_BLOW_OBSTACLES_UP. - feature: tanks can use cannon even against single mercs and in perfect health. Set with Tactical Gameplay Settings > ENEMY_TANKS_DONT_SPARE_SHELLS. - feature: tanks can noticed as soon as any part of it is visible. Set with Tactical Gameplay Settings > ENEMY_TANKS_ANY_PART_VISIBLE. - feature: depending on game difficulty enemy patrols at game start can be randomly reinforced with tank. Set with Strategic Gameplay Settings > ARMY_USES_TANKS_IN_PATROLS. - feature: depending on game difficulty enemy groups created during offensives can include tanks. Set with trategic Gameplay Settings > ARMY_USES_TANKS_IN_ATTACKS. - feature: mercs in vehicles automatically rest their guns, - fix: guns can be rested on vehicles, - rewritten code to allow putting enemies inside vehicles, - added missing descriptions for all vehicle options to INIEditorJA2Options.xml. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7277 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -346,7 +346,7 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !TANK( pSoldier ) ) || AM_A_ROBOT( pSoldier ) )
|
||||
if ( ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ( (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !TANK( pSoldier ) ) ) || AM_A_ROBOT( pSoldier ) )
|
||||
{
|
||||
// bail out!
|
||||
#ifdef TESTAICONTROL
|
||||
@@ -1235,7 +1235,7 @@ void CancelAIAction(SOLDIERTYPE *pSoldier, UINT8 ubForce)
|
||||
#endif
|
||||
|
||||
// re-enable cover checking, something is new or something strange happened
|
||||
if(!TANK(pSoldier))//dnl ch64 290813
|
||||
if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK(pSoldier))//dnl ch64 290813
|
||||
SkipCoverCheck = FALSE;
|
||||
|
||||
// turn off new situation flag to stop this from repeating all the time!
|
||||
@@ -1506,7 +1506,7 @@ void RefreshAI(SOLDIERTYPE *pSoldier)
|
||||
|
||||
if (pSoldier->aiData.bAlertStatus == STATUS_YELLOW)
|
||||
SkipCoverCheck = FALSE;
|
||||
if(TANK(pSoldier))//dnl ch64 290813 tanks don't have move animations
|
||||
if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK(pSoldier) )//dnl ch64 290813 tanks don't have move animations
|
||||
SkipCoverCheck = TRUE;
|
||||
|
||||
// if he's in battle or knows opponents are here
|
||||
@@ -1597,7 +1597,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
|
||||
// in most cases, merc will change location, or may cause damage to opponents,
|
||||
// so a new cover check will be necessary. Exceptions handled individually.
|
||||
if(!TANK(pSoldier))//dnl ch64 290813
|
||||
if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK(pSoldier) )//dnl ch64 290813
|
||||
SkipCoverCheck = FALSE;
|
||||
|
||||
// reset this field, too
|
||||
@@ -2612,6 +2612,11 @@ void HandleAITacticalTraversal( SOLDIERTYPE * pSoldier )
|
||||
++pSectorInfo->ubNumAdmins;
|
||||
break;
|
||||
|
||||
case SOLDIER_CLASS_TANK:
|
||||
if( TANK(pSoldier) )
|
||||
++pSectorInfo->ubNumTanks;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
ProcessQueenCmdImplicationsOfDeath( pSoldier );
|
||||
|
||||
@@ -2480,7 +2480,8 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 * pusFromGridNo)
|
||||
switch (pSoldier->aiData.bOrders)
|
||||
{
|
||||
// JA2 GOLD: give non-NPCs a 5 tile roam range for cover in combat when being shot at
|
||||
case STATIONARY: if (pSoldier->ubProfile != NO_PROFILE || (pSoldier->aiData.bAlertStatus < STATUS_BLACK && !(pSoldier->aiData.bUnderFire)))
|
||||
// anv: and tanks who are technically NPCs
|
||||
case STATIONARY: if ( ( pSoldier->ubProfile != NO_PROFILE && !TANK(pSoldier) ) || (pSoldier->aiData.bAlertStatus < STATUS_BLACK && !(pSoldier->aiData.bUnderFire)))
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
+14
-6
@@ -985,7 +985,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
|
||||
bPersOL = pSoldier->aiData.bOppList[pOpponent->ubID];
|
||||
|
||||
if ((Item[usInHand].mortar ) || (Item[usInHand].grenadelauncher ) )
|
||||
if ((Item[usInHand].mortar ) || (Item[usInHand].grenadelauncher ) || (Item[usInHand].cannon ) )
|
||||
{
|
||||
bPublOL = gbPublicOpplist[pSoldier->bTeam][pOpponent->ubID];
|
||||
// allow long range firing, where target doesn't PERSONALLY see opponent
|
||||
@@ -1100,19 +1100,21 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
case 0:
|
||||
case 1:
|
||||
// they won't use them until they have 2+ opponents as long as half life left
|
||||
if ((ubOpponentCnt < 2) && (pSoldier->stats.bLife > (pSoldier->stats.bLifeMax / 2)))
|
||||
// anv: tanks don't care
|
||||
if ( ( ubOpponentCnt < 2 ) && ( pSoldier->stats.bLife > pSoldier->stats.bLifeMax / 2 ) &&
|
||||
( !gGameExternalOptions.fEnemyTanksDontSpareShells || !TANK(pSoldier) ) && !gGameExternalOptions.fEnemiesDontSpareLaunchables )
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// they won't use them until they have 2+ opponents as long as 3/4 life left
|
||||
if ((ubOpponentCnt < 2) && (pSoldier->stats.bLife > (pSoldier->stats.bLifeMax / 4) * 3 ))
|
||||
if ( (ubOpponentCnt < 2) && ( pSoldier->stats.bLife > (pSoldier->stats.bLifeMax / 4) * 3 ) &&
|
||||
( !gGameExternalOptions.fEnemyTanksDontSpareShells || !TANK(pSoldier) ) && !gGameExternalOptions.fEnemiesDontSpareLaunchables )
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1346,7 +1348,13 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
if ( EXPLOSIVE_GUN( usInHand ) )
|
||||
{
|
||||
ubChanceToGetThrough = AISoldierToLocationChanceToGetThrough( pSoldier, sGridNo, bOpponentLevel[ubLoop], 0 );
|
||||
if ( ubChanceToGetThrough == 0)
|
||||
// anv: tanks shouldn't care about chance to get through - can't hit? At least we'll destroy their cover.
|
||||
// also AISoldierToLocationChanceToGetThrough used to return 0 for tanks, but that's a different story
|
||||
if( ( gGameExternalOptions.fEnemyTanksBlowObstaclesUp && TANK(pSoldier) ) || gGameExternalOptions.fEnemiesBlowObstaclesUp )
|
||||
{
|
||||
ubChanceToGetThrough = 100;
|
||||
}
|
||||
if ( ubChanceToGetThrough == 0 )
|
||||
{
|
||||
continue; // next gridno
|
||||
}
|
||||
@@ -1387,7 +1395,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
||||
// this is try to minimize enemies wasting their (few) mortar shells or LAWs
|
||||
// they won't use them on less than 2 targets as long as half life left
|
||||
if ((Item[usInHand].mortar || Item[usInHand].rocketlauncher ) && (ubOppsInRange < 2) &&
|
||||
(pSoldier->stats.bLife > (pSoldier->stats.bLifeMax / 2)))
|
||||
(pSoldier->stats.bLife > (pSoldier->stats.bLifeMax / 2)) && ( !gGameExternalOptions.fEnemyTanksDontSpareShells || !TANK(pSoldier) ) && !gGameExternalOptions.fEnemiesDontSpareLaunchables )
|
||||
{
|
||||
continue; // next gridno
|
||||
}
|
||||
|
||||
+22
-15
@@ -794,7 +794,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
}
|
||||
|
||||
if ( TANK( pSoldier ) )
|
||||
if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) )
|
||||
{
|
||||
return( AI_ACTION_NONE );
|
||||
}
|
||||
@@ -1889,7 +1889,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
}
|
||||
|
||||
if ( TANK( pSoldier ) )
|
||||
if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) )
|
||||
{
|
||||
return( AI_ACTION_NONE );
|
||||
}
|
||||
@@ -2521,7 +2521,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
}
|
||||
}
|
||||
|
||||
if ( fCivilian && !( pSoldier->ubBodyType == COW || pSoldier->ubBodyType == CRIPPLECIV ) &&
|
||||
if ( fCivilian && !( pSoldier->ubBodyType == COW || pSoldier->ubBodyType == CRIPPLECIV || pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) &&
|
||||
gTacticalStatus.bBoxingState == NOT_BOXING)
|
||||
{
|
||||
if ( FindAIUsableObjClass( pSoldier, IC_WEAPON ) == ITEM_NOT_FOUND )
|
||||
@@ -2589,7 +2589,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
}
|
||||
|
||||
|
||||
if ( fCivilian && !( pSoldier->ubBodyType == COW || pSoldier->ubBodyType == CRIPPLECIV ) )
|
||||
if ( fCivilian && !( pSoldier->ubBodyType == COW || pSoldier->ubBodyType == CRIPPLECIV || pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
|
||||
{
|
||||
if ( FindAIUsableObjClass( pSoldier, IC_WEAPON ) == ITEM_NOT_FOUND )
|
||||
{
|
||||
@@ -3330,7 +3330,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
}
|
||||
}
|
||||
|
||||
if ( !TANK( pSoldier ) )
|
||||
//if ( !TANK( pSoldier ) )
|
||||
if( ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK( pSoldier ) ) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: main red ai");
|
||||
|
||||
@@ -4385,6 +4386,11 @@ INT16 ubMinAPCost;
|
||||
// can this guy move to any of the neighbouring squares ? (sets TRUE/FALSE)
|
||||
ubCanMove = (pSoldier->bActionPoints >= MinPtsToMove(pSoldier));
|
||||
|
||||
if( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
|
||||
{
|
||||
ubCanMove = 0;
|
||||
}
|
||||
|
||||
if ( (pSoldier->bTeam == ENEMY_TEAM || pSoldier->ubProfile == WARDEN) && (gTacticalStatus.fPanicFlags & PANIC_TRIGGERS_HERE) && (gTacticalStatus.ubTheChosenOne == NOBODY) )
|
||||
{
|
||||
INT8 bPanicTrigger;
|
||||
@@ -4560,7 +4566,7 @@ INT16 ubMinAPCost;
|
||||
// offer surrender?
|
||||
#ifdef JA2UB
|
||||
#else
|
||||
if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !( gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER ) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 )
|
||||
if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !( gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER ) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !TANK(pSoldier) )
|
||||
{
|
||||
if ( gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 && gTacticalStatus.Team[ CREATURE_TEAM ].bMenInSector == 0 && NumPCsInSector() < 4 && gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector >= NumPCsInSector() * 3 )
|
||||
{
|
||||
@@ -4601,7 +4607,7 @@ INT16 ubMinAPCost;
|
||||
{
|
||||
if (fCivilian)
|
||||
{
|
||||
if ( ( bCanAttack == NOSHOOT_NOWEAPON) && !(pSoldier->flags.uiStatusFlags & SOLDIER_BOXER) && pSoldier->ubBodyType != COW && pSoldier->ubBodyType != CRIPPLECIV )
|
||||
if ( ( bCanAttack == NOSHOOT_NOWEAPON) && !(pSoldier->flags.uiStatusFlags & SOLDIER_BOXER) && pSoldier->ubBodyType != COW && pSoldier->ubBodyType != CRIPPLECIV && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) )
|
||||
{
|
||||
// cower in fear!!
|
||||
if ( pSoldier->flags.uiStatusFlags & SOLDIER_COWERING )
|
||||
@@ -4841,6 +4847,7 @@ INT16 ubMinAPCost;
|
||||
|
||||
if(BestShot.ubFriendlyFireChance)//dnl ch61 180813
|
||||
{
|
||||
iChance = 0;
|
||||
if(BestShot.ubFriendlyFireChance == 100)
|
||||
{
|
||||
if(pSoldier->aiData.bAttitude == AGGRESSIVE)
|
||||
@@ -4973,7 +4980,7 @@ INT16 ubMinAPCost;
|
||||
|
||||
// if the soldier does have a usable knife somewhere
|
||||
// 0verhaul: And is not a tank!
|
||||
if (bWeaponIn != NO_SLOT && !TANK( pSoldier))
|
||||
if (bWeaponIn != NO_SLOT && !TANK( pSoldier) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"try to stab");
|
||||
BestStab.bWeaponIn = bWeaponIn;
|
||||
@@ -5041,7 +5048,7 @@ INT16 ubMinAPCost;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SANDRO - even if we don't have any blade, calculate how much damage we could do unarmed
|
||||
else if ( !TANK( pSoldier) )
|
||||
else if ( !TANK( pSoldier) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) )
|
||||
{
|
||||
bWeaponIn = FindAIUsableObjClass( pSoldier, IC_PUNCH );
|
||||
if (bWeaponIn == NO_SLOT) // if no punch-type weapon found, just calculate it with empty hands
|
||||
@@ -5497,7 +5504,7 @@ INT16 ubMinAPCost;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(!TANK(pSoldier))
|
||||
if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK(pSoldier) )
|
||||
{
|
||||
// first get the direction, as we will need to pass that in to ShootingStanceChange
|
||||
bDirection = atan8(CenterX(pSoldier->sGridNo),CenterY(pSoldier->sGridNo),CenterX(BestAttack.sTarget),CenterY(BestAttack.sTarget));
|
||||
@@ -5967,7 +5974,7 @@ L_NEWAIM:
|
||||
}
|
||||
|
||||
// end of tank AI
|
||||
if ( TANK( pSoldier ) )
|
||||
if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) )
|
||||
{
|
||||
return( AI_ACTION_NONE );
|
||||
}
|
||||
@@ -6598,7 +6605,7 @@ void DecideAlertStatus( SOLDIERTYPE *pSoldier )
|
||||
|
||||
gubNPCPathCount = 0;
|
||||
|
||||
if ( TANK( pSoldier ) )
|
||||
if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) )
|
||||
{
|
||||
return( AI_ACTION_NONE );
|
||||
}
|
||||
@@ -7110,7 +7117,7 @@ void DecideAlertStatus( SOLDIERTYPE *pSoldier )
|
||||
}
|
||||
}
|
||||
|
||||
if ( TANK( pSoldier ) )
|
||||
if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) )
|
||||
{
|
||||
return( AI_ACTION_NONE );
|
||||
}
|
||||
@@ -7269,7 +7276,7 @@ void DecideAlertStatus( SOLDIERTYPE *pSoldier )
|
||||
// RADIO RED ALERT: determine %chance to call others and report contact
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if ( !TANK( pSoldier ) )
|
||||
if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK( pSoldier ) )
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: main red ai");
|
||||
|
||||
@@ -8450,7 +8457,7 @@ void DecideAlertStatus( SOLDIERTYPE *pSoldier )
|
||||
}
|
||||
|
||||
// end of tank AI
|
||||
if ( TANK( pSoldier ) )
|
||||
if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || TANK( pSoldier ) )
|
||||
{
|
||||
return( AI_ACTION_NONE );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user