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
+11
View File
@@ -1386,6 +1386,14 @@ void LoadGameExternalOptions()
gGameExternalOptions.ubAPSharedAmongPassengersAndVehicleMode = iniReader.ReadInteger("Tactical Gameplay Settings","AP_SHARED_AMONG_PASSENGERS_AND_VEHICLE_MODE", 3, 0, 3);
gGameExternalOptions.ubAPSharedAmongPassengersAndVehicleScale = iniReader.ReadInteger("Tactical Gameplay Settings","AP_SHARED_AMONG_PASSENGERS_AND_VEHICLE_SCALE", 100, 0, 200);
gGameExternalOptions.fEnemyTanksCanMoveInTactical = iniReader.ReadBoolean("Tactical Gameplay Settings","ENEMY_TANKS_CAN_MOVE_IN_TACTICAL", FALSE);
gGameExternalOptions.fEnemyTanksDontSpareShells = iniReader.ReadBoolean("Tactical Gameplay Settings","ENEMY_TANKS_DONT_SPARE_SHELLS", TRUE);
gGameExternalOptions.fEnemyTanksBlowObstaclesUp = iniReader.ReadBoolean("Tactical Gameplay Settings","ENEMY_TANKS_BLOW_OBSTACLES_UP", TRUE);
gGameExternalOptions.fEnemyTanksAnyPartVisible = iniReader.ReadBoolean("Tactical Gameplay Settings","ENEMY_TANKS_ANY_PART_VISIBLE", FALSE);
gGameExternalOptions.fEnemiesDontSpareLaunchables = iniReader.ReadBoolean("Tactical Gameplay Settings","ENEMIES_DONT_SPARE_LAUNCHABLES", TRUE);
gGameExternalOptions.fEnemiesBlowObstaclesUp = iniReader.ReadBoolean("Tactical Gameplay Settings","ENEMIES_BLOW_OBSTACLES_UP", FALSE);
// SANDRO - Improved camo applying and camo can be removed
gGameExternalOptions.fCamoRemoving = iniReader.ReadBoolean("Tactical Gameplay Settings", "CAMO_REMOVING", TRUE);
gGameExternalOptions.bCamoKitArea = iniReader.ReadInteger("Tactical Gameplay Settings", "CAMO_KIT_USABLE_AREA", 5, 0, 100);
@@ -2234,6 +2242,9 @@ void LoadGameExternalOptions()
//dnl ch68 090913 Don't allow permanent items removal from sector
gGameExternalOptions.fNoRemoveRandomSectorItems = iniReader.ReadBoolean("Strategic GamePlay Settings", "NO_REMOVE_RANDOM_SECTOR_ITEMS", true, false);
gGameExternalOptions.fArmyUsesTanksInAttacks = iniReader.ReadBoolean("Strategic Gameplay Settings","ARMY_USES_TANKS_IN_ATTACKS", FALSE);
gGameExternalOptions.fArmyUsesTanksInPatrols = iniReader.ReadBoolean("Strategic Gameplay Settings","ARMY_USES_TANKS_IN_PATROLS", FALSE);
// WANNE: This is just a debug setting. Only in debug version we set that property to TRUE.
// In Release version this should always be set to FALSE
// dnl ch51 081009 JA2 Debug Settings
+12
View File
@@ -837,6 +837,18 @@ typedef struct
BOOLEAN fAddPassengerToAnySquad;
BOOLEAN fPassengerLeavingSwitchToNewSquad;
// anv: tanks can move!
BOOLEAN fEnemyTanksCanMoveInTactical;
BOOLEAN fEnemyTanksDontSpareShells;
BOOLEAN fEnemyTanksBlowObstaclesUp;
BOOLEAN fEnemyTanksAnyPartVisible;
BOOLEAN fEnemiesDontSpareLaunchables;
BOOLEAN fEnemiesBlowObstaclesUp;
BOOLEAN fArmyUsesTanksInAttacks;
BOOLEAN fArmyUsesTanksInPatrols;
// WANNE: Always use "prof.dat".
BOOLEAN fUseDifficultyBasedProfDat;
+1 -1
View File
@@ -9259,7 +9259,7 @@ void ValidateStrategicGroups()
for( i = SEC_A1; i < SEC_P16; i++ )
{
pSector = &SectorInfo[ i ];
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites > gGameExternalOptions.iMaxEnemyGroupSize )
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks > gGameExternalOptions.iMaxEnemyGroupSize )
{
}
//militia
+28 -20
View File
@@ -161,7 +161,7 @@ void ViewCreaturesCallback( GUI_BUTTON *btn, INT32 reason );
void ExtractAndUpdatePopulations();
void PrintEnemyPopTable();
void PrintEnemiesKilledTable();
UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites );
UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites, UINT8 ubTanks );
void BlitGroupIcon( UINT8 ubIconType, UINT8 ubIconColor, UINT32 uiX, UINT32 uiY, HVOBJECT hVObject );
void PrintDetailedEnemiesInSectorInfo( INT32 iScreenX, INT32 iScreenY, UINT8 ubSectorX, UINT8 ubSectorY );
@@ -188,6 +188,7 @@ UINT16 gusDkBlue;
INT16 gsAINumAdmins = -1;
INT16 gsAINumTroops = -1;
INT16 gsAINumElites = -1;
INT16 gsAINumTanks = -1;
INT16 gsAINumCreatures = -1;
BOOLEAN gfOverrideSector = FALSE;
@@ -488,11 +489,11 @@ void RenderStationaryGroups()
ubGroupSize = pSector->ubNumberOfCivsAtLevel[0] + pSector->ubNumberOfCivsAtLevel[1] + pSector->ubNumberOfCivsAtLevel[2];
}
else
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites )
if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks )
{
// show enemies
ubIconColor = ChooseEnemyIconColor( pSector->ubNumAdmins, pSector->ubNumTroops, pSector->ubNumElites );
ubGroupSize = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
ubIconColor = ChooseEnemyIconColor( pSector->ubNumAdmins, pSector->ubNumTroops, pSector->ubNumElites, pSector->ubNumTanks );
ubGroupSize = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
if( pSector->ubGarrisonID != NO_GARRISON )
{
if( gGarrisonGroup[ pSector->ubGarrisonID ].ubPendingGroupID )
@@ -536,7 +537,7 @@ void RenderMovingGroupsAndMercs()
GROUP *pGroup;
HVOBJECT hVObject;
INT32 x, y;
UINT8 ubNumTroops, ubNumAdmins, ubNumElites;
UINT8 ubNumTroops, ubNumAdmins, ubNumElites, ubNumTanks;
float ratio;
INT32 minX, maxX, minY, maxY;
UINT8 ubIconType;
@@ -591,12 +592,13 @@ void RenderMovingGroupsAndMercs()
ubNumAdmins = pGroup->pEnemyGroup->ubNumAdmins;//+ pGroup->pEnemyGroup->ubAdminsInBattle;
ubNumTroops = pGroup->pEnemyGroup->ubNumTroops;//+ pGroup->pEnemyGroup->ubTroopsInBattle;
ubNumElites = pGroup->pEnemyGroup->ubNumElites;// + pGroup->pEnemyGroup->ubElitesInBattle;
ubNumTanks = pGroup->pEnemyGroup->ubNumTanks;
// must have one of the three, already checked groupsize!
Assert( ubNumAdmins || ubNumTroops || ubNumElites );
Assert( ubNumAdmins || ubNumTroops || ubNumElites || ubNumTanks );
//determine icon color
ubIconColor = ChooseEnemyIconColor( ubNumAdmins, ubNumTroops, ubNumElites );
ubIconColor = ChooseEnemyIconColor( ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
// must have a valid intention
Assert( pGroup->pEnemyGroup->ubIntention < NUM_ENEMY_INTENTIONS );
@@ -721,7 +723,7 @@ void RenderInfoInSector()
{
SECTORINFO *pSector;
GROUP *pGroup;
UINT8 ubNumAdmins=0, ubNumTroops=0, ubNumElites=0, ubAdminsInBattle=0, ubTroopsInBattle=0, ubElitesInBattle=0, ubNumGroups=0;
UINT8 ubNumAdmins=0, ubNumTroops=0, ubNumElites=0, ubNumTanks=0, ubAdminsInBattle=0, ubTroopsInBattle=0, ubElitesInBattle=0, ubTanksInBattle=0, ubNumGroups=0;
pSector = &SectorInfo[ SECTOR( ubSectorX, ubSectorY ) ];
@@ -734,9 +736,11 @@ void RenderInfoInSector()
ubNumTroops += pGroup->pEnemyGroup->ubNumTroops;
ubNumElites += pGroup->pEnemyGroup->ubNumElites;
ubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins;
ubNumTanks += pGroup->pEnemyGroup->ubNumTanks;
ubTroopsInBattle += pGroup->pEnemyGroup->ubTroopsInBattle;
ubElitesInBattle += pGroup->pEnemyGroup->ubElitesInBattle;
ubAdminsInBattle += pGroup->pEnemyGroup->ubAdminsInBattle;
ubTanksInBattle += pGroup->pEnemyGroup->ubTanksInBattle;
ubNumGroups++;
}
pGroup = pGroup->next;
@@ -753,15 +757,17 @@ void RenderInfoInSector()
pSector->ubNumberOfCivsAtLevel[0], pSector->ubNumberOfCivsAtLevel[1], pSector->ubNumberOfCivsAtLevel[2] );
yp += 10;
SetFontForeground( FONT_ORANGE );
mprintf( 280, yp, L"Garrison: (%d:%d Admins, %d:%d Troops, %d:%d Elites)",
mprintf( 280, yp, L"Garrison: (%d:%d Admins, %d:%d Troops, %d:%d Elites, %d:%d Tanks)",
pSector->ubAdminsInBattle, pSector->ubNumAdmins,
pSector->ubTroopsInBattle, pSector->ubNumTroops,
pSector->ubElitesInBattle, pSector->ubNumElites );
pSector->ubElitesInBattle, pSector->ubNumElites,
pSector->ubTanksInBattle, pSector->ubNumTanks );
yp += 10;
mprintf( 280, yp, L"%d Groups: (%d:%d Admins, %d:%d Troops, %d:%d Elites)", ubNumGroups,
mprintf( 280, yp, L"%d Groups: (%d:%d Admins, %d:%d Troops, %d:%d Elites, %d:%d Tanks)", ubNumGroups,
ubAdminsInBattle, ubNumAdmins,
ubTroopsInBattle, ubNumTroops,
ubElitesInBattle, ubNumElites );
ubElitesInBattle, ubNumElites,
ubTanksInBattle, ubNumTanks );
yp += 10;
SetFontForeground( FONT_WHITE );
@@ -1266,7 +1272,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason )
gfRenderViewer = TRUE;
if( gsSelSectorY > 1 )
{
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-16, 0, 11, 5 );
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-16, 0, 11, 5, 0 );
pGroup->ubNextX = (UINT8)gsSelSectorX;
pGroup->ubNextY = (UINT8)gsSelSectorY;
pGroup->uiTraverseTime = 10;
@@ -1278,7 +1284,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason )
}
if( gsSelSectorY < 16 )
{
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+16, 0, 8, 8 );
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+16, 0, 8, 8, 0 );
pGroup->ubNextX = (UINT8)gsSelSectorX;
pGroup->ubNextY = (UINT8)gsSelSectorY;
pGroup->uiTraverseTime = 12;
@@ -1290,7 +1296,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason )
}
if( gsSelSectorX > 1 )
{
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-1, 0, 11, 5 );
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-1, 0, 11, 5, 0 );
pGroup->ubNextX = (UINT8)gsSelSectorX;
pGroup->ubNextY = (UINT8)gsSelSectorY;
pGroup->uiTraverseTime = 11;
@@ -1302,7 +1308,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason )
}
if( gsSelSectorX < 16 )
{
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, 0, 14, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, 0, 14, 0, 0 );
pGroup->ubNextX = (UINT8)gsSelSectorX;
pGroup->ubNextY = (UINT8)gsSelSectorY;
pGroup->uiTraverseTime = 13;
@@ -1557,6 +1563,7 @@ void PrintEnemyPopTable()
usEnemyPopTable[ ENEMY_RANK_ADMIN ][ ENEMY_TYPE_GARRISON ] += pSector->ubNumAdmins;
usEnemyPopTable[ ENEMY_RANK_TROOP ][ ENEMY_TYPE_GARRISON ] += pSector->ubNumTroops;
usEnemyPopTable[ ENEMY_RANK_ELITE ][ ENEMY_TYPE_GARRISON ] += pSector->ubNumElites;
//usEnemyPopTable[ ENEMY_RANK_TANK ][ ENEMY_TYPE_GARRISON ] += pSector->ubNumTanks;
}
// count moving enemies
@@ -1583,6 +1590,7 @@ void PrintEnemyPopTable()
usEnemyPopTable[ ENEMY_RANK_ADMIN ][ ubEnemyType ] += pGroup->pEnemyGroup->ubNumAdmins;
usEnemyPopTable[ ENEMY_RANK_TROOP ][ ubEnemyType ] += pGroup->pEnemyGroup->ubNumTroops;
usEnemyPopTable[ ENEMY_RANK_ELITE ][ ubEnemyType ] += pGroup->pEnemyGroup->ubNumElites;
//usEnemyPopTable[ ENEMY_RANK_TANK ][ ubEnemyType ] += pGroup->pEnemyGroup->ubNumTanks;
}
pGroup = pGroup->next;
@@ -1823,7 +1831,7 @@ void PrintEnemiesKilledTable()
UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites )
UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites, UINT8 ubTanks )
{
UINT8 ubIconColor;
@@ -1834,7 +1842,7 @@ UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites )
// Orange Mixed, no elites (Admins + Troops)
// Burgundy Mixed, with elites (Elites + (Admins OR Troops))
Assert( ubAdmins || ubTroops || ubElites );
Assert( ubAdmins || ubTroops || ubElites ||ubTanks );
if ( ubElites )
{
@@ -1895,8 +1903,8 @@ void PrintDetailedEnemiesInSectorInfo( INT32 iScreenX, INT32 iScreenY, UINT8 ubS
// handle garrisoned enemies
if( pSector->ubGarrisonID != NO_GARRISON )
{
iDesired = gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation;
iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites - iDesired;
iDesired = gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation;
iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites + pSector->ubNumTanks - iDesired;
SetFontForeground( FONT_WHITE );
swprintf( wString, L"Garrison #%d: %d desired, ", pSector->ubGarrisonID, iDesired );
+2
View File
@@ -6839,6 +6839,7 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
pSectorInfo->ubNumTroops = min(255, pSectorInfo->ubNumTroops + prisonersregular);
pSectorInfo->ubNumElites = min(255, pSectorInfo->ubNumElites + prisonerselite + prisonersofficer);
pSectorInfo->ubNumAdmins = min(255, pSectorInfo->ubNumAdmins + prisonersadmin);
pSectorInfo->ubNumTanks = min(255, pSectorInfo->ubNumTanks );
// all prisoners are free, reduce count!
DeleteAllPrisoners(pSectorInfo);
@@ -6892,6 +6893,7 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
pSectorInfo->ubNumTroops = min( 512, pSectorInfo->ubNumTroops + escapedregulars );
pSectorInfo->ubNumElites = min( 512, pSectorInfo->ubNumElites + escapedelites + escapedofficers );
pSectorInfo->ubNumAdmins = min( 512, pSectorInfo->ubNumAdmins + escapedadmins );
pSectorInfo->ubNumTanks = min( 512, pSectorInfo->ubNumTanks );
// reduce prisoner count!
ChangeNumberOfPrisoners( pSectorInfo, -escapedofficers, -escapedelites, -escapedregulars, -escapedadmins, sMapX, sMapY );
+54 -9
View File
@@ -166,7 +166,7 @@ typedef struct AUTORESOLVE_STRUCT
UINT8 ubEnemyLeadership;
UINT8 ubPlayerLeadership;
UINT8 ubMercs, ubCivs, ubEnemies;
UINT8 ubAdmins, ubTroops, ubElites;
UINT8 ubAdmins, ubTroops, ubElites, ubTanks;
UINT8 ubYMCreatures, ubYFCreatures, ubAMCreatures, ubAFCreatures;
UINT8 ubAliveMercs, ubAliveCivs, ubAliveEnemies;
UINT8 ubMercCols, ubMercRows;
@@ -226,10 +226,11 @@ typedef struct AUTORESOLVE_STRUCT
#define CELL_ASSIGNED 0x00080000
#define CELL_EPC 0x00100000
#define CELL_ROBOT 0x00200000
#define CELL_TANK 0x00400000
//Combined flags
#define CELL_PLAYER ( CELL_MERC | CELL_MILITIA )
#define CELL_ENEMY ( CELL_ELITE | CELL_TROOP | CELL_ADMIN )
#define CELL_ENEMY ( CELL_ELITE | CELL_TROOP | CELL_ADMIN | CELL_TANK )
#define CELL_CREATURE ( CELL_AF_CREATURE | CELL_AM_CREATURE | CELL_YF_CREATURE | CELL_YM_CREATURE )
#define CELL_FEMALECREATURE ( CELL_AF_CREATURE | CELL_YF_CREATURE )
#define CELL_MALECREATURE ( CELL_AM_CREATURE | CELL_YM_CREATURE )
@@ -441,7 +442,7 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY )
// we must process the enemies killed right here & give out loyalty bonuses as if the battle had been fought & won
if( !gpAR )
{
GetNumberOfEnemiesInSector( ubSectorX, ubSectorY, &ubNumEnemies[ 0 ], &ubNumEnemies[ 1 ], &ubNumEnemies[ 2 ] );
GetNumberOfEnemiesInSector( ubSectorX, ubSectorY, &ubNumEnemies[ 0 ], &ubNumEnemies[ 1 ], &ubNumEnemies[ 2 ], &ubNumEnemies[ 3 ] );
for ( ubRankIndex = 0; ubRankIndex < NUM_ENEMY_RANKS; ubRankIndex++ )
{
@@ -461,6 +462,7 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY )
pSector->ubNumTroops = 0;
pSector->ubNumElites = 0;
pSector->ubNumAdmins = 0;
pSector->ubNumTanks = 0;
pSector->ubNumCreatures = 0;
pSector->bLastKnownEnemies = 0;
//Remove the mobile forces here, but only if battle is over.
@@ -749,9 +751,9 @@ void AssociateEnemiesWithStrategicGroups()
{
SECTORINFO *pSector;
GROUP *pGroup;
UINT8 ubNumAdmins, ubNumTroops, ubNumElites;
UINT8 ubISNumAdmins, ubISNumTroops, ubISNumElites;
UINT8 ubNumElitesInGroup, ubNumTroopsInGroup, ubNumAdminsInGroup;
UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks;
UINT8 ubISNumAdmins, ubISNumTroops, ubISNumElites, ubISNumTanks;
UINT8 ubNumElitesInGroup, ubNumTroopsInGroup, ubNumAdminsInGroup, ubNumTanksInGroup;
INT32 i;
UINT8 pSectors[4];
UINT8 ubDirAmount;
@@ -766,6 +768,7 @@ void AssociateEnemiesWithStrategicGroups()
ubNumAdmins = pSector->ubNumAdmins;
ubNumTroops = pSector->ubNumTroops;
ubNumElites = pSector->ubNumElites;
ubNumTanks = pSector->ubNumTanks;
//Now go through our enemies in the autoresolve array, and assign the ubGroupID to the soldier
//Stationary groups have a group ID of 0
@@ -789,13 +792,20 @@ void AssociateEnemiesWithStrategicGroups()
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
ubNumAdmins--;
}
else if( gpEnemies[ i ].uiFlags & CELL_TANK && ubNumTanks )
{
gpEnemies[ i ].pSoldier->ubGroupID = 0;
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
ubNumTanks--;
}
}
ubNumAdmins = gpAR->ubAdmins - pSector->ubNumAdmins;
ubNumTroops = gpAR->ubTroops - pSector->ubNumTroops;
ubNumElites = gpAR->ubElites - pSector->ubNumElites;
ubNumTanks = gpAR->ubTanks - pSector->ubNumTanks;
if( !ubNumElites && !ubNumTroops && !ubNumAdmins )
if( !ubNumElites && !ubNumTroops && !ubNumAdmins && !ubNumTanks )
{ //All troops accounted for.
return;
}
@@ -809,6 +819,7 @@ void AssociateEnemiesWithStrategicGroups()
ubNumElitesInGroup = pGroup->pEnemyGroup->ubNumElites;
ubNumTroopsInGroup = pGroup->pEnemyGroup->ubNumTroops;
ubNumAdminsInGroup = pGroup->pEnemyGroup->ubNumAdmins;
ubNumTanksInGroup = pGroup->pEnemyGroup->ubNumTanks;
for( i = 0; i < gpAR->ubEnemies; i++ )
{
if( !(gpEnemies[ i ].uiFlags & CELL_ASSIGNED) )
@@ -834,6 +845,13 @@ void AssociateEnemiesWithStrategicGroups()
ubNumAdmins--;
ubNumAdminsInGroup--;
}
else if( ubNumTanks && ubNumTanksInGroup )
{
gpEnemies[ i ].pSoldier->ubGroupID = pGroup->ubGroupID;
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
ubNumTanks--;
ubNumTanksInGroup--;
}
}
}
}
@@ -850,6 +868,7 @@ void AssociateEnemiesWithStrategicGroups()
ubNumElitesInGroup = pGroup->pEnemyGroup->ubNumElites;
ubNumTroopsInGroup = pGroup->pEnemyGroup->ubNumTroops;
ubNumAdminsInGroup = pGroup->pEnemyGroup->ubNumAdmins;
ubNumTanksInGroup = pGroup->pEnemyGroup->ubNumTanks;
for( i = 0; i < gpAR->ubEnemies; i++ )
{
if( !(gpEnemies[ i ].uiFlags & CELL_ASSIGNED) )
@@ -875,6 +894,13 @@ void AssociateEnemiesWithStrategicGroups()
ubNumAdmins--;
ubNumAdminsInGroup--;
}
else if( ubNumTanks && ubNumTanksInGroup )
{
gpEnemies[ i ].pSoldier->ubGroupID = pGroup->ubGroupID;
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
ubNumTanks--;
ubNumTanksInGroup--;
}
}
}
}
@@ -892,10 +918,11 @@ void AssociateEnemiesWithStrategicGroups()
ubISNumAdmins = pSector->ubNumAdmins;
ubISNumTroops = pSector->ubNumTroops;
ubISNumElites = pSector->ubNumElites;
ubISNumTanks = pSector->ubNumTanks;
for( i = 0; i < gpAR->ubEnemies; i++ )
{
if( ubISNumAdmins + ubISNumTroops + ubISNumElites <= gubReinforcementMinEnemyStaticGroupSize ) break;
if( ubISNumAdmins + ubISNumTroops + ubISNumElites + ubISNumTanks <= gubReinforcementMinEnemyStaticGroupSize ) break;
if( !(gpEnemies[ i ].uiFlags & CELL_ASSIGNED) )
{
@@ -926,6 +953,15 @@ void AssociateEnemiesWithStrategicGroups()
ubISNumAdmins--;
ubNumAdmins--;
}
else if( gpEnemies[ i ].uiFlags & CELL_TANK && ubISNumTanks && ubNumTanks )
{
gpEnemies[ i ].pSoldier->ubGroupID = 0;
gpEnemies[ i ].uiFlags |= CELL_ASSIGNED;
gpEnemies[ i ].pSoldier->sSectorX = SECTORX( pSectors[ ubCurrSI ] );
gpEnemies[ i ].pSoldier->sSectorY = SECTORY( pSectors[ ubCurrSI ] );
ubISNumTanks--;
ubNumTanks--;
}
}
}
}
@@ -2480,6 +2516,15 @@ void CreateAutoResolveInterface()
gpEnemies[index].pSoldier->sSectorY = gpAR->ubSectorY;
swprintf( gpEnemies[index].pSoldier->name, gpStrategicString[ STR_AR_ADMINISTRATOR_NAME ] );
}
for( i = 0; i < gpAR->ubTanks; i++, index++ )
{
gpEnemies[index].pSoldier = TacticalCreateEnemyTank();
gpEnemies[index].uiVObjectID = gpAR->iFaces;
gpEnemies[index].usIndex = ELITE_FACE;
gpEnemies[index].pSoldier->sSectorX = gpAR->ubSectorX;
gpEnemies[index].pSoldier->sSectorY = gpAR->ubSectorY;
//swprintf( gpEnemies[index].pSoldier->name, gpStrategicString[ STR_AR_ADMINISTRATOR_NAME ] );
}
AssociateEnemiesWithStrategicGroups();
}
else
@@ -3141,7 +3186,7 @@ void CalculateAutoResolveInfo()
{
// GetNumberOfEnemiesInSector( gpAR->ubSectorX, gpAR->ubSectorY,
GetNumberOfEnemiesInFiveSectors( gpAR->ubSectorX, gpAR->ubSectorY,
&gpAR->ubAdmins, &gpAR->ubTroops, &gpAR->ubElites );
&gpAR->ubAdmins, &gpAR->ubTroops, &gpAR->ubElites, &gpAR->ubTanks );
gpAR->ubEnemies = (UINT8)min( gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubElites, MAX_AR_TEAM_SIZE );
}
else
+6 -6
View File
@@ -337,25 +337,25 @@ void GeneratePatrolGroups()
GROUP *pGroup;
UINT8 ubNumTroops;
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_C7, 0, ubNumTroops, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_C7, 0, ubNumTroops, 0, 0 );
pGroup->ubTransportationMask = CAR;
AddWaypointToPGroup( pGroup, 8, 3 ); //C8
AddWaypointToPGroup( pGroup, 7, 3 ); //C7
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_D9, 0, ubNumTroops, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_D9, 0, ubNumTroops, 0, 0 );
AddWaypointToPGroup( pGroup, 9, 5 ); //E9
AddWaypointToPGroup( pGroup, 9, 4 ); //D9
pGroup->ubTransportationMask = TRUCK;
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_B9, 0, ubNumTroops, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_B9, 0, ubNumTroops, 0, 0 );
AddWaypointToPGroup( pGroup, 12, 2 ); //B12
AddWaypointToPGroup( pGroup, 9, 2 ); //B9
pGroup->ubTransportationMask = FOOT;
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_A14, 0, ubNumTroops, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_A14, 0, ubNumTroops, 0, 0 );
pGroup->ubMoveType = ENDTOEND_FORWARDS;
AddWaypointToPGroup( pGroup, 13, 1 ); //A13
AddWaypointToPGroup( pGroup, 15, 1 ); //A15
@@ -366,13 +366,13 @@ void GeneratePatrolGroups()
pGroup->ubTransportationMask = TRACKED;
ubNumTroops = (UINT8)(5 + gGameOptions.ubDifficultyLevel * 2 + Random( 4 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N6, 0, ubNumTroops, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N6, 0, ubNumTroops, 0, 0 );
AddWaypointToPGroup( pGroup, 9, 14 ); //N9
AddWaypointToPGroup( pGroup, 6, 14 ); //N6
pGroup->ubTransportationMask = CAR;
ubNumTroops = (UINT8)(5 + gGameOptions.ubDifficultyLevel * 2 + Random( 4 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N10, 0, ubNumTroops, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N10, 0, ubNumTroops, 0, 0 );
AddWaypointToPGroup( pGroup, 10, 11 ); //K10
AddWaypointToPGroup( pGroup, 10, 14 ); //N10
pGroup->ubTransportationMask = CAR;
+8 -2
View File
@@ -500,7 +500,10 @@ typedef struct SECTORINFO
UINT32 uiTimeAIArtillerywasOrdered; // Flugente: updated every time an artillery strike is ordered from the militia
INT8 bPadding[ 29 ];
UINT8 ubNumTanks;
UINT8 ubTanksInBattle;
INT8 bPadding[ 27 ];
}SECTORINFO;
@@ -539,7 +542,10 @@ typedef struct UNDERGROUND_SECTORINFO
UINT8 uiNumberOfPrisonersOfWar[PRISONER_MAX];
INT8 bPadding[32];
UINT8 ubNumTanks;
UINT8 ubTanksInBattle;
INT8 bPadding[30];
//no padding left!
}UNDERGROUND_SECTORINFO;
+71 -50
View File
@@ -123,16 +123,16 @@ JA25_SECTOR_AI_MANAGER gJa25StrategicAi;
BOOLEAN AddEnemiesToInitialSectorH7();
UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites );
void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites, UINT8 *pubNumTanks );
void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
void InitJa25InitialEnemiesInSector();
void InitJa25UnderGroundSectors();
void InitNumberOfEnemiesInAboveGroundSectors( );
void InitNumberOfEnemiesInUnderGroundSectors( );
void SetNumberOfJa25BloodCatsInSector( INT32 iSectorID, INT8 bNumBloodCats, INT8 bBloodCatPlacements );
void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
void ResetJa25SectorProbabilities();
BOOLEAN InitJa25StrategicSectorAI( BOOLEAN fReset );
@@ -152,8 +152,8 @@ void FixEnemyCounterInSectorBug();
void AddEnemiesToFirstTunnelSector();
void AddEnemiesToSecondTunnelSector();
UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites );
UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites );
UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks );
UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks );
void RemoveAllEnemySoldierInitListLinks();
INT16 GetGridNoEnemyWillSeekWhenAttacking( INT8 bSaiSector );
void SetH11NumEnemiesInSector();
@@ -175,7 +175,7 @@ BOOLEAN Ja25BetaDateToInvalidateExe();
UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites )
UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites, UINT8 *pNumTanks )
{
SECTORINFO *pSector;
@@ -187,6 +187,7 @@ UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSec
*pNumAdmins = pSector->ubNumAdmins;
*pNumTroops = pSector->ubNumTroops;
*pNumElites = pSector->ubNumElites;
*pNumTanks = pSector->ubNumTanks;
}
else
{
@@ -198,6 +199,7 @@ UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSec
*pNumAdmins = pSector->ubNumAdmins;
*pNumTroops = pSector->ubNumTroops;
*pNumElites = pSector->ubNumElites;
*pNumTanks = pSector->ubNumTanks;
}
}
@@ -278,15 +280,17 @@ BOOLEAN AddEnemiesToInitialSectorH7()
UINT8 ubNumAdmins;
UINT8 ubNumTroops;
UINT8 ubNumElites;
UINT8 ubNumTanks;
UINT8 ubNumRemovedAdmins=0;
UINT8 ubNumRemovedTroops=0;
UINT8 ubNumRemovedElites=0;
UINT8 ubNumRemovedTanks=0;
ubSector = SECTOR( JA2_5_START_SECTOR_X, JA2_5_START_SECTOR_Y );
//Get the number of enemies in the guard post sector
GetNumberOfJA25EnemiesInSector( 8, MAP_ROW_H, 0, &ubNumAdmins, &ubNumTroops, &ubNumElites );
GetNumberOfJA25EnemiesInSector( 8, MAP_ROW_H, 0, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
//determine the #of enemies to travel to the initial heli sector
@@ -299,13 +303,16 @@ BOOLEAN AddEnemiesToInitialSectorH7()
if( ubNumElites > 1 )
ubNumRemovedElites = ubNumElites / 3 + + Random( 3 );
if( ubNumTanks > 1 )
ubNumRemovedTanks = ubNumTanks / 3 + + Random( 3 );
//deduct the # that are moving from the # in the guard post sector
// SetNumberJa25EnemiesInSurfaceSector( SEC_H8, (UINT8)(ubNumAdmins-ubNumRemovedAdmins), (UINT8)(ubNumTroops-ubNumRemovedTroops), (UINT8)(ubNumElites-ubNumRemovedElites) );
SetNumberJa25EnemiesInSector( 8, MAP_ROW_H, 0, (UINT8)(ubNumAdmins-ubNumRemovedAdmins), (UINT8)(ubNumTroops-ubNumRemovedTroops), (UINT8)(ubNumElites-ubNumRemovedElites) );
SetNumberJa25EnemiesInSector( 8, MAP_ROW_H, 0, (UINT8)(ubNumAdmins-ubNumRemovedAdmins), (UINT8)(ubNumTroops-ubNumRemovedTroops), (UINT8)(ubNumElites-ubNumRemovedElites), (UINT8)(ubNumTanks-ubNumRemovedTanks) );
uiWorldMin = GetWorldTotalMin();
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, ubNumRemovedAdmins, ubNumRemovedTroops, ubNumRemovedElites );
pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, ubNumRemovedAdmins, ubNumRemovedTroops, ubNumRemovedElites, ubNumRemovedTanks );
if( pGroup == NULL )
{
@@ -396,24 +403,24 @@ void InitJa25UnderGroundSectors()
*/
}
void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites )
void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks )
{
//if its a ground level
if( bSectorZ == 0 )
{
SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//its an underground level
else
{
SetNumberJa25EnemiesInUnderGroundSector( sSectorX, sSectorY, bSectorZ, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInUnderGroundSector( sSectorX, sSectorY, bSectorZ, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
}
void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites )
void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks )
{
SECTORINFO *pSector;
@@ -421,6 +428,7 @@ void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UI
pSector->ubNumAdmins = ubNumAdmins;
pSector->ubNumTroops = ubNumTroops;
pSector->ubNumElites = ubNumElites;
pSector->ubNumTanks = ubNumTanks;
}
void SetNumberOfJa25BloodCatsInSector( INT32 iSectorID, INT8 bNumBloodCats, INT8 bBloodCatPlacements )
@@ -433,7 +441,7 @@ void SetNumberOfJa25BloodCatsInSector( INT32 iSectorID, INT8 bNumBloodCats, INT8
pSector->bBloodCatPlacements = bBloodCatPlacements;
}
void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites )
void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks )
{
UNDERGROUND_SECTORINFO *pSector=NULL;
@@ -444,6 +452,7 @@ void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, IN
pSector->ubNumAdmins = ubNumAdmins;
pSector->ubNumTroops = ubNumTroops;
pSector->ubNumElites = ubNumElites;
pSector->ubNumTanks = ubNumTanks;
}
void InitNumberOfEnemiesInAboveGroundSectors( )
@@ -451,6 +460,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks=0;
//H7
{
@@ -477,7 +487,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
ubNumElites = 0 + Random( 0 );
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_H7, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_H7, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
@@ -508,7 +518,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_H8, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_H8, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//Guard Post
@@ -538,7 +548,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_H9, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_H9, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
// SEC_H10:
@@ -567,7 +577,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_H10, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_H10, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//SEC_H11
@@ -600,7 +610,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_I9, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_I9, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//First part of town
@@ -630,7 +640,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_I10, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_I10, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//Second part of town
@@ -660,7 +670,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_I11, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_I11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//SEC_I12:
@@ -689,7 +699,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_I12, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_I12, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//Abandoned mine
@@ -719,7 +729,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_I13, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_I13, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
// SEC_J11:
@@ -748,7 +758,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_J11, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_J11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
// SEC_J12:
@@ -777,7 +787,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_J12, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_J12, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//Power Generator, Ground Level
@@ -807,7 +817,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_J13, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_J13, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
//Complex, Ground Level
@@ -837,7 +847,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( )
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_K15, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_K15, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
}
@@ -846,6 +856,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks;
//Mine Sector Level 1
switch( gGameOptions.ubDifficultyLevel )
@@ -866,7 +877,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 0 + Random( 0 );
break;
}
SetNumberJa25EnemiesInSector( 13, 9, 1, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 13, 9, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
//Power Generator Level 1
@@ -888,7 +899,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 0 + Random( 0 );
break;
}
SetNumberJa25EnemiesInSector( 13, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 13, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
//Tunnel First Part, Level 1
@@ -910,7 +921,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 0 + Random( 0 );
break;
}
SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
//Tunnel Second Part, Level 1
@@ -932,7 +943,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 0 + Random( 0 );
break;
}
SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
@@ -955,7 +966,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 6 + Random( 4 );
break;
}
SetNumberJa25EnemiesInSector( 15, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 15, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
//Complex, Level 2, K15
@@ -977,7 +988,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 10 + Random( 2 );
break;
}
SetNumberJa25EnemiesInSector( 15, 11, 2, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 15, 11, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
//Complex, Level 2, L15
@@ -999,7 +1010,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 14 + Random( 2 );
break;
}
SetNumberJa25EnemiesInSector( 15, 12, 2, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 15, 12, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
//Complex, Level 3, L15
@@ -1021,7 +1032,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( )
ubNumElites = 15 + Random( 0 );
break;
}
SetNumberJa25EnemiesInSector( 15, 12, 3, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 15, 12, 3, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
void InitJa25SaveStruct()
@@ -1270,7 +1281,7 @@ void HandleAddingEnemiesToTunnelMaps()
else if( AreAnyPlayerMercsStillInSector( 14, 10, 1 ) &&
!AreAnyPlayerMercsStillInSector( 14, 11, 1 ) )
{
ubNumEnemies = NumEnemiesToAttackFirstTunnelSector( NULL, NULL, NULL );
ubNumEnemies = NumEnemiesToAttackFirstTunnelSector( NULL, NULL, NULL, NULL );
//Add enemies to the first sector
HandleAddEnemiesToSectorPlayerIsntIn( JA25_J14_1, ubNumEnemies );
@@ -1284,7 +1295,7 @@ void HandleAddingEnemiesToTunnelMaps()
//else if the player is in the second sector
else if( AreAnyPlayerMercsStillInSector( 14, 11, 1 ) )
{
ubNumEnemies = NumEnemiesToAttackSecondTunnelSector( NULL, NULL, NULL );
ubNumEnemies = NumEnemiesToAttackSecondTunnelSector( NULL, NULL, NULL, NULL );
//Add enemies to the first sector
HandleAddEnemiesToSectorPlayerIsntIn( JA25_K14_1, ubNumEnemies );
@@ -1313,10 +1324,11 @@ void AddEnemiesToFirstTunnelSector()
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks=0;
NumEnemiesToAttackFirstTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites );
NumEnemiesToAttackFirstTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
void AddEnemiesToSecondTunnelSector()
@@ -1324,16 +1336,18 @@ void AddEnemiesToSecondTunnelSector()
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks=0;
NumEnemiesToAttackSecondTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites );
SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites );
NumEnemiesToAttackSecondTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites )
UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks )
{
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks=0;
//if the player blew up the fan, add a ton of enemies to the sector
//1st Tunnel Sector
@@ -1365,14 +1379,18 @@ UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8
if( pElites )
*pElites = ubNumElites;
return( ubNumAdmins + ubNumTroops + ubNumElites );
if( pTanks )
*pTanks = ubNumTanks;
return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks );
}
UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites )
UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks )
{
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks=0;
//if the player blew up the fan, add a ton of enemies to the sector
//1st Tunnel Sector
@@ -1402,8 +1420,10 @@ UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT
*pTroops = ubNumTroops;
if( pElites )
*pElites = ubNumElites;
if( pTanks )
*pTanks = ubNumTanks;
return( ubNumAdmins + ubNumTroops + ubNumElites );
return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks );
}
@@ -2166,7 +2186,7 @@ BOOLEAN HandleAddEnemiesToSectorPlayerIsntIn( INT16 sSaiSector, UINT8 ubNumEnemi
gubEnemyEncounterCode = ENEMY_INVASION_CODE;
}
SetNumberJa25EnemiesInSector( sSectorX, sSectorY, bSectorZ, 0, ubNumEnemies, 0 );
SetNumberJa25EnemiesInSector( sSectorX, sSectorY, bSectorZ, 0, ubNumEnemies, 0, 0 );
SetThisSectorAsEnemyControlled( sSectorX, sSectorY, bSectorZ, FALSE );
@@ -2211,7 +2231,7 @@ if ( gGameUBOptions.pJA2UB == TRUE )
if( gJa25AiSectorStruct[ sSaiSector ].bSectorZ == 0 )
{
pGroup = CreateNewEnemyGroupDepartingFromSector( sSector, 0, ubNumEnemies, 0 );
pGroup = CreateNewEnemyGroupDepartingFromSector( sSector, 0, ubNumEnemies, 0, 0 );
if( sGridNo != -1 )
{
@@ -2241,7 +2261,7 @@ if ( gGameUBOptions.pJA2UB == TRUE )
Ja25SAI_DetermineWhichLevelToAttackFrom( sSaiSector, &sSector, &bLevel );
//underground, we have to specify
pGroup = CreateNewEnemyGroupDepartingFromSectorUsingZLevel( sSector, bLevel, 0, ubNumEnemies, 0 );//was sSector
pGroup = CreateNewEnemyGroupDepartingFromSectorUsingZLevel( sSector, bLevel, 0, ubNumEnemies, 0, 0 );//was sSector
// pGroup->pEnemyGroup->ubTroopsInBattle = ubNumEnemies;
}
@@ -2802,6 +2822,7 @@ void SetH11NumEnemiesInSector()
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks=0;
// SEC_H11:
{
@@ -2829,7 +2850,7 @@ void SetH11NumEnemiesInSector()
break;
}
SetNumberJa25EnemiesInSurfaceSector( SEC_H11, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SEC_H11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
}
}
+4 -4
View File
@@ -188,12 +188,12 @@ BOOLEAN ShouldEnemiesBeAddedToInitialSector();
void InitJa25StrategicAi();
extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
void InitJa25SaveStruct();
void InitJa25StrategicAiBloodcats( );
extern void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
extern void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
BOOLEAN SaveJa25SaveInfoToSaveGame( HWFILE hFile );
BOOLEAN LoadJa25SaveInfoFromSavedGame( HWFILE hFile );
@@ -305,7 +305,7 @@ enum
extern BOOLEAN gfEnemyShouldImmediatelySeekThePlayer;
//extern INT32 giNumJA25Sectors;
extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
void SetJa25SectorOwnedStatus( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fPlayerOwned );
INT8 GetTheFurthestSectorPlayerOwns();
void Ja25_UpdateTimeOfEndOfLastBattle( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ );
@@ -317,7 +317,7 @@ void JA25_HandleUpdateOfStrategicAi();
void SetEnemiesToFindThePlayerMercs();
void HandleSayingDontStayToLongWarningInSectorH8();
extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
#ifdef JA2BETAVERSION
BOOLEAN InitJa25StrategicAiDecisions( BOOLEAN fLoadedGame );
+9 -2
View File
@@ -1996,6 +1996,7 @@ static int l_AddEnemyToUnderGroundSector(lua_State *L)
UINT8 ubNumAdmins = lua_tointeger(L,4);
UINT8 ubNumTroops = lua_tointeger(L,5);
UINT8 ubNumElites = lua_tointeger(L,6);
UINT8 ubNumTanks = lua_tointeger(L,7);
UNDERGROUND_SECTORINFO *pSector = FindUnderGroundSector( sSectorX, sSectorY, bLevel );
@@ -2004,6 +2005,7 @@ static int l_AddEnemyToUnderGroundSector(lua_State *L)
pSector->ubNumAdmins = ubNumAdmins;
pSector->ubNumTroops = ubNumTroops;
pSector->ubNumElites = ubNumElites;
pSector->ubNumTanks = ubNumTanks;
}
}
@@ -2191,6 +2193,7 @@ int i;
UINT8 ubNumAdmins=0;
UINT8 ubNumTroops=0;
UINT8 ubNumElites=0;
UINT8 ubNumTanks=0;
INT16 sSectorX;
INT16 sSectorY;
@@ -2202,8 +2205,9 @@ INT16 sSectorY;
if (i == 3 ) ubNumAdmins = lua_tointeger(L,i);
if (i == 4 ) ubNumTroops = lua_tointeger(L,i);
if (i == 5 ) ubNumElites = lua_tointeger(L,i);
if (i == 6 ) ubNumTanks = lua_tointeger(L,i);
}
SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
return 0;
}
@@ -4360,7 +4364,8 @@ UINT16 y = -1;
UINT16 z = -1;
UINT8 TROOPS_ILOSC = 0;
UINT8 ELITA_ILOSC = 0;
UINT CREATURE_ILOSC = 0;
UINT8 CREATURE_ILOSC = 0;
UINT8 TANKS_ILOSC = 0;
if ( ( x >= 1 || x <= 16 ) && ( y >= 1 || y <= 16 ) )
{
@@ -4370,12 +4375,14 @@ UINT CREATURE_ILOSC = 0;
TROOPS_ILOSC = lh_getIntegerFromTable(L, "Troops");
ELITA_ILOSC = lh_getIntegerFromTable(L, "Elite");
CREATURE_ILOSC = lh_getIntegerFromTable(L, "Creature");
TANKS_ILOSC = lh_getIntegerFromTable(L, "Tanks");
//z = lh_getIntegerFromTable(L, "SectorZ");
SectorInfo[ (UINT8)SECTOR( x, y ) ].ubNumTroops = TROOPS_ILOSC;
SectorInfo[ (UINT8)SECTOR( x, y ) ].ubNumElites = ELITA_ILOSC;
SectorInfo[ (UINT8)SECTOR( x, y ) ].ubNumCreatures = CREATURE_ILOSC;
SectorInfo[ (UINT8)SECTOR( x, y ) ].ubNumTanks = TANKS_ILOSC;
}
return 0;
+10 -10
View File
@@ -2689,39 +2689,39 @@ void MobileMilitiaDeserters(INT16 sMapX, INT16 sMapY, BOOLEAN fDeleteEquip, BOOL
///////////////////////
// check enemy presence to decide if mobiles are threatened and some will desert.
// Note: cant use NumEnemiesInFiveSectors() as it does not work for omerta or when reinforcements are deactivated, also it uses generateDirectionInfo(), which is used for militia movement.
UINT8 eAdmins = 0, eTroops = 0, eElites = 0;
UINT8 eAdmins = 0, eTroops = 0, eElites = 0, eTanks = 0;
//enemies in current sector
GetNumberOfEnemiesInSector( sMapX, sMapY, &eAdmins, &eTroops, &eElites );
GetNumberOfEnemiesInSector( sMapX, sMapY, &eAdmins, &eTroops, &eElites, &eTanks );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
enemiesNear = TRUE;
if ( ( sMapX > MINIMUM_VALID_X_COORDINATE ) && !enemiesNear )
{
//left side
GetNumberOfEnemiesInSector( sMapX - 1, sMapY, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
GetNumberOfEnemiesInSector( sMapX - 1, sMapY, &eAdmins, &eTroops, &eElites, &eTanks );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) )
enemiesNear = TRUE;
}
if ( ( sMapX < MAXIMUM_VALID_X_COORDINATE ) && !enemiesNear)
{
//right side
GetNumberOfEnemiesInSector( sMapX + 1, sMapY, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
GetNumberOfEnemiesInSector( sMapX + 1, sMapY, &eAdmins, &eTroops, &eElites, &eTanks );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) )
enemiesNear = TRUE;
}
if ( ( sMapY > MINIMUM_VALID_Y_COORDINATE ) && !enemiesNear )
{
//top side
GetNumberOfEnemiesInSector( sMapX, sMapY - 1, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
GetNumberOfEnemiesInSector( sMapX, sMapY - 1, &eAdmins, &eTroops, &eElites, &eTanks );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) )
enemiesNear = TRUE;
}
if ( ( sMapY < MAXIMUM_VALID_Y_COORDINATE ) && !enemiesNear)
{
//bottom side
GetNumberOfEnemiesInSector( sMapX, sMapY + 1, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
GetNumberOfEnemiesInSector( sMapX, sMapY + 1, &eAdmins, &eTroops, &eElites, &eTanks );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) )
enemiesNear = TRUE;
}
+6 -3
View File
@@ -221,12 +221,13 @@ void ValidateAndCorrectInBattleCounters( GROUP *pLocGroup )
{
if( pGroup->ubSectorX == pLocGroup->ubSectorX && pGroup->ubSectorY == pLocGroup->ubSectorY )
{
if( pGroup->pEnemyGroup->ubAdminsInBattle || pGroup->pEnemyGroup->ubTroopsInBattle || pGroup->pEnemyGroup->ubElitesInBattle )
if( pGroup->pEnemyGroup->ubAdminsInBattle || pGroup->pEnemyGroup->ubTroopsInBattle || pGroup->pEnemyGroup->ubElitesInBattle || pGroup->pEnemyGroup->ubTanksInBattle )
{
ubInvalidGroups++;
pGroup->pEnemyGroup->ubAdminsInBattle = 0;
pGroup->pEnemyGroup->ubTroopsInBattle = 0;
pGroup->pEnemyGroup->ubElitesInBattle = 0;
pGroup->pEnemyGroup->ubTanksInBattle = 0;
}
}
}
@@ -244,17 +245,19 @@ void ValidateAndCorrectInBattleCounters( GROUP *pLocGroup )
L"If you can provide information on how a previous battle was resolved here or nearby patrol "
L"(auto resolve, tactical battle, cheat keys, or retreat),"
L"please forward that info (no data files necessary) as well as the following code (very important): "
L"G(%02d:%c%d_b%d) A(%02d:%02d) T(%02d:%02d) E(%02d:%02d) C(%02d:%02d)",
L"G(%02d:%c%d_b%d) A(%02d:%02d) T(%02d:%02d) E(%02d:%02d) C(%02d:%02d) Ta(%02d:%02d)",
ubInvalidGroups, pLocGroup->ubSectorY + 'A' - 1, pLocGroup->ubSectorX, pLocGroup->ubSectorZ,
pSector->ubNumAdmins, pSector->ubAdminsInBattle,
pSector->ubNumTroops, pSector->ubTroopsInBattle,
pSector->ubNumElites, pSector->ubElitesInBattle,
pSector->ubNumCreatures, pSector->ubCreaturesInBattle );
pSector->ubNumCreatures, pSector->ubCreaturesInBattle,
pSector->ubNumTanks, pSector->ubTanksInBattle );
DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL );
pSector->ubAdminsInBattle = 0;
pSector->ubTroopsInBattle = 0;
pSector->ubElitesInBattle = 0;
pSector->ubCreaturesInBattle = 0;
pSector->ubTanksInBattle = 0;
}
}
#endif
+162 -50
View File
@@ -161,7 +161,7 @@ UINT8 NumHostilesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
pSector = FindUnderGroundSector( sSectorX, sSectorY, (UINT8)sSectorZ );
if( pSector )
{
ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures);
ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures + pSector->ubNumTanks);
}
}
else
@@ -171,7 +171,7 @@ UINT8 NumHostilesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
//Count stationary hostiles
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures);
ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures + pSector->ubNumTanks);
//Count mobile enemies
pGroup = gpGroupList;
@@ -205,7 +205,7 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
pSector = FindUnderGroundSector( sSectorX, sSectorY, (UINT8)sSectorZ );
if( pSector )
{
ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites);
ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks);
}
}
else
@@ -215,7 +215,7 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
//Count stationary enemies
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites);
ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks);
//Count mobile enemies
pGroup = gpGroupList;
@@ -254,7 +254,7 @@ UINT8 NumEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
ubNumTroops = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites);
ubNumTroops = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks);
if (is_networked)
ubNumTroops += numenemyLAN((UINT8)sSectorX,(UINT8)sSectorY ); //hayden
@@ -295,7 +295,7 @@ UINT8 NumStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
return( 0 );
}
return (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites);
return (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks);
}
UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
@@ -322,13 +322,13 @@ UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
if( pSector->ubGarrisonID == ROADBLOCK )
{ //consider these troops as mobile troops even though they are in a garrison
ubNumTroops += (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites);
ubNumTroops += (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks);
}
return ubNumTroops;
}
void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites )
void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks )
{
GROUP *pGroup;
SECTORINFO *pSector;
@@ -338,7 +338,7 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
//Now count the number of mobile groups in the sector.
*pubNumTroops = *pubNumElites = *pubNumAdmins = 0;
*pubNumTroops = *pubNumElites = *pubNumAdmins = *pubNumTanks = 0;
pGroup = gpGroupList;
while( pGroup )
{
@@ -347,6 +347,7 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu
*pubNumTroops += pGroup->pEnemyGroup->ubNumTroops;
*pubNumElites += pGroup->pEnemyGroup->ubNumElites;
*pubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins;
*pubNumTanks += pGroup->pEnemyGroup->ubNumTanks;
}
pGroup = pGroup->next;
}
@@ -357,11 +358,12 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu
*pubNumAdmins += pSector->ubNumAdmins;
*pubNumTroops += pSector->ubNumTroops;
*pubNumElites += pSector->ubNumElites;
*pubNumTanks += pSector->ubNumTanks;
}
}
void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites )
void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks )
{
GROUP *pGroup;
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE);
@@ -370,7 +372,7 @@ void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSe
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
//Now count the number of mobile groups in the sector.
*pubNumTroops = *pubNumElites = *pubNumAdmins = 0;
*pubNumTroops = *pubNumElites = *pubNumAdmins = *pubNumTanks = 0;
pGroup = gpGroupList;
while( pGroup )
{
@@ -379,13 +381,14 @@ void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSe
*pubNumTroops += pGroup->pEnemyGroup->ubNumTroops;
*pubNumElites += pGroup->pEnemyGroup->ubNumElites;
*pubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins;
*pubNumTanks += pGroup->pEnemyGroup->ubNumTanks;
}
pGroup = pGroup->next;
}
}
void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites )
void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks )
{
SECTORINFO *pSector;
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE);
@@ -398,19 +401,21 @@ void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8
*pubNumAdmins = pSector->ubNumAdmins;
*pubNumTroops = pSector->ubNumTroops;
*pubNumElites = pSector->ubNumElites;
*pubNumTanks = pSector->ubNumTanks;
}
void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites )
void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks )
{
UINT8 ubNumAdmins, ubNumTroops, ubNumElites;
UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks;
GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites );
GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks );
GetNumberOfMobileEnemiesInSector( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites );
GetNumberOfMobileEnemiesInSector( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
*pubNumAdmins += ubNumAdmins;
*pubNumTroops += ubNumTroops;
*pubNumElites += ubNumElites;
*pubNumTanks += ubNumTanks;
}
void EndTacticalBattleForEnemy()
@@ -426,6 +431,7 @@ void EndTacticalBattleForEnemy()
pSector->ubAdminsInBattle = 0;
pSector->ubTroopsInBattle = 0;
pSector->ubElitesInBattle = 0;
pSector->ubTanksInBattle = 0;
}
else if( !gbWorldSectorZ )
{
@@ -435,6 +441,7 @@ void EndTacticalBattleForEnemy()
pSector->ubAdminsInBattle = 0;
pSector->ubTroopsInBattle = 0;
pSector->ubElitesInBattle = 0;
pSector->ubTanksInBattle = 0;
pSector->ubNumCreatures = 0;
pSector->ubCreaturesInBattle = 0;
}
@@ -453,6 +460,7 @@ void EndTacticalBattleForEnemy()
pGroup->pEnemyGroup->ubTroopsInBattle = 0;
pGroup->pEnemyGroup->ubElitesInBattle = 0;
pGroup->pEnemyGroup->ubAdminsInBattle = 0;
pGroup->pEnemyGroup->ubTanksInBattle = 0;
}
pGroup = pGroup->next;
}
@@ -502,8 +510,8 @@ BOOLEAN PrepareEnemyForSectorBattle()
SECTORINFO *pSector;
GROUP *pGroup;
SOLDIERTYPE *pSoldier;
unsigned ubNumAdmins, ubNumTroops, ubNumElites;
unsigned ubTotalAdmins, ubTotalElites, ubTotalTroops;
unsigned ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks;
unsigned ubTotalAdmins, ubTotalElites, ubTotalTroops, ubTotalTanks;
unsigned totalCountOfStationaryEnemies = 0;
unsigned totalCountOfMobileEnemies = 0;
int sNumSlots;
@@ -557,7 +565,8 @@ BOOLEAN PrepareEnemyForSectorBattle()
pGroup->ubSectorY == gpBattleGroup->ubSectorY &&
!pGroup->pEnemyGroup->ubAdminsInBattle &&
!pGroup->pEnemyGroup->ubTroopsInBattle &&
!pGroup->pEnemyGroup->ubElitesInBattle )
!pGroup->pEnemyGroup->ubElitesInBattle &&
!pGroup->pEnemyGroup->ubTanksInBattle)
{
HandleArrivalOfReinforcements( pGroup );
}
@@ -592,11 +601,12 @@ BOOLEAN PrepareEnemyForSectorBattle()
// OJW - 20090403 - override max ai in co-op
if (is_networked && is_server && gMaxEnemiesEnabled == 1)
{
float totalEnemies = (float)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites);
float totalEnemies = (float)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks);
ubTotalAdmins = (unsigned int)(((float)pSector->ubNumAdmins / totalEnemies) * mapMaximumNumberOfEnemies);
ubTotalTroops = (unsigned int)(((float)pSector->ubNumTroops / totalEnemies) * mapMaximumNumberOfEnemies);
ubTotalElites = (unsigned int)(((float)pSector->ubNumElites / totalEnemies) * mapMaximumNumberOfEnemies);
totalEnemies = (float)(ubTotalAdmins + ubTotalTroops + ubTotalElites);
ubTotalTanks = (unsigned int)(((float)pSector->ubNumTanks / totalEnemies) * mapMaximumNumberOfEnemies);
totalEnemies = (float)(ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks);
// take care of any rounding losses
while (totalEnemies < mapMaximumNumberOfEnemies)
@@ -609,9 +619,11 @@ BOOLEAN PrepareEnemyForSectorBattle()
pSector->ubNumAdmins = ubTotalAdmins;
pSector->ubNumTroops = ubTotalTroops;
pSector->ubNumElites = ubTotalElites;
pSector->ubNumTanks = ubTotalTanks;
pSector->ubAdminsInBattle = 0;
pSector->ubTroopsInBattle = 0;
pSector->ubElitesInBattle = 0;
pSector->ubTanksInBattle = 0;
}
else
{
@@ -636,19 +648,22 @@ BOOLEAN PrepareEnemyForSectorBattle()
pSector->ubNumAdmins = ubTotalAdmins;
pSector->ubNumTroops = ubTotalTroops;
pSector->ubNumElites = ubTotalElites;
pSector->ubNumTanks = ubTotalTanks;
pSector->ubAdminsInBattle = 0;
pSector->ubTroopsInBattle = 0;
pSector->ubElitesInBattle = 0;
pSector->ubTanksInBattle = 0;
}
else
{
ubTotalAdmins = pSector->ubNumAdmins - pSector->ubAdminsInBattle;
ubTotalTroops = pSector->ubNumTroops - pSector->ubTroopsInBattle;
ubTotalElites = pSector->ubNumElites - pSector->ubElitesInBattle;
ubTotalTanks = pSector->ubNumTanks - pSector->ubTanksInBattle;
}
}
totalCountOfStationaryEnemies = ubTotalAdmins + ubTotalTroops + ubTotalElites;
totalCountOfStationaryEnemies = ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks;
if( totalCountOfStationaryEnemies > mapMaximumNumberOfEnemies )
{
@@ -662,19 +677,21 @@ BOOLEAN PrepareEnemyForSectorBattle()
ubTotalAdmins = min( mapMaximumNumberOfEnemies, ubTotalAdmins );
ubTotalTroops = min( mapMaximumNumberOfEnemies-ubTotalAdmins, ubTotalTroops );
ubTotalElites = min( mapMaximumNumberOfEnemies-ubTotalAdmins-ubTotalTroops, ubTotalElites );
ubTotalTanks = min( mapMaximumNumberOfEnemies-ubTotalAdmins-ubTotalTroops-ubTotalElites, ubTotalTanks );
}
pSector->ubAdminsInBattle += ubTotalAdmins;
pSector->ubTroopsInBattle += ubTotalTroops;
pSector->ubElitesInBattle += ubTotalElites;
pSector->ubTanksInBattle += ubTotalTanks;
#ifdef JA2TESTVERSION
if( gfOverrideSector )
{
//if there are no troops in the current groups, then we're done.
if( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites )
if( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks )
return FALSE;
AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites );
AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks );
ValidateEnemiesHaveWeapons();
return TRUE;
}
@@ -701,7 +718,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
//Subtract the total number of stationary enemies from the available slots, as stationary forces take
//precendence in combat. The mobile forces that could also be in the same sector are considered later if
//all the slots fill up.
sNumSlots -= ubTotalAdmins + ubTotalTroops + ubTotalElites;
sNumSlots -= ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks;
//Now, process all of the groups and search for both enemy and player groups in the sector.
//For enemy groups, we fill up the slots until we have none left or all of the groups have been
@@ -756,6 +773,20 @@ BOOLEAN PrepareEnemyForSectorBattle()
pGroup->pEnemyGroup->ubElitesInBattle += ubNumElites;
ubTotalElites += ubNumElites;
}
if( sNumSlots > 0 )
{ //Add tanks
AssertGE(pGroup->pEnemyGroup->ubNumTanks, pGroup->pEnemyGroup->ubTanksInBattle);
ubNumTanks = pGroup->pEnemyGroup->ubNumTanks - pGroup->pEnemyGroup->ubTanksInBattle;
sNumSlots -= ubNumTanks;
if( sNumSlots < 0 )
{ //adjust the value to zero
ubNumTanks += sNumSlots;
sNumSlots = 0;
gfPendingEnemies = TRUE;
}
pGroup->pEnemyGroup->ubTanksInBattle += ubNumTanks;
ubTotalTanks += ubNumTanks;
}
//NOTE:
//no provisions for profile troop leader or retreat groups yet.
}
@@ -777,12 +808,12 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
//if there are no troops in the current groups, then we're done.
if( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites )
if( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks )
{
return FALSE;
}
AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites );
AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks );
//Now, we have to go through all of the enemies in the new map, and assign their respective groups if
//in a mobile group, but only for the ones that were assigned from the
@@ -797,7 +828,8 @@ BOOLEAN PrepareEnemyForSectorBattle()
ubNumAdmins = pGroup->pEnemyGroup->ubAdminsInBattle;
ubNumTroops = pGroup->pEnemyGroup->ubTroopsInBattle;
ubNumElites = pGroup->pEnemyGroup->ubElitesInBattle;
unsigned num = ubNumAdmins + ubNumTroops + ubNumElites;
ubNumTanks = pGroup->pEnemyGroup->ubTanksInBattle;
unsigned num = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks;
unsigned firstSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
unsigned lastSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID;
@@ -863,12 +895,22 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
}
break;
case SOLDIER_CLASS_TANK:
if( ubNumTanks )
{
num--;
sNumSlots--;
ubNumTanks--;
pSoldier->ubGroupID = pGroup->ubGroupID;
}
break;
}
}
AssertEQ( ubNumElites , 0);
AssertEQ( ubNumTroops , 0);
AssertEQ( ubNumAdmins , 0);
AssertEQ( ubNumTanks , 0);
AssertEQ( num , 0);
}
pGroup = pGroup->next;
@@ -882,7 +924,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
BOOLEAN PrepareEnemyForUndergroundBattle()
{
UNDERGROUND_SECTORINFO *pUnderground;
unsigned ubTotalAdmins, ubTotalTroops, ubTotalElites;
unsigned ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks;
pUnderground = gpUndergroundSectorInfoHead;
while( pUnderground )
@@ -896,13 +938,15 @@ BOOLEAN PrepareEnemyForUndergroundBattle()
ubTotalAdmins = (UINT8)(pUnderground->ubNumAdmins - pUnderground->ubAdminsInBattle);
ubTotalTroops = (UINT8)(pUnderground->ubNumTroops - pUnderground->ubTroopsInBattle);
ubTotalElites = (UINT8)(pUnderground->ubNumElites - pUnderground->ubElitesInBattle);
ubTotalTanks = (UINT8)(pUnderground->ubNumTanks - pUnderground->ubTanksInBattle);
pUnderground->ubAdminsInBattle += ubTotalAdmins;
pUnderground->ubTroopsInBattle += ubTotalTroops;
pUnderground->ubElitesInBattle += ubTotalElites;
AddSoldierInitListEnemyDefenceSoldiers( pUnderground->ubNumAdmins, pUnderground->ubNumTroops, pUnderground->ubNumElites );
pUnderground->ubTanksInBattle += ubTotalTanks;
AddSoldierInitListEnemyDefenceSoldiers( pUnderground->ubNumAdmins, pUnderground->ubNumTroops, pUnderground->ubNumElites, pUnderground->ubNumTanks );
ValidateEnemiesHaveWeapons();
}
return ( ( BOOLEAN) ( pUnderground->ubNumAdmins + pUnderground->ubNumTroops + pUnderground->ubNumElites > 0 ) );
return ( ( BOOLEAN) ( pUnderground->ubNumAdmins + pUnderground->ubNumTroops + pUnderground->ubNumElites + pUnderground->ubNumTanks > 0 ) );
}
pUnderground = pUnderground->next;
}
@@ -990,6 +1034,34 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier )
}
}
break;
case TANK_CAR:
if( !pSoldier->bSectorZ )
{
pSector = &SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ];
if( pSector->ubNumTanks )
{
pSector->ubNumTanks--;
}
if( pSector->ubTanksInBattle )
{
pSector->ubTanksInBattle--;
}
}
else
{
UNDERGROUND_SECTORINFO *pUnderground;
pUnderground = FindUnderGroundSector( (UINT8)pSoldier->sSectorX, (UINT8)pSoldier->sSectorY, (UINT8)pSoldier->bSectorZ );
Assert( pUnderground );
if( pUnderground->ubNumTanks)
{
pUnderground->ubNumTanks--;
}
if( pUnderground->ubTanksInBattle )
{
pUnderground->ubTanksInBattle--;
}
}
break;
}
if( pSoldier->aiData.bNeutral || pSoldier->bTeam != ENEMY_TEAM && pSoldier->bTeam != CREATURE_TEAM )
@@ -1130,7 +1202,7 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier )
// }
#ifdef JA2BETAVERSION
ubTotalEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
ubTotalEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
#endif
switch( pSoldier->ubSoldierClass )
@@ -1243,7 +1315,7 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier )
{ //basement level (UNDERGROUND_SECTORINFO)
UNDERGROUND_SECTORINFO *pSector = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
#ifdef JA2BETAVERSION
UINT32 ubTotalEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites;
UINT32 ubTotalEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks;
#endif
if( pSector )
{
@@ -1387,7 +1459,7 @@ void AddPossiblePendingEnemiesToBattle()
#endif
UINT8 ubSlots, ubNumAvailable;
UINT8 ubNumElites, ubNumTroops, ubNumAdmins;
UINT8 ubNumElites, ubNumTroops, ubNumAdmins, ubNumTanks;
UINT8 ubNumGroupsInSector;
UINT8 ubGroupIndex;
GROUP *pGroup;
@@ -1473,11 +1545,11 @@ void AddPossiblePendingEnemiesToBattle()
//return;
}
if( pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins )
if( pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks )
{
ubNumElites = ubNumTroops = ubNumAdmins = 0;
ubNumElites = ubNumTroops = ubNumAdmins = ubNumTanks = 0;
ubNumAvailable = pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins - pSector->ubElitesInBattle - pSector->ubTroopsInBattle - pSector->ubAdminsInBattle;
ubNumAvailable = pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks - pSector->ubElitesInBattle - pSector->ubTroopsInBattle - pSector->ubAdminsInBattle - pSector->ubTanksInBattle;
while( ubNumAvailable && ubSlots )
{
// So they just magically appear out of nowhere from the edge?
@@ -1504,6 +1576,13 @@ void AddPossiblePendingEnemiesToBattle()
ubSlots--;
ubNumAdmins++;
}
else if( pSector->ubTanksInBattle < pSector->ubNumTanks )
{ //Add a tank
pSector->ubTanksInBattle++;
ubNumAvailable--;
ubSlots--;
ubNumTanks++;
}
else
{
AssertMsg( 0, "AddPossiblePendingEnemiesToBattle(): Logic Error -- by Kris" );
@@ -1511,7 +1590,7 @@ void AddPossiblePendingEnemiesToBattle()
}
if( ubNumAdmins || ubNumTroops || ubNumElites )
if( ubNumAdmins || ubNumTroops || ubNumElites || ubNumTanks )
{ //This group has contributed forces, then add them now, because different
//groups appear on different sides of the map.
UINT8 ubStrategicInsertionCode = ubPredefinedInsertionCode;
@@ -1552,7 +1631,7 @@ void AddPossiblePendingEnemiesToBattle()
if( ubStrategicInsertionCode < INSERTION_CODE_NORTH ||ubStrategicInsertionCode > INSERTION_CODE_WEST )
ubStrategicInsertionCode = INSERTION_CODE_NORTH + Random( 4 );
AddEnemiesToBattle( 0, ubStrategicInsertionCode, ubNumAdmins, ubNumTroops, ubNumElites, FALSE );
AddEnemiesToBattle( 0, ubStrategicInsertionCode, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, FALSE );
gfPendingEnemies = TRUE;
}
}
@@ -1582,7 +1661,7 @@ void AddPossiblePendingEnemiesToBattle()
pGroup = pGroupInSectorList[ ubGroupIndex];
// Flugente fix: check for underflow...
UINT8 currentgroupsize = pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle;
UINT8 currentgroupsize = pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + pGroup->pEnemyGroup->ubTanksInBattle;
if ( currentgroupsize > pGroup->ubGroupSize )
ubNumAvailable = 0;
else
@@ -1643,19 +1722,25 @@ void AddPossiblePendingEnemiesToBattle()
{ //Add an elite troop
pGroup->pEnemyGroup->ubElitesInBattle++;
ubSlots--;
AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 1, FALSE );
AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 1, 0, FALSE );
}
else if( pGroup->pEnemyGroup->ubTroopsInBattle < pGroup->pEnemyGroup->ubNumTroops )
{ //Add a regular troop.
pGroup->pEnemyGroup->ubTroopsInBattle++;
ubSlots--;
AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, FALSE );
AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 0, FALSE );
}
else if( pGroup->pEnemyGroup->ubAdminsInBattle < pGroup->pEnemyGroup->ubNumAdmins )
{ //Add an admin troop
pGroup->pEnemyGroup->ubAdminsInBattle++;
ubSlots--;
AddEnemiesToBattle( pGroup, ubInsertionCode, 1, 0, 0, FALSE );
AddEnemiesToBattle( pGroup, ubInsertionCode, 1, 0, 0, 0, FALSE );
}
else if( pGroup->pEnemyGroup->ubTanksInBattle < pGroup->pEnemyGroup->ubNumTanks )
{ //Add a tank
pGroup->pEnemyGroup->ubTanksInBattle++;
ubSlots--;
AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 0, 1, FALSE );
}
else
{
@@ -1664,7 +1749,7 @@ void AddPossiblePendingEnemiesToBattle()
pGroup->pEnemyGroup->ubTroopsInBattle++;
ubSlots--;
AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, FALSE );
AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 0, FALSE );
}
}
@@ -1733,7 +1818,7 @@ void NotifyPlayersOfNewEnemies()
}
}
void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, BOOLEAN fMagicallyAppeared )
void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, BOOLEAN fMagicallyAppeared )
{
SOLDIERTYPE *pSoldier;
MAPEDGEPOINTINFO MapEdgepointInfo;
@@ -1768,6 +1853,8 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub
pSector->ubTroopsInBattle += ubNumTroops;
pSector->ubNumElites += ubNumElites;
pSector->ubElitesInBattle += ubNumElites;
pSector->ubNumTanks += ubNumTanks;
pSector->ubTanksInBattle += ubNumTanks;
}
else
{
@@ -1780,13 +1867,15 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub
pSector->ubTroopsInBattle += ubNumTroops;
pSector->ubNumElites += ubNumElites;
pSector->ubElitesInBattle += ubNumElites;
pSector->ubNumTanks += ubNumTanks;
pSector->ubTanksInBattle += ubNumTanks;
}
}
//Because the enemies magically appeared, have one of our soldiers say something...
NotifyPlayersOfNewEnemies();
}
ubTotalSoldiers = ubNumAdmins + ubNumTroops + ubNumElites;
ubTotalSoldiers = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks;
#ifdef JA2UB
if( gsGridNoForMapEdgePointInfo != -1 )
@@ -1814,10 +1903,10 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub
}
else
{
ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (UINT8)(ubNumAdmins+ubNumElites+ubNumTroops) );
ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (UINT8)(ubNumAdmins+ubNumElites+ubNumTroops+ubNumTanks) );
}
#else
ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (UINT8)(ubNumAdmins+ubNumElites+ubNumTroops) );
ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (UINT8)(ubNumAdmins+ubNumElites+ubNumTroops+ubNumTanks) );
#endif
@@ -1893,6 +1982,29 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub
}
UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 );
}
else if( ubNumTanks && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumTroops + ubNumAdmins + ubNumTanks) && ubNumberOfVehicles < 9 )
{
ubNumTanks--;
ubTotalSoldiers--;
Assert(pSoldier = TacticalCreateEnemyTank());
if( pGroup )
{
pSoldier->ubGroupID = pGroup->ubGroupID;
}
pSoldier->ubInsertionDirection = bDesiredDirection;
//Setup the position
if( ubCurrSlot < MapEdgepointInfo.ubNumPoints )
{ //using an edgepoint
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
pSoldier->usStrategicInsertionData = MapEdgepointInfo.sGridNo[ ubCurrSlot++ ];
}
else
{ //no edgepoints left, so put him at the entrypoint.
pSoldier->ubStrategicInsertionCode = ubStrategicInsertionCode;
}
UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 );
}
// HEADROCK HAM 3.2: enemy reinforcements arrive with 0 APs.
if (gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 1 || gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 2)
{
@@ -2454,7 +2566,7 @@ BOOLEAN CheckPendingEnemies()
{
if( gbWorldSectorZ ) return FALSE;
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
if( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins) > ( pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle) )
if( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks) > ( pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle + pSector->ubTanksInBattle) )
return TRUE;
for (GROUP *pGroup = gpGroupList; pGroup; pGroup = pGroup->next)
{
@@ -2462,7 +2574,7 @@ BOOLEAN CheckPendingEnemies()
&& !pGroup->fVehicle
&& pGroup->ubSectorX == gWorldSectorX
&& pGroup->ubSectorY == gWorldSectorY
&& pGroup->ubGroupSize > pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle)
&& pGroup->ubGroupSize > pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + pGroup->pEnemyGroup->ubTanksInBattle)
return TRUE;
}
return FALSE;
+5 -5
View File
@@ -22,10 +22,10 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ );
UINT8 NumEnemiesInSector( INT16 sSectorX, INT16 sSectorY );
UINT8 NumStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY );
UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY );
void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites );
void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites );
void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites );
void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites );
void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks );
void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks );
void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks );
void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks );
//Called when entering a sector so the campaign AI can automatically insert the
//correct number of troops of each type based on the current number in the sector
@@ -33,7 +33,7 @@ void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAd
BOOLEAN PrepareEnemyForSectorBattle();
BOOLEAN PrepareEnemyForUndergroundBattle();
void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, BOOLEAN fMagicallyAppeared );
void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, BOOLEAN fMagicallyAppeared );
void AddPossiblePendingEnemiesToBattle();
void EndTacticalBattleForEnemy();
+26 -13
View File
@@ -31,19 +31,20 @@
UINT8 gubReinforcementMinEnemyStaticGroupSize = 12;
UINT32 guiMilitiaReinforceTurn = 0, guiMilitiaArrived = 0;//dnl ch68 090913
void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites )
void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks )
{
UINT8 ubNumAdmins, ubNumTroops, ubNumElites;
UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks;
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber, ubIndex;
GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites );
GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks );
GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites );
GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
*pubNumAdmins += ubNumAdmins;
*pubNumTroops += ubNumTroops;
*pubNumElites += ubNumElites;
*pubNumTanks += ubNumTanks;
if( !gGameExternalOptions.gfAllowReinforcements )
return;
@@ -55,9 +56,9 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
{
GetNumberOfStationaryEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites );
GetNumberOfStationaryEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
while( ubNumElites + ubNumTroops + ubNumAdmins > gubReinforcementMinEnemyStaticGroupSize)
while( ubNumElites + ubNumTroops + ubNumAdmins + ubNumTanks > gubReinforcementMinEnemyStaticGroupSize)
{
if( ubNumElites )
{
@@ -72,23 +73,29 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub
*pubNumAdmins += 1;
ubNumAdmins--;
}
else if( ubNumTanks )
{
*pubNumTanks += 1;
ubNumTanks--;
}
}
GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites );
GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
*pubNumAdmins += ubNumAdmins;
*pubNumTroops += ubNumTroops;
*pubNumElites += ubNumElites;
*pubNumTanks += ubNumTanks;
}
}
UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY )
{
UINT8 ubNumAdmins, ubNumTroops, ubNumElites;
UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks;
GetNumberOfEnemiesInFiveSectors( sMapX, sMapY, &ubNumAdmins, &ubNumTroops, &ubNumElites );
GetNumberOfEnemiesInFiveSectors( sMapX, sMapY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks );
return ubNumAdmins + ubNumTroops + ubNumElites;
return ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks;
}
BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 sSectorY )
@@ -279,19 +286,25 @@ UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY )
(pThisSector->ubNumElites)++;
(pSector->ubNumElites)--;
(pThisSector->ubElitesInBattle)++;
AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 1, FALSE );
AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 1, 0, FALSE );
}else if( pSector->ubNumTroops )
{
(pThisSector->ubNumTroops)++;
(pSector->ubNumTroops)--;
(pThisSector->ubTroopsInBattle)++;
AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 1, 0, FALSE );
AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 1, 0, 0, FALSE );
}else if( pSector->ubNumAdmins )
{
(pThisSector->ubNumAdmins)++;
(pSector->ubNumAdmins)--;
(pThisSector->ubAdminsInBattle)++;
AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 1, 0, 0, FALSE );
AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 1, 0, 0, 0, FALSE );
}else if( pSector->ubNumTanks )
{
(pThisSector->ubNumTanks)++;
(pSector->ubNumTanks)--;
(pThisSector->ubTanksInBattle)++;
AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 0, 1, FALSE );
}
return (UINT8)pusMoveDir[ ubIndex ][ 2 ];
+1 -1
View File
@@ -6,7 +6,7 @@
//For Autoresolve (mostly)
void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites );
void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks );
BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 sSectorY );
UINT8 GetAdjacentSectors( UINT8 pSectors[4], INT16 sSectorX, INT16 sSectorY );
UINT8 CountAllMilitiaInFiveSectors(INT16 sMapX, INT16 sMapY);
+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;
}
}
}
}
+10 -5
View File
@@ -695,7 +695,7 @@ BOOLEAN AddWaypointStrategicIDToPGroup( GROUP *pGroup, UINT32 uiSectorID )
//Enemy grouping functions -- private use by the strategic AI.
//............................................................
GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites )
GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks )
{
GROUP *pNew;
AssertMsg( uiSector >= 0 && uiSector <= 255, String( "CreateNewEnemyGroup with out of range value of %d", uiSector ) );
@@ -706,7 +706,7 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin
AssertMsg( pNew->pEnemyGroup, "MemAlloc failure during enemy group creation." );
memset( pNew->pEnemyGroup, 0, sizeof( ENEMYGROUP ) );
// Make sure group is not bigger than allowed!
while (ubNumAdmins + ubNumTroops + ubNumElites > gGameExternalOptions.iMaxEnemyGroupSize)
while (ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks > gGameExternalOptions.iMaxEnemyGroupSize)
{
if (ubNumTroops)
{
@@ -716,10 +716,14 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin
{
ubNumAdmins--;
}
else
else if (ubNumElites)
{
ubNumElites--;
}
else if (ubNumTanks)
{
ubNumTanks--;
}
}
pNew->pWaypoints = NULL;
pNew->ubSectorX = (UINT8)SECTORX( uiSector );
@@ -733,7 +737,8 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin
pNew->pEnemyGroup->ubNumAdmins = ubNumAdmins;
pNew->pEnemyGroup->ubNumTroops = ubNumTroops;
pNew->pEnemyGroup->ubNumElites = ubNumElites;
pNew->ubGroupSize = (UINT8)(ubNumAdmins + ubNumTroops + ubNumElites);
pNew->pEnemyGroup->ubNumTanks = ubNumTanks;
pNew->ubGroupSize = (UINT8)(ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks);
pNew->ubTransportationMask = FOOT;
pNew->fVehicle = FALSE;
pNew->ubCreatedSectorID = pNew->ubOriginalSector;
@@ -5554,7 +5559,7 @@ BOOLEAN ScoutIsPresentInSquad( INT16 ubSectorNumX, INT16 ubSectorNumY )
}
#ifdef JA2UB
GROUP* CreateNewEnemyGroupDepartingFromSectorUsingZLevel( UINT32 uiSector, UINT8 ubSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites )
GROUP* CreateNewEnemyGroupDepartingFromSectorUsingZLevel( UINT32 uiSector, UINT8 ubSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks )
{
GROUP *pNew;
AssertMsg( uiSector >= 0 && uiSector <= 255, String( "CreateNewEnemyGroup with out of range value of %d", uiSector ) );
+5 -4
View File
@@ -71,8 +71,9 @@ typedef struct ENEMYGROUP
UINT8 ubTroopsInBattle; //number of soldiers currently in battle.
UINT8 ubElitesInBattle; //number of elite soldiers currently in battle.
// WDS - New AI
UINT8 numTanks;
INT8 bPadding[19];
UINT8 ubNumTanks;
UINT8 ubTanksInBattle;
INT8 bPadding[18];
}ENEMYGROUP;
//NOTE: ALL FLAGS ARE CLEARED WHENEVER A GROUP ARRIVES IN A SECTOR, OR ITS WAYPOINTS ARE
@@ -180,9 +181,9 @@ BOOLEAN SetGroupPatrolParameters( UINT8 ubGroupID, UINT8 ubRestAtFL, UINT8 ubRes
//Enemy grouping functions -- private use by the strategic AI.
//............................................................
GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
#ifdef JA2UB
GROUP* CreateNewEnemyGroupDepartingFromSectorUsingZLevel( UINT32 uiSector, UINT8 ubSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites );
GROUP* CreateNewEnemyGroupDepartingFromSectorUsingZLevel( UINT32 uiSector, UINT8 ubSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks );
#endif
//ARRIVALCALLBACK -- None of these functions should be called directly.
+1
View File
@@ -86,6 +86,7 @@ enum
ENEMY_RANK_ADMIN,
ENEMY_RANK_TROOP,
ENEMY_RANK_ELITE,
//ENEMY_RANK_TANK,
NUM_ENEMY_RANKS
};
+2
View File
@@ -88,6 +88,7 @@ BOOLEAN LuaUnderground::InitializeSectorList()
sectorData.getValue("numAdmins", s->ubNumAdmins);
sectorData.getValue("numTroops", s->ubNumTroops);
sectorData.getValue("numElites", s->ubNumElites);
sectorData.getValue("numTanks", s->ubNumTanks);
sectorData.getValue("numBloodcats", s->ubNumBloodcats);
sectorData.getValue("numCreatures", s->ubNumCreatures);
@@ -104,6 +105,7 @@ BOOLEAN LuaUnderground::InitializeSectorList()
m_log << "\t\tAdmins: " << static_cast<int>(s->ubNumAdmins) << LF;
m_log << "\t\tTroops: " << static_cast<int>(s->ubNumTroops) << LF;
m_log << "\t\tElites: " << static_cast<int>(s->ubNumElites) << LF;
m_log << "\t\tTanks: " << static_cast<int>(s->ubNumTanks) << LF;
m_log << "\t- Creature population" << LF;
m_log << "\t\tBloodcats: " << static_cast<int>(s->ubNumBloodcats) << LF;
m_log << "\t\tCrepitus: " << static_cast<int>(s->ubNumCreatures) << LF;
+3
View File
@@ -391,6 +391,7 @@ void CrippledVersionFailureToLoadMapCheck();
extern INT16 gsAINumAdmins;
extern INT16 gsAINumTroops;
extern INT16 gsAINumElites;
extern INT16 gsAINumTanks;
extern INT16 gsAINumCreatures;
//The wrapper time for EnterSector
BOOLEAN fStartNewFile = TRUE;
@@ -2550,6 +2551,7 @@ void PrepareLoadedSector()
pSector->ubNumAdmins = (UINT8)( gsAINumAdmins > 0 ? gsAINumAdmins : 0 );
pSector->ubNumTroops = (UINT8)( gsAINumTroops > 0 ? gsAINumTroops : 0 );
pSector->ubNumElites = (UINT8)( gsAINumElites > 0 ? gsAINumElites : 0 );
pSector->ubNumTanks = (UINT8)( gsAINumTanks > 0 ? gsAINumTanks : 0 );
pSector->ubNumCreatures = (UINT8)( gsAINumCreatures > 0 ? gsAINumCreatures : 0 );
}
else if( !gbWorldSectorZ )
@@ -2559,6 +2561,7 @@ void PrepareLoadedSector()
pSector->ubNumAdmins = (UINT8)( gsAINumAdmins > 0 ? gsAINumAdmins : 0 );
pSector->ubNumTroops = (UINT8)( gsAINumTroops > 0 ? gsAINumTroops : 0 );
pSector->ubNumElites = (UINT8)( gsAINumElites > 0 ? gsAINumElites : 0 );
pSector->ubNumTanks = (UINT8)( gsAINumTanks > 0 ? gsAINumTanks : 0 );
pSector->ubNumCreatures = (UINT8)( gsAINumCreatures > 0 ? gsAINumCreatures : 0 );
}
}
+2
View File
@@ -316,9 +316,11 @@ void DoneFadeOutKilledQueen( void )
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumAdmins = 0;
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumTroops = 0;
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumElites = 0;
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumTanks = 0;
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubAdminsInBattle = 0;
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTroopsInBattle = 0;
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubElitesInBattle = 0;
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTanksInBattle = 0;
// ATE: banish elliot... dead or alive
gMercProfiles[ ELLIOT ].sSectorX = 0;
+47 -15
View File
@@ -43,7 +43,7 @@ int gCivPreservedTempFileVersion[256];
BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *pNode, GROUP *pGroup = NULL );
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures );
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks );
BOOLEAN gfRestoringEnemySoldiersFromTempFile = FALSE;
BOOLEAN gfRestoringCiviliansFromTempFile = FALSE;
@@ -104,8 +104,8 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
#endif
INT8 bSectorZ;
UINT8 ubSectorID;
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0;
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures;
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0;
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks;
gfRestoringEnemySoldiersFromTempFile = TRUE;
@@ -253,6 +253,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
ubStrategicElites = pSector->ubNumElites;
ubStrategicTroops = pSector->ubNumTroops;
ubStrategicAdmins = pSector->ubNumAdmins;
ubStrategicTanks = pSector->ubNumTanks;
ubStrategicCreatures = pSector->ubNumCreatures;
}
else
@@ -260,7 +261,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
SECTORINFO *pSector;
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
ubStrategicCreatures = pSector->ubNumCreatures;
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites );
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks );
}
for( i = 0; i < slots; i++ )
@@ -347,6 +348,16 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
AddPlacementToWorld( curr );
}
break;
case SOLDIER_CLASS_TANK:
if( curr->pBasicPlacement->bBodyType == TANK_NE || curr->pBasicPlacement->bBodyType == TANK_NW )
{
ubNumTanks++;
if( ubNumTanks < ubStrategicTanks )
{
AddPlacementToWorld( curr );
}
}
break;
}
break;
}
@@ -374,12 +385,13 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
}
//now add any extra enemies that have arrived since the temp file was made.
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins )
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks )
{
ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0;
ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0;
ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0;
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites );
ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0;
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks );
}
if( ubStrategicCreatures > ubNumCreatures )
{
@@ -662,8 +674,8 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
#endif
INT8 bSectorZ;
UINT8 ubSectorID;
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0;
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures;
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0;
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks;
gfRestoringEnemySoldiersFromTempFile = TRUE;
@@ -702,16 +714,17 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
ubNumElites = pSector->ubNumElites;
ubNumTroops = pSector->ubNumTroops;
ubNumAdmins = pSector->ubNumAdmins;
ubNumTanks = pSector->ubNumTanks;
ubNumCreatures = pSector->ubNumCreatures;
}
if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
{
// Get the number of enemies form the temp file
CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicElites, &ubStrategicTroops, &ubStrategicAdmins, &ubStrategicCreatures );
CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicElites, &ubStrategicTroops, &ubStrategicAdmins, &ubStrategicCreatures, &ubStrategicTanks );
//If any of the counts differ from what is in memory
if( ubStrategicElites != ubNumElites || ubStrategicTroops != ubNumTroops || ubStrategicAdmins != ubNumAdmins || ubStrategicCreatures != ubNumCreatures )
if( ubStrategicElites != ubNumElites || ubStrategicTroops != ubNumTroops || ubStrategicAdmins != ubNumAdmins || ubStrategicCreatures != ubNumCreatures || ubStrategicTanks != ubNumTanks )
{
//remove the file
RemoveEnemySoldierTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
@@ -720,7 +733,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
}
//reset
ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = 0;
ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = ubNumTanks = 0;
//Open the file for reading
@@ -860,6 +873,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
ubStrategicElites = pSector->ubNumElites;
ubStrategicTroops = pSector->ubNumTroops;
ubStrategicAdmins = pSector->ubNumAdmins;
ubStrategicTanks = pSector->ubNumTanks;
ubStrategicCreatures = pSector->ubNumCreatures;
}
else
@@ -867,7 +881,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
SECTORINFO *pSector;
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
ubStrategicCreatures = pSector->ubNumCreatures;
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites );
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks );
}
for( i = 0; i < slots; i++ )
@@ -944,6 +958,16 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
//def: AddPlacementToWorld( curr );
}
break;
case SOLDIER_CLASS_TANK:
if( curr->pBasicPlacement->bBodyType == TANK_NE || curr->pBasicPlacement->bBodyType == TANK_NW )
{
ubNumTanks++;
if( ubNumTanks <= ubStrategicTanks )
{
//def: AddPlacementToWorld( curr );
}
}
break;
}
break;
}
@@ -969,12 +993,13 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
}
//now add any extra enemies that have arrived since the temp file was made.
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins )
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks )
{
ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0;
ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0;
ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0;
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites );
ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0;
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks );
}
if( ubStrategicCreatures > ubNumCreatures )
{
@@ -1567,7 +1592,7 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures )
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks )
{
// SOLDIERINITNODE *curr;
SOLDIERCREATE_STRUCT tempDetailedPlacement;
@@ -1592,6 +1617,7 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile(
*pubNumElites = 0;
*pubNumRegulars = 0;
*pubNumAdmins = 0;
*pubNumTanks = 0;
*pubNumCreatures = 0;
@@ -1758,6 +1784,12 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile(
case SOLDIER_CLASS_CREATURE:
(*pubNumCreatures)++;
break;
case SOLDIER_CLASS_TANK:
if( tempDetailedPlacement.bBodyType == TANK_NE || tempDetailedPlacement.bBodyType == TANK_NW )
{
(*pubNumTanks)++;
}
break;
}
/*
while( curr )
+1 -1
View File
@@ -259,7 +259,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8
}
Assert( ( bSoldierClass >= SOLDIER_CLASS_NONE ) && ( bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA ) );
Assert( ( bSoldierClass >= SOLDIER_CLASS_NONE ) && ( bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA ) || bSoldierClass == SOLDIER_CLASS_TANK );
Assert( ( bEquipmentRating >= 0 ) && ( bEquipmentRating <= 4 ) );
+1 -1
View File
@@ -2329,7 +2329,7 @@ INT32 SoldierToSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE
// anv: special check for vehicles - since they're no longer transparent, we need to check for visibility
// of all substructures, also vehicle will be noticed even if just part of it is sticking around the corner
if( pEndSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && !TANK( pEndSoldier ) )
if( pEndSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && ( !TANK( pEndSoldier ) || gGameExternalOptions.fEnemyTanksAnyPartVisible ) )
{
STRUCTURE *pBase = pEndSoldier->pLevelNode->pStructureData;
if( pBase == NULL )
+4 -4
View File
@@ -6950,16 +6950,16 @@ void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
{
SECTORINFO *pSectorInfo = &(SectorInfo[SECTOR( sMapX, sMapY )]);
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = 0;
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = 0;
}
else
{
UNDERGROUND_SECTORINFO *pSectorInfo;
pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ );
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = 0;
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = 0;
}
}
+1 -1
View File
@@ -2610,7 +2610,7 @@ INT16 MinPtsToMove(SOLDIERTYPE *pSoldier)
INT16 sCost;
INT32 sGridNo;
if ( TANK( pSoldier ) )
if ( TANK( pSoldier ) && !gGameExternalOptions.fEnemyTanksCanMoveInTactical )
{
return(sLowest);//dnl ch64 290813 100AP made INT8 return obsolete
}
+21 -2
View File
@@ -14228,6 +14228,15 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
if ( TileIsOutOfBounds(this->sGridNo) )
return( FALSE );
// anv: passengers who can shoot can rest their guns
if ( this->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
{
if( !gNewVehicle[pVehicleList[this->iVehicleId].ubVehicleType].VehicleSeats[GetSeatIndexFromSoldier(this)].fBlockedShots )
return( TRUE );
else
return( FALSE );
}
// we determine the height of the next tile in our direction. Because of the way structures are handled, we sometimes have to take the very tile we're occupying right now
INT32 nextGridNoinSight = this->sGridNo;
if ( this->ubDirection == NORTH || this->ubDirection == SOUTHWEST || this->ubDirection == WEST || this->ubDirection == NORTHWEST )
@@ -14258,8 +14267,13 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
{
SOLDIERTYPE* pSoldier = MercPtrs[ usPersonID ];
// anv: vehicles don't mind
if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
applybipod = TRUE;
}
// if the other person is an ally and prone
if ( this->bSide == pSoldier->bSide && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE )
else if ( this->bSide == pSoldier->bSide && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE )
{
// if we are facing the other guy in a 90 degree angle, we can mount our gun on his back
// Once merc's relationship allows angering mercs through actions of others, add a penalty here
@@ -14324,8 +14338,13 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
{
SOLDIERTYPE* pSoldier = MercPtrs[usPersonID];
// anv: vehicles don't mind
if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{
applybipod = TRUE;
}
// if the other person is an ally and prone
if ( this->bSide == pSoldier->bSide && gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_CROUCH )
else if ( this->bSide == pSoldier->bSide && gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_CROUCH )
{
applybipod = TRUE;
+1
View File
@@ -329,6 +329,7 @@ enum
SOLDIER_CLASS_CREATURE,
SOLDIER_CLASS_MINER,
SOLDIER_CLASS_ZOMBIE,
SOLDIER_CLASS_TANK,
SOLDIER_CLASS_MAX,
};
+84
View File
@@ -2430,6 +2430,10 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
}
break;
case SOLDIER_CLASS_TANK:
pp->bExpLevel = bp->bRelativeAttributeLevel;
break;
default:
pp->bExpLevel = bp->bRelativeAttributeLevel; //avg 2 (1-4)
ubSoldierClass = SOLDIER_CLASS_NONE;
@@ -3033,6 +3037,86 @@ SOLDIERTYPE* TacticalCreateEliteEnemy()
return( pSoldier );
}
//USED BY STRATEGIC AI and AUTORESOLVE
SOLDIERTYPE* TacticalCreateEnemyTank()
{
BASIC_SOLDIERCREATE_STRUCT bp;
SOLDIERCREATE_STRUCT pp;
UINT8 ubID;
SOLDIERTYPE * pSoldier;
if( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI )
{
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ELITE );
if( pSoldier ) return pSoldier;
}
memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ELITE );
RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ELITE );
bp.bTeam = ENEMY_TEAM;
bp.bOrders = SEEKENEMY;
bp.bAttitude = (INT8) Random( MAXATTITUDES );
bp.bBodyType = TANK_NW;
bp.ubSoldierClass = SOLDIER_CLASS_TANK;
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
//SPECIAL! Certain events in the game can cause profiled NPCs to become enemies. The two cases are
//adding Mike and Iggy. We will only add one NPC in any given combat and the conditions for setting
//the associated facts are done elsewhere. There is also another place where NPCs can get added, which
//is in AddPlacementToWorld() used for inserting defensive enemies.
//NOTE: We don't want to add Mike or Iggy if this is being called from autoresolve!
OkayToUpgradeEliteToSpecialProfiledEnemy( &pp );
pSoldier = TacticalCreateSoldier( &pp, &ubID );
if ( pSoldier )
{
// send soldier to centre of map, roughly
pSoldier->aiData.sNoiseGridno = (CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
}
return( pSoldier );
}
//USED BY STRATEGIC AI and AUTORESOLVE
// should to be succeeded by TacticalCreateArmyTroop/EliteEnemy and AddSoldierToVehicle
SOLDIERTYPE* TacticalCreateJeep()
{
BASIC_SOLDIERCREATE_STRUCT bp;
SOLDIERCREATE_STRUCT pp;
UINT8 ubID;
SOLDIERTYPE * pSoldier;
SOLDIERTYPE * pDriver;
if( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI )
{
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ELITE );
if( pSoldier ) return pSoldier;
}
memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ELITE );
RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ELITE );
bp.bTeam = CIV_TEAM;
bp.bOrders = STATIONARY;
bp.bAttitude = (INT8) Random( MAXATTITUDES );
bp.bBodyType = JEEP;
bp.ubSoldierClass = SOLDIER_CLASS_NONE;
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
pp.ubProfile = 199;
pSoldier = TacticalCreateSoldier( &pp, &ubID );
if ( pSoldier )
{
// send soldier to centre of map, roughly
pSoldier->aiData.sNoiseGridno = (CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
}
return( pSoldier );
}
#ifdef ENABLE_ZOMBIES
//USED BY STRATEGIC AI and AUTORESOLVE
SOLDIERTYPE* TacticalCreateZombie()
+2
View File
@@ -425,6 +425,8 @@ SOLDIERTYPE* TacticalCreateArmyTroop();
#endif
SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass, INT16 sX, INT16 sY ); // Flugente: added sector coordinates
SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType );
SOLDIERTYPE* TacticalCreateEnemyTank();
SOLDIERTYPE* TacticalCreateJeep();
// Flugente: assassins are elite soldiers of the civ team that go hostile on a certain event, otherwise they just blend in
SOLDIERTYPE* TacticalCreateEnemyAssassin(UINT8 disguisetype);
+54 -3
View File
@@ -976,7 +976,7 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
return ubNumAdded;
}
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite )
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks )
{
SOLDIERINITNODE *mark;
SOLDIERINITNODE *curr;
@@ -985,6 +985,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
UINT8 ubElitePDSlots = 0, ubEliteDSlots = 0, ubElitePSlots = 0, ubEliteBSlots = 0;
UINT8 ubTroopPDSlots = 0, ubTroopDSlots = 0, ubTroopPSlots = 0, ubTroopBSlots = 0;
UINT8 ubAdminPDSlots = 0, ubAdminDSlots = 0, ubAdminPSlots = 0, ubAdminBSlots = 0;
UINT8 ubTankPDSlots = 0, ubTankDSlots = 0, ubTankPSlots = 0, ubTankBSlots = 0;
UINT8 ubFreeSlots;
UINT8 *pCurrSlots=NULL;
UINT8 *pCurrTotal=NULL;
@@ -1002,7 +1003,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//of each type of enemy may not be the same. Elites will choose the best placements, then army, then
//administrators.
ubMaxNum = ubTotalAdmin + ubTotalTroops + ubTotalElite;
ubMaxNum = ubTotalAdmin + ubTotalTroops + ubTotalElite + ubTotalTanks;
AssertLE (ubMaxNum, gGameExternalOptions.ubGameMaximumNumberOfEnemies);
@@ -1052,6 +1053,19 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
else
ubTroopBSlots++;
break;
case SOLDIER_CLASS_TANK:
if( curr->pDetailedPlacement->bBodyType == TANK_NW ||curr->pDetailedPlacement->bBodyType == TANK_NE )
{
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
ubTankPDSlots++;
else if( curr->pBasicPlacement->fPriorityExistance )
ubTankPSlots++;
else if( curr->pDetailedPlacement )
ubTankDSlots++;
else
ubTankBSlots++;
}
break;
}
}
curr = curr->next;
@@ -1060,7 +1074,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
//ADD PLACEMENTS WITH PRIORITY EXISTANCE WITH DETAILED PLACEMENT INFORMATION FIRST
//we now have the numbers of available slots for each soldier class, so loop through three times
//and randomly choose some (or all) of the matching slots to fill. This is done randomly.
for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY; ubCurrClass++ )
for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY + 1; ubCurrClass++ )
{
//First, prepare the counters.
switch( ubCurrClass )
@@ -1077,6 +1091,11 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
pCurrSlots = &ubTroopPDSlots;
pCurrTotal = &ubTotalTroops;
break;
case SOLDIER_CLASS_ARMY + 1:// SOLDIER_CLASS_TANK
ubCurrClass = SOLDIER_CLASS_TANK;
pCurrSlots = &ubTankPDSlots;
pCurrTotal = &ubTotalTanks;
break;
}
//Now, loop through the priority existance and detailed placement section of the list.
curr = gSoldierInitHead;
@@ -1253,6 +1272,12 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
ubTotalAdmin--;
}
else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks )
{
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK;
curr->pBasicPlacement->bBodyType = TANK_NW;
ubTotalTanks--;
}
else
Assert(0);
if( AddPlacementToWorld( curr ) )
@@ -1334,6 +1359,26 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
curr = curr->next;
}
// anv: try to place tanks outdoors
curr = gSoldierInitHead;
while( curr && ubFreeSlots && ubMaxNum )
{
if( !curr->pSoldier && curr->pBasicPlacement->bTeam == ENEMY_TEAM && ubTotalTanks && !GridNoIndoors( curr->pBasicPlacement->usStartingGridNo ))
{
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK;
curr->pBasicPlacement->bBodyType = TANK_NW;
ubTotalTanks--;
if( AddPlacementToWorld( curr ) )
{
ubMaxNum--;
}
else
return;
ubFreeSlots--;
}
curr = curr->next;
}
//Now, loop through the entire list again, but for the last time. All enemies will be inserted now ignoring
//detailed placements and classes.
curr = gSoldierInitHead;
@@ -1362,6 +1407,12 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
ubTotalAdmin--;
}
else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks )
{
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK;
curr->pBasicPlacement->bBodyType = TANK_NW;
ubTotalTanks--;
}
else
Assert(0);
/* DISABLE THE OVERRIDE FOR NOW...
+1 -1
View File
@@ -40,7 +40,7 @@ void RemoveSoldierNodeFromInitList( SOLDIERINITNODE *pNode );
SOLDIERINITNODE* FindSoldierInitNodeWithID( UINT16 usID );
UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum );
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite );
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks );
void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNumInfants,
UINT8 ubNumYoungMales, UINT8 ubNumYoungFemales, UINT8 ubNumAdultMales,
UINT8 ubNumAdultFemales );
+36 -32
View File
@@ -510,24 +510,24 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
if( pVehicleSoldier )
{
if ( pVehicleSoldier->bTeam != gbPlayerNum )
if ( pVehicleSoldier->bTeam != pSoldier->bTeam )
{
// Can we add a new vehicle
if( vCount >= gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles )
if( vCount >= gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles && pSoldier->bTeam == gbPlayerNum )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[VEHICLE_CAN_NOT_BE_ADDED] );
return( FALSE );
}
// Change sides...
pVehicleSoldier = ChangeSoldierTeam( pVehicleSoldier, gbPlayerNum );
pVehicleSoldier = ChangeSoldierTeam( pVehicleSoldier, pSoldier->bTeam );
// add it to mapscreen list
fReBuildCharacterList = TRUE;
}
}
// If vehicle is empty, add to unique squad now that it has somebody in it!
if ( GetNumberInVehicle( iId ) == 0 && pVehicleSoldier )
if ( GetNumberInVehicle( iId ) == 0 && pVehicleSoldier && pSoldier->bTeam == gbPlayerNum )
{
// 2 ) Add to unique squad...
AddCharacterToUniqueSquad( pVehicleSoldier );
@@ -536,17 +536,17 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
// We have now a guy on a squad group, remove him!
RemovePlayerFromGroup( SquadMovementGroups[ pVehicleSoldier->bAssignment ], pVehicleSoldier );
// I really have vehicles.\
// ONLY add to vehicle group once!
if ( !DoesPlayerExistInPGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ) )
{
//NOW.. add guy to vehicle group....
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier );
}
else
{
pVehicleSoldier->ubGroupID = pVehicleList[ iId ].ubMovementGroup;
}
// I really have vehicles.\
// ONLY add to vehicle group once!
if ( !DoesPlayerExistInPGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ) )
{
//NOW.. add guy to vehicle group....
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier );
}
else
{
pVehicleSoldier->ubGroupID = pVehicleList[ iId ].ubMovementGroup;
}
}
// check if the grunt is already here
@@ -565,7 +565,7 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
UnSetUIBusy( pSoldier->ubID );
// can't call SelectSoldier in mapscreen, that will initialize interface panels!!!
if ( guiCurrentScreen == GAME_SCREEN )
if ( guiCurrentScreen == GAME_SCREEN && pSoldier->bTeam == gbPlayerNum )
{
SelectSoldier( pVehicleSoldier->ubID, FALSE, TRUE );
}
@@ -611,11 +611,11 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
}
// if in a squad, remove from squad, if not, check if in vehicle, if so remove, if not, then check if in mvt group..if so, move and destroy group
if( pSoldier->bAssignment < ON_DUTY )
if( pSoldier->bTeam == gbPlayerNum && pSoldier->bAssignment < ON_DUTY )
{
RemoveCharacterFromSquads( pSoldier );
}
else if( pSoldier->ubGroupID != 0 )
else if( pSoldier->bTeam == gbPlayerNum && pSoldier->ubGroupID != 0 )
{
// Flugente 2012-08-15: had very weird behaviour here. The outcommented code below failed, because the group size wasn't 0, which then threw an Assert()-error.
// This happened in r5468 when assinging a merc on repair duty to the truck, switching back and forth between the two
@@ -628,22 +628,26 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
//pSoldier->ubGroupID = 0;
}
if( ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iId ) )
{
SetTimeOfAssignmentChangeForMerc( pSoldier );
}
// set thier assignment
ChangeSoldiersAssignment( pSoldier, VEHICLE );
// set vehicle id
pSoldier->iVehicleId = iId;
// if vehicle is part of mvt group, then add character to mvt group
if( pVehicleList[ iId ].ubMovementGroup != 0 )
if( pSoldier->bTeam == gbPlayerNum )
{
// add character
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pSoldier );
if( ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iId ) )
{
SetTimeOfAssignmentChangeForMerc( pSoldier );
}
// set thier assignment
ChangeSoldiersAssignment( pSoldier, VEHICLE );
// if vehicle is part of mvt group, then add character to mvt group
if( pVehicleList[ iId ].ubMovementGroup != 0 )
{
// add character
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pSoldier );
}
}
@@ -692,7 +696,7 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection );
// can't call SetCurrentSquad OR SelectSoldier in mapscreen, that will initialize interface panels!!!
if ( guiCurrentScreen == GAME_SCREEN )
if ( pSoldier->bTeam == gbPlayerNum && guiCurrentScreen == GAME_SCREEN )
{
SetCurrentSquad( pVehicleSoldier->bAssignment, TRUE );
}
@@ -1592,7 +1596,7 @@ SOLDIERTYPE *GetDriver( INT32 iID )
void SetDriver( INT32 iID, UINT8 ubID )
{
// anv: first make sure previous driver won't be driver anymore
if( pVehicleList[ iID ].ubDriver != NOBODY )
if( pVehicleList[ iID ].ubDriver != NOBODY && MercPtrs[ pVehicleList[ iID ].ubDriver ]->iVehicleId == iID )
{
if( MercPtrs[ pVehicleList[ iID ].ubDriver ] )
{
+9 -4
View File
@@ -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 );
+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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 );
}
+2 -1
View File
@@ -157,8 +157,9 @@ static int LuaGroupCreate( lua_State *L )
UINT8 NumAdmins = (UINT8) luaL_checkinteger( L, 2);
UINT8 NumTroops = (UINT8) luaL_checkinteger( L, 3);
UINT8 NumElites = (UINT8) luaL_checkinteger( L, 4);
UINT8 NumTanks = (UINT8) luaL_checkinteger( L, 5);
GROUP *pGroup = CreateNewEnemyGroupDepartingFromSector( Sector, NumAdmins, NumTroops, NumElites );
GROUP *pGroup = CreateNewEnemyGroupDepartingFromSector( Sector, NumAdmins, NumTroops, NumElites, NumTanks );
if (pGroup)
{
+9 -8
View File
@@ -103,6 +103,7 @@ UNDERGROUND_SECTORINFO *pSector;
UINT8 ubNumAdmins = 0;
UINT8 ubNumTroops = 0;
UINT8 ubNumElites = 0;
UINT8 ubNumTanks = 0;
if ( Level != 0 )
{
@@ -117,25 +118,25 @@ UINT8 ubNumElites = 0;
ubNumAdmins = Random( 0 );
ubNumTroops = 10 + Random( 5 );
ubNumElites = Random( 4 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
case DIF_LEVEL_MEDIUM:
ubNumAdmins = Random( 0 );
ubNumTroops = 15 + Random( 8 );
ubNumElites = 1 + Random( 2 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
case DIF_LEVEL_HARD:
ubNumAdmins = Random( 0 );
ubNumTroops = 20 + Random( 7 );
ubNumElites = 2 + Random( 2 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
case DIF_LEVEL_INSANE:
ubNumAdmins = Random( 0 );
ubNumTroops = 20 + Random( 3 );
ubNumElites = 6 + Random( 3 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
}
}
@@ -151,25 +152,25 @@ UINT8 ubNumElites = 0;
ubNumAdmins = Random( 0 );
ubNumTroops = 10 + Random( 5 );
ubNumElites = Random( 4 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
case DIF_LEVEL_MEDIUM:
ubNumAdmins = Random( 0 );
ubNumTroops = 15 + Random( 8 );
ubNumElites = 1 + Random( 2 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
case DIF_LEVEL_HARD:
ubNumAdmins = Random( 0 );
ubNumTroops = 23 + Random( 7);
ubNumElites = 2 + Random( 2 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
case DIF_LEVEL_INSANE:
ubNumAdmins = Random( 0 );
ubNumTroops = 20 + Random( 3 );
ubNumElites = 6 + Random( 3 );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites );
SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks );
break;
}
}