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:
Wanne
2014-06-18 18:10:07 +00:00
parent 33b3707381
commit 981c81b4b4
42 changed files with 971 additions and 372 deletions
+221 -92
View File
@@ -462,7 +462,7 @@ void SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup );
void ClearPreviousAIGroupAssignment( GROUP *pGroup );
void CalcNumTroopsBasedOnComposition( UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 ubTotal, INT32 iCompositionID );
void CalcNumTroopsBasedOnComposition( UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 ubTotal, INT32 iCompositionID );
void ConvertGroupTroopsToComposition( GROUP *pGroup, INT32 iCompositionID );
void RemoveSoldiersFromGarrisonBasedOnComposition( INT32 iGarrisonID, UINT8 ubSize );
@@ -556,7 +556,7 @@ INT32 GarrisonReinforcementsRequested( INT32 iGarrisonID, UINT8 *pubExtraReinfor
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ];
iExistingForces = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
iExistingForces = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
iReinforcementsRequested = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation - iExistingForces;
//Record how many of the reinforcements are additionally provided due to being denied in the past. This will grow
@@ -592,7 +592,7 @@ INT32 ReinforcementsAvailable( INT32 iGarrisonID )
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ];
iReinforcementsAvailable = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins;
iReinforcementsAvailable = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks;
iReinforcementsAvailable -= gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation;
switch( gGarrisonGroup[ iGarrisonID ].ubComposition )
@@ -673,7 +673,7 @@ BOOLEAN AdjacentSectorIsImportantAndUndefended( UINT8 ubSectorID )
pSector = &SectorInfo[ ubSectorID ];
if( pSector->ubNumTroops || pSector->ubNumElites || pSector->ubNumAdmins )
if( pSector->ubNumTroops || pSector->ubNumElites || pSector->ubNumAdmins || pSector->ubNumTanks )
{
return FALSE;
}
@@ -815,7 +815,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic2");
}
}
#ifdef JA2BETAVERSION
if( pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites != pGroup->ubGroupSize ||
if( pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks != pGroup->ubGroupSize ||
pGroup->ubGroupSize > iMaxEnemyGroupSize )
{
SAIReportError( L"Strategic AI: Internal error (bad group populations). Please send PRIOR save file and Strategic Decisions.txt." );
@@ -1120,6 +1120,7 @@ void InitStrategicAI()
SECTORINFO *pSector = NULL;
GROUP *pGroup;
UINT8 ubNumTroops;
UINT8 ubNumTanks;
INT32 iPercentElitesBonus;
INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic3");
@@ -1432,9 +1433,9 @@ void InitStrategicAI()
}
// fill up deficit with admins if total enemies less than min enemy group size
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites < gubMinEnemyGroupSize )
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks < gubMinEnemyGroupSize )
{
pSector->ubNumAdmins = gubMinEnemyGroupSize - pSector->ubNumTroops - pSector->ubNumElites;
pSector->ubNumAdmins = gubMinEnemyGroupSize - pSector->ubNumTroops - pSector->ubNumElites - pSector->ubNumTanks;
}
//Calculate weight (range is -20 to +20 before multiplier).
@@ -1472,11 +1473,22 @@ void InitStrategicAI()
{ //Add this patrol group now.
ubNumTroops = (UINT8)(gPatrolGroup[ i ].bSize + Random( 3 ) - 1);
ubNumTroops = (UINT8)max( gubMinEnemyGroupSize, min( iMaxEnemyGroupSize, ubNumTroops ) );
ubNumTanks = 0;
if( ubNumTroops && gGameExternalOptions.fArmyUsesTanksInPatrols )
{
if( Random( 10 ) < gGameOptions.ubDifficultyLevel && i != 3 && i != 4)
{
ubNumTroops--;
ubNumTanks++;
}
}
//ubNumTroops = (UINT8)max( gubMinEnemyGroupSize, min( MAX_STRATEGIC_TEAM_SIZE, gPatrolGroup[ i ].bSize + Random( 3 ) - 1 ) );
//Note on adding patrol groups...
//The patrol group can't actually start on the first waypoint, so we set it to the second way
//point for initialization, and then add the waypoints from 0 up
pGroup = CreateNewEnemyGroupDepartingFromSector( gPatrolGroup[ i ].ubSectorID[ 1 ], 0, ubNumTroops, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( gPatrolGroup[ i ].ubSectorID[ 1 ], 0, ubNumTroops, 0, ubNumTanks );
Assert( pGroup );
if( i == 3 || i == 4 )
@@ -1788,7 +1800,8 @@ BOOLEAN HandlePlayerGroupNoticedByPatrolGroup( GROUP *pPlayerGroup, GROUP *pEnem
ubSectorID = (BOOLEAN)SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY );
usOffensePoints = pEnemyGroup->pEnemyGroup->ubNumAdmins * 2 +
pEnemyGroup->pEnemyGroup->ubNumTroops * 4 +
pEnemyGroup->pEnemyGroup->ubNumElites * 6;
pEnemyGroup->pEnemyGroup->ubNumElites * 6 +
pEnemyGroup->pEnemyGroup->ubNumTanks * 20;
if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) )
{
RequestAttackOnSector( ubSectorID, usDefencePoints );
@@ -1838,7 +1851,8 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID )
}
usOffensePoints = pSector->ubNumAdmins * 2 +
pSector->ubNumTroops * 4 +
pSector->ubNumElites * 6;
pSector->ubNumElites * 6 +
pSector->ubNumTanks * 20;
if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) )
{
RequestAttackOnSector( ubSectorID, usDefencePoints );
@@ -1850,7 +1864,7 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID )
if( pSector->ubGarrisonID != NO_GARRISON )
{
//Decide whether or not they will attack them with some of the troops.
ubEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites);
ubEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks);
if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE )
iReinforcementsApproved = (ubEnemies - gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation );
else
@@ -1858,7 +1872,7 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID )
if( iReinforcementsApproved*2 > pPlayerGroup->ubGroupSize*3 && iReinforcementsApproved > gubMinEnemyGroupSize )
{ //Then enemy's available outnumber the player by at least 3:2, so attack them.
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSectorID, 0, (UINT8)iReinforcementsApproved, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0 );
ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition );
@@ -1866,12 +1880,12 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID )
RemoveSoldiersFromGarrisonBasedOnComposition( pSector->ubGarrisonID, pGroup->ubGroupSize );
if( pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins > iMaxEnemyGroupSize )
if( pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks > iMaxEnemyGroupSize )
{
#ifdef JA2BETAVERSION
LogStrategicEvent( "ERROR: Sector %c%d now has %d enemies (max %d).",
gGarrisonGroup[ pSector->ubGarrisonID ].ubSectorID / 16 + 'A' , gGarrisonGroup[ pSector->ubGarrisonID ].ubSectorID % 16,
pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins, iMaxEnemyGroupSize );
pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks, iMaxEnemyGroupSize );
#endif
}
@@ -1893,7 +1907,8 @@ BOOLEAN HandleMilitiaNoticedByPatrolGroup( UINT8 ubSectorID, GROUP *pEnemyGroup
UINT8 ubSectorY = (UINT8)(ubSectorID / 16) + 1;
usOffensePoints = pEnemyGroup->pEnemyGroup->ubNumAdmins * 2 +
pEnemyGroup->pEnemyGroup->ubNumTroops * 4 +
pEnemyGroup->pEnemyGroup->ubNumElites * 6;
pEnemyGroup->pEnemyGroup->ubNumElites * 6 +
pEnemyGroup->pEnemyGroup->ubNumTanks * 20;
if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) )
{
RequestAttackOnSector( ubSectorID, usDefencePoints );
@@ -2043,11 +2058,11 @@ void HandleEmptySectorNoticedByGarrison( UINT8 ubGarrisonSectorID, UINT8 ubEmpty
//An opportunity has arisen, where the enemy has noticed an important sector that is undefended.
pSector = &SectorInfo[ ubGarrisonSectorID ];
ubAvailableTroops = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins;
ubAvailableTroops = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks;
if( ubAvailableTroops >= gubMinEnemyGroupSize * 2 )
{ //split group into two groups, and move one of the groups to the next sector.
pGroup = CreateNewEnemyGroupDepartingFromSector( ubGarrisonSectorID, 0, (UINT8)(ubAvailableTroops / 2), 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( ubGarrisonSectorID, 0, (UINT8)(ubAvailableTroops / 2), 0, 0 );
ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ ubDstGarrisonID ].ubComposition );
RemoveSoldiersFromGarrisonBasedOnComposition( ubSrcGarrisonID, pGroup->ubGroupSize );
gGarrisonGroup[ ubDstGarrisonID ].ubPendingGroupID = pGroup->ubGroupID;
@@ -2145,11 +2160,12 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5");
pSector->ubNumAdmins = (UINT8)(pSector->ubNumAdmins + pGroup->pEnemyGroup->ubNumAdmins);
pSector->ubNumTroops = (UINT8)(pSector->ubNumTroops + pGroup->pEnemyGroup->ubNumTroops);
pSector->ubNumElites = (UINT8)(pSector->ubNumElites + pGroup->pEnemyGroup->ubNumElites);
pSector->ubNumTanks = (UINT8)(pSector->ubNumTanks + pGroup->pEnemyGroup->ubNumTanks);
#ifdef JA2BETAVERSION
LogStrategicEvent( "%d reinforcements have arrived to garrison sector %c%d",
pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops +
pGroup->pEnemyGroup->ubNumElites, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX );
pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX );
#endif
if( IsThisSectorASAMSector( pGroup->ubSectorX, pGroup->ubSectorY, 0 ) )
{
@@ -2218,10 +2234,11 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5");
pPatrolGroup->pEnemyGroup->ubNumTroops += pGroup->pEnemyGroup->ubNumTroops;
pPatrolGroup->pEnemyGroup->ubNumElites += pGroup->pEnemyGroup->ubNumElites;
pPatrolGroup->pEnemyGroup->ubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins;
pPatrolGroup->ubGroupSize += (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins );
pPatrolGroup->pEnemyGroup->ubNumTanks += pGroup->pEnemyGroup->ubNumTanks;
pPatrolGroup->ubGroupSize += (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks);
#ifdef JA2BETAVERSION
LogStrategicEvent( "%d reinforcements have joined patrol group at sector %c%d (new size: %d)",
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins,
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks,
pPatrolGroup->ubSectorY + 'A' - 1, pPatrolGroup->ubSectorX, pPatrolGroup->ubGroupSize );
#endif
if( pPatrolGroup->ubGroupSize > iMaxEnemyGroupSize )
@@ -2255,11 +2272,17 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5");
pGroup->pEnemyGroup->ubNumElites--;
pPatrolGroup->pEnemyGroup->ubNumElites--;
}
else if( pGroup->pEnemyGroup->ubNumTanks )
{
pGroup->pEnemyGroup->ubNumTanks--;
pPatrolGroup->pEnemyGroup->ubNumTanks--;
}
}
pPatrolGroup->ubGroupSize = iMaxEnemyGroupSize;
Assert( pPatrolGroup->pEnemyGroup->ubNumAdmins +
pPatrolGroup->pEnemyGroup->ubNumTroops +
pPatrolGroup->pEnemyGroup->ubNumElites == iMaxEnemyGroupSize );
pPatrolGroup->pEnemyGroup->ubNumElites +
pPatrolGroup->pEnemyGroup->ubNumTanks == iMaxEnemyGroupSize );
}
RemovePGroup( pGroup );
RecalculatePatrolWeight( i );
@@ -2285,7 +2308,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5");
#ifdef JA2BETAVERSION
LogStrategicEvent( "%d soldiers have arrived to patrol area near sector %c%d",
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins,
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks,
pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX );
#endif
RecalculatePatrolWeight( i );
@@ -2451,7 +2474,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup )
return FALSE;
}
pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY-1 ) ];
ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() )
{
HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY-1 ) );
@@ -2483,7 +2506,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup )
return FALSE;
}
pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY+1 ) ];
ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() )
{
HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY+1 ) );
@@ -2499,7 +2522,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup )
return FALSE;
}
pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX-1, pPlayerGroup->ubSectorY ) ];
ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() )
{
HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX-1, pPlayerGroup->ubSectorY ) );
@@ -2563,7 +2586,7 @@ void CheckEnemyControlledSector( UINT8 ubSectorID )
}
}
}
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites )
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks )
{
//The sector is still controlled, so look around to see if there are any players nearby.
@@ -2718,7 +2741,7 @@ void RecalculateGarrisonWeight( INT32 iGarrisonID )
pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ];
iDesiredPop = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation;
iCurrentPop = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
iCurrentPop = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
iPriority = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bPriority;
//First, remove the previous weight from the applicable field.
@@ -2954,7 +2977,7 @@ void SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoints
#ifdef JA2BETAVERSION
LogStrategicEvent( "%d troops have been reassigned from %c%d to garrison sector %c%d",
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins,
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks,
pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX,
ubDstSectorY + 'A' - 1, ubDstSectorX );
#endif
@@ -3013,7 +3036,7 @@ void SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoints
}
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0 );
ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ iDstGarrisonID ].ubComposition );
pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY );
//Madd: unlimited reinforcements?
@@ -3023,7 +3046,7 @@ void SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoints
pGroup->ubMoveType = ONE_WAY;
gGarrisonGroup[ iDstGarrisonID ].ubPendingGroupID = pGroup->ubGroupID;
ubGroupSize = (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins);
ubGroupSize = (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks);
if( ubNumExtraReinforcements )
{
@@ -3099,13 +3122,13 @@ void SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoints
}
}
pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0 );
ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ iDstGarrisonID ].ubComposition );
RemoveSoldiersFromGarrisonBasedOnComposition( iSrcGarrisonID, pGroup->ubGroupSize );
pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY );
pGroup->ubMoveType = ONE_WAY;
gGarrisonGroup[ iDstGarrisonID ].ubPendingGroupID = pGroup->ubGroupID;
ubGroupSize = (UINT8)( pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins );
ubGroupSize = (UINT8)( pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks );
if( ubNumExtraReinforcements )
{
@@ -3167,7 +3190,7 @@ void SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup )
#ifdef JA2BETAVERSION
LogStrategicEvent( "%d troops have been reassigned from %c%d to reinforce patrol group covering sector %c%d",
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins,
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks,
pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX,
ubDstSectorY + 'A' - 1, ubDstSectorX );
#endif
@@ -3181,7 +3204,7 @@ void SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup )
if( iRandom < giReinforcementPool )
{ //use the pool and send the requested amount from SECTOR P3 (queen's palace)
iReinforcementsApproved = min( iReinforcementsRequested, giReinforcementPool );
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0 );
pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY );
//Madd: unlimited reinforcements?
@@ -3192,7 +3215,7 @@ void SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup )
#ifdef JA2BETAVERSION
LogStrategicEvent( "%d troops have been sent from palace to patrol area near sector %c%d",
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins,
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks,
ubDstSectorY + 'A' - 1, ubDstSectorX );
#endif
@@ -3219,7 +3242,7 @@ void SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup )
iReinforcementsAvailable = ReinforcementsAvailable( iSrcGarrisonID );
//Send the lowest of the two: number requested or number available
iReinforcementsApproved = min( iReinforcementsRequested, iReinforcementsAvailable );
pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0 );
pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY );
gPatrolGroup[ iPatrolID ].ubPendingGroupID = pGroup->ubGroupID;
@@ -3227,7 +3250,7 @@ void SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup )
#ifdef JA2BETAVERSION
LogStrategicEvent( "%d troops have been sent from garrison sector %c%d to patrol area near sector %c%d",
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins,
pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks,
ubSrcSectorY + 'A' - 1, ubSrcSectorX,
ubDstSectorY + 'A' - 1, ubDstSectorX );
#endif
@@ -4284,6 +4307,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
UINT8 stagesector0, stagesector1, stagesector2, stagesector3;
UINT8 assaultsector0, assaultsector1, assaultsector2, assaultsector3;
unsigned ubNumSoldiers;
UINT8 ubNumTanks = 0;
UINT32 grouptroops[4] = {0,0,0,0};
UINT32 groupelites[4] = {0,0,0,0};
UINT32 grouptanks[4] = {0,0,0,0};
switch( usActionCode )
{
@@ -4366,11 +4393,25 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3);
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, ubNumSoldiers, ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, ubNumSoldiers, ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, ubNumSoldiers, ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, ubNumSoldiers, ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel );
// anv: replace one of soldiers with tank
for( UINT8 ubCounter = 0; ubCounter < 4; ubCounter++ )
{
grouptroops[ubCounter] = ubNumSoldiers;
grouptanks[ubCounter] = 0;
if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks )
{
if( Random(10) < gGameOptions.ubDifficultyLevel )
{
grouptroops[ubCounter]--;
grouptanks[ubCounter]++;
}
}
}
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], grouptroops[0] - grouptroops[0] / gGameOptions.ubDifficultyLevel, grouptanks[0] );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], grouptroops[1] - grouptroops[1] / gGameOptions.ubDifficultyLevel, grouptanks[1] );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], grouptroops[2] - grouptroops[2] / gGameOptions.ubDifficultyLevel, grouptanks[2] );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], grouptroops[3] - grouptroops[3] / gGameOptions.ubDifficultyLevel, grouptanks[3] );
if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID )
{
@@ -4416,13 +4457,27 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
}
ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3);
UINT32 grouptroops = ubNumSoldiers;
UINT32 groupelites = 0;
if ( gGameOptions.ubDifficultyLevel > 0 )
groupelites = ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel;
UINT32 totalusedsoldiers = 4 * min(grouptroops + groupelites, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
// anv: replace one of soldiers with tank
for( UINT8 ubCounter = 0; ubCounter < 4; ubCounter++ )
{
grouptroops[ubCounter] = ubNumSoldiers;
grouptanks[ubCounter] = 0;
if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks )
{
if( Random(10) < gGameOptions.ubDifficultyLevel )
{
grouptroops[ubCounter]--;
grouptanks[ubCounter]++;
}
}
groupelites[ubCounter] = 0;
if ( gGameOptions.ubDifficultyLevel > 0 )
groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / gGameOptions.ubDifficultyLevel;
}
//UINT32 totalusedsoldiers = 4 * min(grouptroops + groupelites + ubNumTanks, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
UINT32 totalusedsoldiers = 4 * min(grouptroops[0] + groupelites[0] + grouptanks[0], (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
switch( usActionCode )
{
@@ -4542,10 +4597,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
break;
}
pGroup0 = CreateNewEnemyGroupDepartingFromSector( stagesector0, 0, grouptroops, groupelites );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( stagesector1, 0, grouptroops, groupelites );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( stagesector2, 0, grouptroops, groupelites );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( stagesector3, 0, grouptroops, groupelites );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( stagesector0, 0, grouptroops[0], groupelites[0], grouptanks[0] );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( stagesector1, 0, grouptroops[1], groupelites[1], grouptanks[1] );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( stagesector2, 0, grouptroops[2], groupelites[2], grouptanks[2] );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( stagesector3, 0, grouptroops[3], groupelites[3], grouptanks[3] );
if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID )
{
@@ -4599,6 +4654,13 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3);
// anv: replace one of soldiers with tank
if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks )
{
ubNumSoldiers--;
ubNumTanks++;
}
UINT32 grouptroops = ubNumSoldiers;
UINT32 groupelites = 0;
if ( gGameOptions.ubDifficultyLevel > 0 )
@@ -4614,12 +4676,12 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) )
ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops, groupelites );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops, groupelites );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops, groupelites );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops, groupelites, ubNumTanks );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops, groupelites, ubNumTanks );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops, groupelites, ubNumTanks );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, 0 );
totalusedsoldiers += min(grouptroops + groupelites, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
totalusedsoldiers += min(grouptroops + groupelites + ubNumTanks, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID )
{
@@ -4671,12 +4733,12 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
assaultsector3 = SEC_H9;
}
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, 0 );
totalusedsoldiers += min(grouptroops + groupelites, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
totalusedsoldiers += min(grouptroops + groupelites + ubNumTanks, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID )
{
@@ -4711,12 +4773,12 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) )
ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
totalusedsoldiers += min(grouptroops + groupelites, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
totalusedsoldiers += min(grouptroops + groupelites + ubNumTanks, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID )
{
@@ -4751,10 +4813,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) )
ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
totalusedsoldiers += min(grouptroops + groupelites, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
@@ -4792,10 +4854,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
// If we were to use our usual staging points in Meduna, the Chitzena and Grumm attacks would very likely combine in Grumm Mine. 2 double attacks in the same sector are a 'bit' too much
if ( (SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) )
{
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites, ubNumTanks );
totalusedsoldiers += min(grouptroops + groupelites, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize);
@@ -4839,11 +4901,22 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
ubSectorID = (UINT8)STRATEGIC_INDEX_TO_SECTOR_INFO( sWorldSectorLocationOfFirstBattle );
pSector = &SectorInfo[ ubSectorID ];
ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 4);
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubNumSoldiers, 0 );
// anv: replace one of soldiers with tank
if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks )
{
if( Random( 10 ) < gGameOptions.ubDifficultyLevel )
{
ubNumSoldiers--;
ubNumTanks++;
}
}
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubNumSoldiers, 0, ubNumTanks );
//Madd: unlimited reinforcements?
if ( !gfUnlimitedTroops )
giReinforcementPool -= ubNumSoldiers;
giReinforcementPool -= ( ubNumSoldiers + ubNumTanks );
giReinforcementPool = max( giReinforcementPool, 0 );
@@ -4915,6 +4988,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
unsigned adminsThisSquad = 0;
unsigned troopsThisSquad = 0;
unsigned elitesThisSquad = 0;
unsigned tanksThisSquad = 0;
if (direness < 25) {
adminsThisSquad = soldiersThisSquad * (40 + Random(20)) / 100; // 40-60% of total
troopsThisSquad = soldiersThisSquad - adminsThisSquad; // The rest
@@ -4932,7 +5006,16 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
elitesThisSquad = soldiersThisSquad - troopsThisSquad - adminsThisSquad; // The rest
}
Assert(adminsThisSquad + troopsThisSquad + elitesThisSquad == soldiersThisSquad);
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad );
// anv: replace one of soldiers with tank
if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks )
{
if( Random( 10 * 100 ) < gGameOptions.ubDifficultyLevel * direness )
{
elitesThisSquad--;
tanksThisSquad++;
}
}
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, tanksThisSquad );
if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) {
pGroup0->pEnemyGroup->ubIntention = STAGE;
if (groupCnt > 2) {
@@ -5001,7 +5084,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
unsigned elitesThisSquad = soldiersThisSquad - troopsThisSquad - adminsThisSquad; // The rest
Assert(adminsThisSquad + troopsThisSquad + elitesThisSquad == soldiersThisSquad);
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad );
pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, 0 );
if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) {
pGroup0->pEnemyGroup->ubIntention = STAGE;
if (groupCnt > 2) {
@@ -5018,7 +5101,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
case NPC_ACTION_SEND_SOLDIERS_TO_OMERTA:
ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 6); //6, 12, or 18 based on difficulty.
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubNumSoldiers, (UINT8)(ubNumSoldiers/7) ); //add 1 elite to normal, and 2 for hard
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubNumSoldiers, (UINT8)(ubNumSoldiers/7), 0 ); //add 1 elite to normal, and 2 for hard
ubNumSoldiers = (UINT8)(ubNumSoldiers + ubNumSoldiers / 7);
//Madd: unlimited reinforcements
@@ -5048,8 +5131,18 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
if ( !gfUnlimitedTroops )
giReinforcementPool -= ubNumSoldiers;
// anv: replace one of soldiers with tank
if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks )
{
if( Random( 10 * 100 ) < gGameOptions.ubDifficultyLevel * HighestPlayerProgressPercentage() )
{
ubNumSoldiers--;
ubNumTanks++;
}
}
giReinforcementPool = max( giReinforcementPool, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, 0, ubNumSoldiers );
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, 0, ubNumSoldiers, ubNumTanks );
MoveSAIGroupToSector( &pGroup, ubSectorID, STAGE, REINFORCEMENTS );
// WANNE: This should fix the assertion in UC in the cutscene!
@@ -5313,16 +5406,16 @@ void InvestigateSector( UINT8 ubSectorID )
switch( i )
{
case 0: //NORTH
AddEnemiesToBattle( NULL, INSERTION_CODE_NORTH, ubAdmins[i], ubTroops[i], ubElites[i], TRUE );
AddEnemiesToBattle( NULL, INSERTION_CODE_NORTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE );
break;
case 1: //EAST
AddEnemiesToBattle( NULL, INSERTION_CODE_EAST, ubAdmins[i], ubTroops[i], ubElites[i], TRUE );
AddEnemiesToBattle( NULL, INSERTION_CODE_EAST, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE );
break;
case 2: //SOUTH
AddEnemiesToBattle( NULL, INSERTION_CODE_SOUTH, ubAdmins[i], ubTroops[i], ubElites[i], TRUE );
AddEnemiesToBattle( NULL, INSERTION_CODE_SOUTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE );
break;
case 3: //WEST
AddEnemiesToBattle( NULL, INSERTION_CODE_WEST, ubAdmins[i], ubTroops[i], ubElites[i], TRUE );
AddEnemiesToBattle( NULL, INSERTION_CODE_WEST, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE );
break;
}
}
@@ -5561,7 +5654,7 @@ void RequestHighPriorityGarrisonReinforcements( INT32 iGarrisonID, UINT8 ubSoldi
if( pGroup->ubGroupSize > ubSoldiersRequested && pGroup->ubGroupSize - ubSoldiersRequested >= gubMinEnemyGroupSize )
{ //Split the group, and send to location
GROUP *pNewGroup;
pNewGroup = CreateNewEnemyGroupDepartingFromSector( (UINT8)SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ), 0, 0, 0 );
pNewGroup = CreateNewEnemyGroupDepartingFromSector( (UINT8)SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ), 0, 0, 0, 0 );
//Transfer the troops from group to new group
if( pGroup->pEnemyGroup->ubNumTroops >= ubSoldiersRequested )
{ //All of them are troops, so do it in one shot.
@@ -5604,6 +5697,16 @@ void RequestHighPriorityGarrisonReinforcements( INT32 iGarrisonID, UINT8 ubSoldi
ValidateLargeGroup( pGroup );
ValidateLargeGroup( pNewGroup );
}
else if( pGroup->pEnemyGroup->ubNumTanks )
{
pGroup->pEnemyGroup->ubNumTanks--;
pGroup->ubGroupSize--;
pNewGroup->pEnemyGroup->ubNumTanks++;
pNewGroup->ubGroupSize++;
ubSoldiersRequested--;
ValidateLargeGroup( pGroup );
ValidateLargeGroup( pNewGroup );
}
else
{
AssertMsg( 0, "Strategic AI group transfer error. KM : 0" );
@@ -5632,7 +5735,7 @@ void RequestHighPriorityGarrisonReinforcements( INT32 iGarrisonID, UINT8 ubSoldi
}
else
{ //There are no groups that have enough troops. Send a new force from the palace instead.
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubSoldiersRequested, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubSoldiersRequested, 0, 0 );
pGroup->ubMoveType = ONE_WAY;
pGroup->pEnemyGroup->ubIntention = REINFORCEMENTS;
gGarrisonGroup[ iGarrisonID ].ubPendingGroupID = pGroup->ubGroupID;
@@ -5669,7 +5772,7 @@ void MassFortifyTowns()
for( i = 0; i < giGarrisonArraySize; i++ )
{
pSector = &SectorInfo[ gGarrisonGroup[ i ].ubSectorID ];
ubNumTroops = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
ubNumTroops = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
ubDesiredTroops = (UINT8)gArmyComp[ gGarrisonGroup[ i ].ubComposition ].bDesiredPopulation;
if( ubNumTroops < ubDesiredTroops )
@@ -5708,7 +5811,7 @@ void RenderAIViewerGarrisonInfo( INT32 x, INT32 y, SECTORINFO *pSector )
{
INT32 iDesired, iSurplus;
iDesired = gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation;
iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites - iDesired;
iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites + pSector->ubNumTanks- iDesired;
SetFontForeground( FONT_WHITE );
if( iSurplus >= 0 )
{
@@ -5779,7 +5882,7 @@ BOOLEAN GarrisonCanProvideMinimumReinforcements( INT32 iGarrisonID )
pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ];
iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
iDesired = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation;
if( iAvailable - iDesired >= gubMinEnemyGroupSize )
@@ -5811,7 +5914,7 @@ BOOLEAN GarrisonRequestingMinimumReinforcements( INT32 iGarrisonID )
}
pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ];
iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
iDesired = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation;
if( iDesired - iAvailable >= gubMinEnemyGroupSize )
@@ -5857,8 +5960,8 @@ void EliminateSurplusTroopsForGarrison( GROUP *pGroup, SECTORINFO *pSector )
INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize;
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic8");
iTotal = pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins +
pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins;
iTotal = pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks +
pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks;
if( iTotal <= iMaxEnemyGroupSize )
{
return;
@@ -5944,6 +6047,32 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic8");
iTotal = 0;
}
}
else if( pGroup->pEnemyGroup->ubNumTanks )
{
if( pGroup->pEnemyGroup->ubNumTanks < iTotal )
{
iTotal -= pGroup->pEnemyGroup->ubNumTanks;
pGroup->pEnemyGroup->ubNumTanks = 0;
}
else
{
pGroup->pEnemyGroup->ubNumTanks -= (UINT8)iTotal;
iTotal = 0;
}
}
else if( pSector->ubNumTanks )
{
if( pSector->ubNumTanks < iTotal )
{
iTotal -= pSector->ubNumTanks;
pSector->ubNumTanks = 0;
}
else
{
pSector->ubNumTanks -= (UINT8)iTotal;
iTotal = 0;
}
}
}
}