From 9e97538d8902a37474db5369e7a790bcc91c0e0c Mon Sep 17 00:00:00 2001 From: Flugente Date: Sun, 20 Mar 2016 18:45:51 +0000 Subject: [PATCH] New feature: enemy combat jeeps fill the role between infantry and tanks. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=344628&#msg_344628 This is savegame compatible. GameDir >= r2305 required. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8114 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Editor/EditorMercs.cpp | 6 +- GameSettings.cpp | 22 +- GameSettings.h | 11 + GameVersion.cpp | 18 +- GameVersion.h | 3 +- Init.cpp | 4 +- Laptop/CampaignStats.cpp | 4 +- Strategic/AI Viewer.cpp | 38 +- Strategic/ASD.cpp | 44 +- Strategic/ASD.h | 1 + Strategic/Auto Resolve.cpp | 127 +++-- Strategic/Campaign Init.cpp | 12 +- Strategic/Campaign Types.h | 10 +- Strategic/Ja25 Strategic Ai.cpp | 69 ++- Strategic/Ja25 Strategic Ai.h | 8 +- Strategic/Map Screen Interface Map.cpp | 21 +- Strategic/PreBattle Interface.cpp | 9 +- Strategic/Queen Command.cpp | 187 +++++-- Strategic/Queen Command.h | 12 +- Strategic/Reinforcement.cpp | 50 +- Strategic/Reinforcement.h | 2 +- Strategic/Strategic AI.cpp | 696 ++++++++++++++++--------- Strategic/Strategic Movement.cpp | 11 +- Strategic/Strategic Movement.h | 6 +- Strategic/UndergroundInit.cpp | 2 + Strategic/strategicmap.cpp | 75 ++- Tactical/Animation Control.cpp | 40 +- Tactical/Animation Data.cpp | 11 + Tactical/Animation Data.h | 5 + Tactical/End Game.cpp | 1 + Tactical/Enemy Soldier Save.cpp | 66 ++- Tactical/Handle Items.cpp | 3 + Tactical/Handle UI.cpp | 83 ++- Tactical/Interface Enhanced.cpp | 6 +- Tactical/Interface.cpp | 2 +- Tactical/Inventory Choosing.cpp | 44 +- Tactical/Items.cpp | 4 +- Tactical/LOS.cpp | 14 +- Tactical/Overhead.cpp | 12 +- Tactical/PATHAI.cpp | 17 +- Tactical/Points.cpp | 34 +- Tactical/Soldier Ani.cpp | 3 +- Tactical/Soldier Control.cpp | 39 +- Tactical/Soldier Control.h | 1 + Tactical/Soldier Create.cpp | 49 +- Tactical/Soldier Create.h | 1 + Tactical/Soldier Init List.cpp | 92 +++- Tactical/Soldier Init List.h | 2 +- Tactical/Soldier Profile.cpp | 2 + Tactical/Soldier Tile.cpp | 4 +- Tactical/Soldier macros.h | 4 +- Tactical/SoldierTooltips.cpp | 2 +- Tactical/TeamTurns.cpp | 2 +- Tactical/Turn Based Input.cpp | 1 + Tactical/Weapons.cpp | 61 ++- Tactical/Weapons.h | 7 +- Tactical/XML_AmmoTypes.cpp | 51 +- Tactical/opplist.cpp | 12 +- TacticalAI/AIMain.cpp | 12 +- TacticalAI/AIUtils.cpp | 26 +- TacticalAI/Attacks.cpp | 20 +- TacticalAI/DecideAction.cpp | 64 ++- TileEngine/Explosion Control.cpp | 8 +- TileEngine/structure.cpp | 19 +- Utils/Text.h | 1 + Utils/_ChineseText.cpp | 2 + Utils/_DutchText.cpp | 2 + Utils/_EnglishText.cpp | 2 + Utils/_FrenchText.cpp | 2 + Utils/_GermanText.cpp | 2 + Utils/_ItalianText.cpp | 2 + Utils/_PolishText.cpp | 2 + Utils/_RussianText.cpp | 2 + lua/lua_strategic.cpp | 3 +- ub_config.cpp | 94 ++-- 75 files changed, 1614 insertions(+), 772 deletions(-) diff --git a/Editor/EditorMercs.cpp b/Editor/EditorMercs.cpp index 10dd013e..478cd4e9 100644 --- a/Editor/EditorMercs.cpp +++ b/Editor/EditorMercs.cpp @@ -304,7 +304,7 @@ STR16 EditMercAttitudes[6] = { L"Defensive",L"Brave Loner",L"Brave Buddy", #define MAX_REBELTYPES 6 #define MAX_CIVTYPES 6 #else -#define MAX_ENEMYTYPES 7 +#define MAX_ENEMYTYPES 11 //#define MAX_ENEMYRANDOMTYPES 5 #define MAX_CREATURETYPES 8 #define MAX_REBELTYPES 7 @@ -318,7 +318,7 @@ INT8 bCreatureArray[MAX_CREATURETYPES]={ ADULTFEMALEMONSTER }; INT8 bRebelArray[MAX_REBELTYPES]={ RANDOM, MANCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE }; INT8 bCivArray[MAX_CIVTYPES]={ RANDOM, MANCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE }; #else -INT8 bEnemyArray[MAX_ENEMYTYPES]={ RANDOM, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE, TANK_NW, TANK_NE }; +INT8 bEnemyArray[MAX_ENEMYTYPES] = {RANDOM, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE, TANK_NW, TANK_NE, COMBAT_JEEP}; INT8 bCreatureArray[MAX_CREATURETYPES]={ BLOODCAT, LARVAE_MONSTER, INFANT_MONSTER, YAF_MONSTER, YAM_MONSTER, ADULTFEMALEMONSTER, AM_MONSTER, QUEENMONSTER }; INT8 bRebelArray[MAX_REBELTYPES]={ RANDOM, FATCIV, MANCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE }; INT8 bCivArray[MAX_CIVTYPES]={ RANDOM, FATCIV, MANCIV, MINICIV, DRESSCIV, HATKIDCIV, KIDCIV, REGMALE, BIGMALE, STOCKYMALE, REGFEMALE, @@ -2161,6 +2161,7 @@ void ChangeBodyType( INT8 bOffset ) //+1 or -1 only case JEEP: case TANK_NW: case TANK_NE: + case COMBAT_JEEP: gpSelected->pSoldier->flags.uiStatusFlags |= SOLDIER_VEHICLE; break; } @@ -2503,6 +2504,7 @@ void DisplayBodyTypeInfo() case AM_MONSTER: swprintf( str, pDisplayBodyTypeInfoText[25] ); break; case QUEENMONSTER: swprintf( str, pDisplayBodyTypeInfoText[26] ); break; case BLOODCAT: swprintf( str, pDisplayBodyTypeInfoText[27] ); break; + case COMBAT_JEEP: swprintf( str, pDisplayBodyTypeInfoText[28] ); break; } DrawEditorInfoBox( str, FONT10ARIAL, iScreenWidthOffset + 490, 2 * iScreenHeightOffset + 364, 70, 20 ); } diff --git a/GameSettings.cpp b/GameSettings.cpp index 5b9406eb..e69d3ee8 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1377,6 +1377,7 @@ void LoadGameExternalOptions() gGameExternalOptions.fAllowTanksDrivingOverPeople = iniReader.ReadBoolean("Tactical Gameplay Settings","ALLOW_TANKS_DRIVING_OVER_PEOPLE", TRUE); gGameExternalOptions.ubCarsRammingMaxStructureArmour = iniReader.ReadInteger("Tactical Gameplay Settings","CARS_RAMMING_MAX_STRUCTURE_ARMOUR", 30, 0, 255); + gGameExternalOptions.ubEnemyJeepsRammingMaxStructureArmour = iniReader.ReadInteger( "Tactical Gameplay Settings", "ENEMY_JEEP_RAMMING_MAX_STRUCTURE_ARMOUR", 38, 0, 255 ); gGameExternalOptions.ubTanksRammingMaxStructureArmour = iniReader.ReadInteger("Tactical Gameplay Settings","TANKS_RAMMING_MAX_STRUCTURE_ARMOUR", 70, 0, 255); gGameExternalOptions.ubAPSharedAmongPassengersAndVehicleMode = iniReader.ReadInteger("Tactical Gameplay Settings","AP_SHARED_AMONG_PASSENGERS_AND_VEHICLE_MODE", 3, 0, 3); @@ -1973,15 +1974,21 @@ void LoadGameExternalOptions() gGameExternalOptions.gASDResource_Cost[ASD_MONEY] = 1; gGameExternalOptions.gASDResource_Cost[ASD_FUEL] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_COST_FUEL", 10, 1, 100 ); - gGameExternalOptions.gASDResource_Cost[ASD_HELI] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_COST_HELI", 100000, 10000, 1000000 ); - gGameExternalOptions.gASDResource_Cost[ASD_JEEP] = 50000; - gGameExternalOptions.gASDResource_Cost[ASD_TANK] = 200000; + gGameExternalOptions.gASDResource_Cost[ASD_HELI] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_COST_HELI", 30000, 1, 1000000 ); + gGameExternalOptions.gASDResource_Cost[ASD_JEEP] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_COST_JEEP", 20000, 1, 1000000 ); + gGameExternalOptions.gASDResource_Cost[ASD_TANK] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_COST_TANK", 50000, 1, 1000000 ); gGameExternalOptions.gASDResource_BuyTime[ASD_MONEY] = 0; gGameExternalOptions.gASDResource_BuyTime[ASD_FUEL] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_TIME_FUEL", 60 * 8, 1, 60 * 48 ); gGameExternalOptions.gASDResource_BuyTime[ASD_HELI] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_TIME_HELI", 60 * 20, 1, 60 * 48 ); - gGameExternalOptions.gASDResource_BuyTime[ASD_JEEP] = 60 * 12; - gGameExternalOptions.gASDResource_BuyTime[ASD_TANK] = 60 * 24; + gGameExternalOptions.gASDResource_BuyTime[ASD_JEEP] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_TIME_JEEP", 60 * 12, 1, 60 * 48 ); + gGameExternalOptions.gASDResource_BuyTime[ASD_TANK] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_TIME_TANK", 60 * 24, 1, 60 * 48 ); + + gGameExternalOptions.fASDAssignsTanks = iniReader.ReadBoolean( "Strategic Additional Enemy AI Settings", "ASD_ASSIGNS_TANKS", TRUE ); + gGameExternalOptions.fASDAssignsJeeps = iniReader.ReadBoolean( "Strategic Additional Enemy AI Settings", "ASD_ASSIGNS_JEEPS", TRUE ); + + gGameExternalOptions.gASDResource_Fuel_Tank = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_FUEL_REQUIRED_TANK", 100, 0, 10000 ); + gGameExternalOptions.gASDResource_Fuel_Jeep = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_FUEL_REQUIRED_JEEP", 20, 0, 10000 ); // Flugente: enemy heli //################# Enemy Helicopter Settings ################## @@ -2236,8 +2243,11 @@ void LoadGameExternalOptions() 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); - gGameExternalOptions.usTankMinimumProgress = iniReader.ReadInteger("Strategic Gameplay Settings","TANK_MINIMUM_PROGRESS", 0, 0, 100); + gGameExternalOptions.usTankMinimumProgress = iniReader.ReadInteger("Strategic Gameplay Settings","TANK_MINIMUM_PROGRESS", 60, 0, 100); + gGameExternalOptions.fArmyUsesJeepsInAttacks = iniReader.ReadBoolean( "Strategic Gameplay Settings", "ARMY_USES_JEEPS_IN_ATTACKS", FALSE ); + gGameExternalOptions.fArmyUsesJeepsInPatrols = iniReader.ReadBoolean( "Strategic Gameplay Settings", "ARMY_USES_JEEPS_IN_PATROLS", FALSE ); + gGameExternalOptions.usJeepMinimumProgress = iniReader.ReadInteger( "Strategic Gameplay Settings", "JEEP_MINIMUM_PROGRESS", 30, 0, 100 ); // 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 diff --git a/GameSettings.h b/GameSettings.h index 41e8e8cf..e3f93c7c 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -616,6 +616,12 @@ typedef struct INT32 gASDResource_Cost[ASD_RESOURCE_MAX]; INT32 gASDResource_BuyTime[ASD_RESOURCE_MAX]; + BOOLEAN fASDAssignsTanks; + BOOLEAN fASDAssignsJeeps; + + INT32 gASDResource_Fuel_Tank; + INT32 gASDResource_Fuel_Jeep; + // Flugente: enemy heli BOOLEAN fEnemyHeliActive; UINT8 usEnemyHeliMinimumProgress; @@ -831,6 +837,10 @@ typedef struct BOOLEAN fArmyUsesTanksInPatrols; UINT8 usTankMinimumProgress; + BOOLEAN fArmyUsesJeepsInAttacks; + BOOLEAN fArmyUsesJeepsInPatrols; + UINT8 usJeepMinimumProgress; + // WANNE: Always use "prof.dat". BOOLEAN fUseDifficultyBasedProfDat; @@ -1460,6 +1470,7 @@ typedef struct BOOLEAN fAllowTanksDrivingOverPeople; UINT8 ubCarsRammingMaxStructureArmour; + UINT8 ubEnemyJeepsRammingMaxStructureArmour; UINT8 ubTanksRammingMaxStructureArmour; UINT8 ubAPSharedAmongPassengersAndVehicleMode; diff --git a/GameVersion.cpp b/GameVersion.cpp index 39a4e1b6..76936814 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -15,9 +15,9 @@ #ifdef JA2EDITOR #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8113 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8113 (Development Build)" }; #endif // ------------------------------ @@ -27,11 +27,11 @@ //DEBUG BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8113 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8113 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8113 (Development Build)" }; #endif #elif defined CRIPPLED_VERSION @@ -46,16 +46,16 @@ //RELEASE BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8113 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8113 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Release v1.13.8105 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.8113 (Development Build)" }; #endif #endif -CHAR8 czVersionNumber[16] = { "Build 16.03.12" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 16.03.20" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/GameVersion.h b/GameVersion.h index 20e70c53..4f47be51 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -21,6 +21,7 @@ extern CHAR16 zTrackingNumber[16]; // Keeps track of the saved game version. Increment the saved game version whenever // you will invalidate the saved game file +#define ENEMY_JEEPS 165 // Flugente: enemy jeeps #define ENEMY_HELICOPTERS 164 // Flugente: enemy helicopters #define DRUG_SYSTEM_REDONE 163 // Flugente: reworked the drug system #define MILITIA_PATH_PLOTTING 162 // Flugente: the player can plot militia paths in strategic, similar to player or helicopter travel @@ -83,7 +84,7 @@ extern CHAR16 zTrackingNumber[16]; #define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes #define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system -#define SAVE_GAME_VERSION ENEMY_HELICOPTERS +#define SAVE_GAME_VERSION ENEMY_JEEPS //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Init.cpp b/Init.cpp index 5e2a116e..7cd067ff 100644 --- a/Init.cpp +++ b/Init.cpp @@ -84,9 +84,10 @@ #include "AimArchives.h" #include "connect.h" #include "DynamicDialogueWidget.h" // added by Flugente for InitMyBoxes() +#include "Animation Data.h" // added by Flugente extern INT16 APBPConstants[TOTAL_APBP_VALUES] = {0}; -extern INT16 gubMaxActionPoints[28];//MAXBODYTYPES = 28... JUST GETTING IT TO WORK NOW. GOTTHARD 7/2/08 +extern INT16 gubMaxActionPoints[TOTALBODYTYPES];//MAXBODYTYPES = 28... JUST GETTING IT TO WORK NOW. GOTTHARD 7/2/08 extern BOOLEAN GetCDromDriveLetter( STR8 pString ); // The InitializeGame function is responsible for setting up all data and Gaming Engine @@ -1870,4 +1871,5 @@ void SetupMaxActionPointsAnimation() gubMaxActionPoints[ELDORADO] = APBPConstants[AP_VEHICLE_MAXIMUM]; gubMaxActionPoints[ICECREAMTRUCK] = APBPConstants[AP_VEHICLE_MAXIMUM]; gubMaxActionPoints[JEEP] = APBPConstants[AP_VEHICLE_MAXIMUM]; + gubMaxActionPoints[COMBAT_JEEP] = APBPConstants[AP_VEHICLE_MAXIMUM]; } diff --git a/Laptop/CampaignStats.cpp b/Laptop/CampaignStats.cpp index 2d0a6523..c7976e65 100644 --- a/Laptop/CampaignStats.cpp +++ b/Laptop/CampaignStats.cpp @@ -156,7 +156,7 @@ Incident_Stats::AddStat( SOLDIERTYPE* pSoldier, UINT8 aType ) case ENEMY_TEAM: { - if ( TANK(pSoldier) ) + if ( ARMED_VEHICLE( pSoldier ) ) group = CAMPAIGNHISTORY_SD_ENEMY_TANK; else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR ) group = CAMPAIGNHISTORY_SD_ENEMY_ADMIN; @@ -226,7 +226,7 @@ Incident_Stats::AddStat( SOLDIERTYPE* pSoldier, UINT8 aType ) break; } - if ( TANK(pSoldier) ) + if ( ARMED_VEHICLE( pSoldier ) ) { if ( pSoldier->bSide == 0 ) usIncidentFlags |= INCIDENT_TANKS_PLAYERSIDE; diff --git a/Strategic/AI Viewer.cpp b/Strategic/AI Viewer.cpp index be0d3eed..2dba2ef4 100644 --- a/Strategic/AI Viewer.cpp +++ b/Strategic/AI Viewer.cpp @@ -162,7 +162,7 @@ void ViewCreaturesCallback( GUI_BUTTON *btn, INT32 reason ); void ExtractAndUpdatePopulations(); void PrintEnemyPopTable(); void PrintEnemiesKilledTable(); -UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites, UINT8 ubTanks ); +UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites, UINT8 ubTanks, UINT8 ubJeeps ); void BlitGroupIcon( UINT8 ubIconType, UINT8 ubIconColor, UINT32 uiX, UINT32 uiY, HVOBJECT hVObject ); void PrintDetailedEnemiesInSectorInfo( INT32 iScreenX, INT32 iScreenY, UINT8 ubSectorX, UINT8 ubSectorY ); @@ -495,7 +495,7 @@ void RenderStationaryGroups() else if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks ) { // show enemies - ubIconColor = ChooseEnemyIconColor( pSector->ubNumAdmins, pSector->ubNumTroops, pSector->ubNumElites, pSector->ubNumTanks ); + ubIconColor = ChooseEnemyIconColor( pSector->ubNumAdmins, pSector->ubNumTroops, pSector->ubNumElites, pSector->ubNumTanks, pSector->ubNumJeeps ); ubGroupSize = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; if( pSector->ubGarrisonID != NO_GARRISON ) @@ -541,14 +541,13 @@ void RenderMovingGroupsAndMercs() GROUP *pGroup; HVOBJECT hVObject; INT32 x, y; - UINT8 ubNumTroops, ubNumAdmins, ubNumElites, ubNumTanks; + UINT8 ubNumTroops, ubNumAdmins, ubNumElites, ubNumTanks, ubNumJeeps; float ratio; INT32 minX, maxX, minY, maxY; UINT8 ubIconType; UINT8 ubIconColor; UINT8 ubFontColor; - SetFont( FONT10ARIAL ); SetFontShadow( FONT_NEARBLACK ); @@ -597,12 +596,13 @@ void RenderMovingGroupsAndMercs() ubNumTroops = pGroup->pEnemyGroup->ubNumTroops;//+ pGroup->pEnemyGroup->ubTroopsInBattle; ubNumElites = pGroup->pEnemyGroup->ubNumElites;// + pGroup->pEnemyGroup->ubElitesInBattle; ubNumTanks = pGroup->pEnemyGroup->ubNumTanks; + ubNumJeeps = pGroup->pEnemyGroup->ubNumJeeps; // must have one of the three, already checked groupsize! - Assert( ubNumAdmins || ubNumTroops || ubNumElites || ubNumTanks ); + Assert( ubNumAdmins || ubNumTroops || ubNumElites || ubNumTanks || ubNumJeeps ); //determine icon color - ubIconColor = ChooseEnemyIconColor( ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + ubIconColor = ChooseEnemyIconColor( ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); // must have a valid intention Assert( pGroup->pEnemyGroup->ubIntention < NUM_ENEMY_INTENTIONS ); @@ -727,7 +727,7 @@ void RenderInfoInSector() { SECTORINFO *pSector; GROUP *pGroup; - UINT8 ubNumAdmins=0, ubNumTroops=0, ubNumElites=0, ubNumTanks=0, ubAdminsInBattle=0, ubTroopsInBattle=0, ubElitesInBattle=0, ubTanksInBattle=0, ubNumGroups=0; + UINT8 ubNumAdmins = 0, ubNumTroops = 0, ubNumElites = 0, ubNumTanks = 0, ubNumJeeps = 0, ubAdminsInBattle = 0, ubTroopsInBattle = 0, ubElitesInBattle = 0, ubTanksInBattle = 0, ubJeepsInBattle = 0,ubNumGroups = 0; pSector = &SectorInfo[ SECTOR( ubSectorX, ubSectorY ) ]; @@ -741,10 +741,12 @@ void RenderInfoInSector() ubNumElites += pGroup->pEnemyGroup->ubNumElites; ubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins; ubNumTanks += pGroup->pEnemyGroup->ubNumTanks; + ubNumJeeps += pGroup->pEnemyGroup->ubNumJeeps; ubTroopsInBattle += pGroup->pEnemyGroup->ubTroopsInBattle; ubElitesInBattle += pGroup->pEnemyGroup->ubElitesInBattle; ubAdminsInBattle += pGroup->pEnemyGroup->ubAdminsInBattle; ubTanksInBattle += pGroup->pEnemyGroup->ubTanksInBattle; + ubJeepsInBattle += pGroup->pEnemyGroup->ubJeepsInBattle; ubNumGroups++; } pGroup = pGroup->next; @@ -761,17 +763,19 @@ void RenderInfoInSector() MilitiaInSectorOfRank( ubSectorX, ubSectorY, GREEN_MILITIA ), MilitiaInSectorOfRank( ubSectorX, ubSectorY, REGULAR_MILITIA ), MilitiaInSectorOfRank( ubSectorX, ubSectorY, ELITE_MILITIA ) ); yp += 10; SetFontForeground( FONT_ORANGE ); - mprintf( 280, yp, L"Garrison: (%d:%d Admins, %d:%d Troops, %d:%d Elites, %d:%d Tanks)", + mprintf( 280, yp, L"Garrison: (%d:%d Admins, %d:%d Troops, %d:%d Elites, %d:%d Tanks, %d:%d Jeeps)", pSector->ubAdminsInBattle, pSector->ubNumAdmins, pSector->ubTroopsInBattle, pSector->ubNumTroops, pSector->ubElitesInBattle, pSector->ubNumElites, - pSector->ubTanksInBattle, pSector->ubNumTanks ); + pSector->ubTanksInBattle, pSector->ubNumTanks, + pSector->ubJeepsInBattle, pSector->ubNumJeeps ); yp += 10; - mprintf( 280, yp, L"%d Groups: (%d:%d Admins, %d:%d Troops, %d:%d Elites, %d:%d Tanks)", ubNumGroups, + mprintf( 280, yp, L"%d Groups: (%d:%d Admins, %d:%d Troops, %d:%d Elites, %d:%d Tanks, %d:%d Jeeps)", ubNumGroups, ubAdminsInBattle, ubNumAdmins, ubTroopsInBattle, ubNumTroops, ubElitesInBattle, ubNumElites, - ubTanksInBattle, ubNumTanks ); + ubTanksInBattle, ubNumTanks, + ubJeepsInBattle, ubNumJeeps ); yp += 10; SetFontForeground( FONT_WHITE ); @@ -1274,7 +1278,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) gfRenderViewer = TRUE; if( gsSelSectorY > 1 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-16, 0, 11, 5, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-16, 0, 11, 5, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 10; @@ -1286,7 +1290,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) } if( gsSelSectorY < 16 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+16, 0, 8, 8, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+16, 0, 8, 8, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 12; @@ -1298,7 +1302,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) } if( gsSelSectorX > 1 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-1, 0, 11, 5, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-1, 0, 11, 5, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 11; @@ -1310,7 +1314,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) } if( gsSelSectorX < 16 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, 0, 14, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, 0, 14, 0, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 13; @@ -1833,7 +1837,7 @@ void PrintEnemiesKilledTable() -UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites, UINT8 ubTanks ) +UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites, UINT8 ubTanks, UINT8 ubJeeps ) { UINT8 ubIconColor; @@ -1844,7 +1848,7 @@ UINT8 ChooseEnemyIconColor( UINT8 ubAdmins, UINT8 ubTroops, UINT8 ubElites, UINT // Orange Mixed, no elites (Admins + Troops) // Burgundy Mixed, with elites (Elites + (Admins OR Troops)) - Assert( ubAdmins || ubTroops || ubElites ||ubTanks ); + Assert( ubAdmins || ubTroops || ubElites || ubTanks || ubJeeps ); if ( ubElites ) { diff --git a/Strategic/ASD.cpp b/Strategic/ASD.cpp index 8f05fdc1..4ea0c52f 100644 --- a/Strategic/ASD.cpp +++ b/Strategic/ASD.cpp @@ -196,6 +196,13 @@ void UpdateASD( ) if ( !(gASD_Flags & ASDFACT_HELI_UNLOCKED) && HighestPlayerProgressPercentage( ) >= gGameExternalOptions.usEnemyHeliMinimumProgress ) SetASDFlag( ASDFACT_HELI_UNLOCKED ); + if ( !(gASD_Flags & ASDFACT_JEEP_UNLOCKED) && HighestPlayerProgressPercentage( ) >= gGameExternalOptions.usJeepMinimumProgress ) + SetASDFlag( ASDFACT_JEEP_UNLOCKED ); + + if ( !(gASD_Flags & ASDFACT_TANK_UNLOCKED) && HighestPlayerProgressPercentage( ) >= gGameExternalOptions.usTankMinimumProgress ) + SetASDFlag( ASDFACT_TANK_UNLOCKED ); + + // determine whether we need to buy new toys ASDDecideOnPurchases(); @@ -250,10 +257,10 @@ void ASDDecideOnPurchases() // how many would we like to have? Note that this refers to the ones in our pool, the vehicles awarded to enemy groups are no longer accounted for needed_jeep = min( 10, 2 + highestplayerprogress / 10 ); - // if we already unlocked tanks, we want less jeeps + // if we already unlocked tanks, we no longer want jeeps - they are replaced by tanks if ( gASD_Flags & ASDFACT_TANK_UNLOCKED ) { - needed_jeep = max( 4, 12 - highestplayerprogress / 10 ); + needed_jeep = 0; } // how many are needed? @@ -1411,20 +1418,16 @@ void UpdateAndDamageEnemyHeliIfFound( INT16 sSectorX, INT16 sSectorY, INT16 sSec } //////////////////////////////////////////// enemy tanks ///////////////////////////////////////////////////////// -// TODO: ini this -INT32 gASDResource_Cost_Fuel_Tank = 100; // how many units of fuel a tank needs (used upon creation) -INT32 gASDResource_Cost_Fuel_Jeep = 20; - UINT32 ASDResourceCostFuel( UINT8 aType ) { switch ( aType ) { case ASD_TANK: - return gASDResource_Cost_Fuel_Tank; + return gGameExternalOptions.gASDResource_Fuel_Tank; break; case ASD_JEEP: - return gASDResource_Cost_Fuel_Jeep; + return gGameExternalOptions.gASDResource_Fuel_Jeep; break; } @@ -1434,8 +1437,7 @@ UINT32 ASDResourceCostFuel( UINT8 aType ) // if ASD has tanks, it can allow the queen to upgrade soldiers to tanks BOOLEAN ASDSoldierUpgradeToTank( ) { - // TODO: ini val for feature - if ( gGameExternalOptions.fASDActive && 0 ) + if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsTanks ) { if ( gASD_Flags & ASDFACT_TANK_UNLOCKED ) { @@ -1454,3 +1456,25 @@ BOOLEAN ASDSoldierUpgradeToTank( ) return FALSE; } + +BOOLEAN ASDSoldierUpgradeToJeep( ) +{ + if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsJeeps ) + { + if ( gASD_Flags & ASDFACT_JEEP_UNLOCKED ) + { + if ( gASDResource[ASD_JEEP] ) + { + gASDResource[ASD_JEEP] = max( 0, gASDResource[ASD_JEEP] - 1 ); + return TRUE; + } + } + } + else + { + gASDResource[ASD_JEEP] = max( 0, gASDResource[ASD_JEEP] - 1 ); + return TRUE; + } + + return FALSE; +} diff --git a/Strategic/ASD.h b/Strategic/ASD.h index 20309729..c4dfa1a1 100644 --- a/Strategic/ASD.h +++ b/Strategic/ASD.h @@ -118,5 +118,6 @@ UINT32 ASDResourceCostFuel( UINT8 aType ); // if ASD is used, any tanks the queen uses in mobile attacks come from its pool, and we have to account for that BOOLEAN ASDSoldierUpgradeToTank( ); +BOOLEAN ASDSoldierUpgradeToJeep( ); #endif //__ASD_H diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index cd2cdf73..25565cf5 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -167,7 +167,7 @@ typedef struct AUTORESOLVE_STRUCT UINT8 ubEnemyLeadership; UINT8 ubPlayerLeadership; UINT8 ubMercs, ubCivs, ubEnemies; - UINT8 ubAdmins, ubTroops, ubElites, ubTanks; + UINT8 ubAdmins, ubTroops, ubElites, ubTanks, ubJeeps; UINT8 ubYMCreatures, ubYFCreatures, ubAMCreatures, ubAFCreatures; UINT8 ubAliveMercs, ubAliveCivs, ubAliveEnemies; UINT8 ubMercCols, ubMercRows; @@ -228,10 +228,11 @@ typedef struct AUTORESOLVE_STRUCT #define CELL_EPC 0x00100000 #define CELL_ROBOT 0x00200000 #define CELL_TANK 0x00400000 +#define CELL_JEEP 0x00800000 //Combined flags #define CELL_PLAYER ( CELL_MERC | CELL_MILITIA ) -#define CELL_ENEMY ( CELL_ELITE | CELL_TROOP | CELL_ADMIN | CELL_TANK ) +#define CELL_ENEMY ( CELL_ELITE | CELL_TROOP | CELL_ADMIN | CELL_TANK | CELL_JEEP ) #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 ) @@ -290,6 +291,8 @@ enum MILITIA1F_FACE, MILITIA2F_FACE, MILITIA3F_FACE, + JEEP_FACE, + JEEP_WRECK, }; extern void CreateDestroyMapInvButton(); @@ -434,6 +437,8 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY ) SECTORINFO *pSector; INT32 i; UINT8 ubNumEnemies[ NUM_ENEMY_RANKS ]; + UINT8 ubNumTanks = 0; + UINT8 ubNumJeeps = 0; UINT8 ubRankIndex; //Clear any possible battle locator @@ -441,14 +446,12 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY ) pGroup = gpGroupList; pSector = &SectorInfo[ SECTOR( ubSectorX, ubSectorY ) ]; - - UINT8 ubNumTanks = 0; - + // if we're doing this from the Pre-Battle interface, gpAR is NULL, and RemoveAutoResolveInterface(0 won't happen, so // 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 ], &ubNumTanks ); + GetNumberOfEnemiesInSector( ubSectorX, ubSectorY, &ubNumEnemies[0], &ubNumEnemies[1], &ubNumEnemies[2], &ubNumTanks, &ubNumJeeps ); for ( ubRankIndex = 0; ubRankIndex < NUM_ENEMY_RANKS; ++ubRankIndex ) { @@ -479,6 +482,7 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY ) pSector->ubNumElites = 0; pSector->ubNumAdmins = 0; pSector->ubNumTanks = 0; + pSector->ubNumJeeps = 0; pSector->ubNumCreatures = 0; pSector->bLastKnownEnemies = 0; //Remove the mobile forces here, but only if battle is over. @@ -764,9 +768,9 @@ void AssociateEnemiesWithStrategicGroups() { SECTORINFO *pSector; GROUP *pGroup; - UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks; //how many soldiers of the type do we still have to assign to a group? - UINT8 ubISNumAdmins, ubISNumTroops, ubISNumElites, ubISNumTanks; - UINT8 ubNumElitesInGroup, ubNumTroopsInGroup, ubNumAdminsInGroup, ubNumTanksInGroup; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; //how many soldiers of the type do we still have to assign to a group? + UINT8 ubISNumAdmins, ubISNumTroops, ubISNumElites, ubISNumTanks, ubISNumJeeps; + UINT8 ubNumElitesInGroup, ubNumTroopsInGroup, ubNumAdminsInGroup, ubNumTanksInGroup, ubNumJeepsInGroup; INT32 i; UINT8 pSectors[4]; UINT8 ubDirAmount; @@ -782,6 +786,7 @@ void AssociateEnemiesWithStrategicGroups() ubNumTroops = pSector->ubNumTroops; ubNumElites = pSector->ubNumElites; ubNumTanks = pSector->ubNumTanks; + ubNumJeeps = pSector->ubNumJeeps; //Now go through our enemies in the autoresolve array, and assign the ubGroupID to the soldier //Stationary groups have a group ID of 0 - first assign enemies from those stationary groups @@ -793,6 +798,12 @@ void AssociateEnemiesWithStrategicGroups() gpEnemies[i].uiFlags |= CELL_ASSIGNED; ubNumTanks--; } + else if ( gpEnemies[i].uiFlags & CELL_JEEP && ubNumJeeps ) + { + gpEnemies[i].pSoldier->ubGroupID = 0; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + ubNumJeeps--; + } else if ( gpEnemies[i].uiFlags & CELL_ELITE && ubNumElites ) { gpEnemies[ i ].pSoldier->ubGroupID = 0; @@ -817,8 +828,9 @@ void AssociateEnemiesWithStrategicGroups() ubNumTroops = gpAR->ubTroops - pSector->ubNumTroops; ubNumElites = gpAR->ubElites - pSector->ubNumElites; ubNumTanks = gpAR->ubTanks - pSector->ubNumTanks; + ubNumJeeps = gpAR->ubJeeps - pSector->ubNumJeeps; - if( !ubNumElites && !ubNumTroops && !ubNumAdmins && !ubNumTanks ) + if ( !ubNumElites && !ubNumTroops && !ubNumAdmins && !ubNumTanks && !ubNumJeeps ) { //All troops accounted for. return; } @@ -833,6 +845,7 @@ void AssociateEnemiesWithStrategicGroups() ubNumTroopsInGroup = pGroup->pEnemyGroup->ubNumTroops; ubNumAdminsInGroup = pGroup->pEnemyGroup->ubNumAdmins; ubNumTanksInGroup = pGroup->pEnemyGroup->ubNumTanks; + ubNumJeepsInGroup = pGroup->pEnemyGroup->ubNumJeeps; for( i = 0; i < gpAR->ubEnemies; i++ ) { if( !(gpEnemies[ i ].uiFlags & CELL_ASSIGNED) ) //has this soldier already been assigned to a cell and therefore a group (while processing the static enemies above) ? @@ -844,6 +857,13 @@ void AssociateEnemiesWithStrategicGroups() ubNumTanks--; ubNumTanksInGroup--; } + else if ( ubNumJeeps && ubNumJeepsInGroup && gpEnemies[i].uiFlags & CELL_JEEP ) + { + gpEnemies[i].pSoldier->ubGroupID = pGroup->ubGroupID; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + ubNumJeeps--; + ubNumJeepsInGroup--; + } else if (ubNumElites && ubNumElitesInGroup && gpEnemies[i].uiFlags & CELL_ELITE) { gpEnemies[ i ].pSoldier->ubGroupID = pGroup->ubGroupID; @@ -883,6 +903,7 @@ void AssociateEnemiesWithStrategicGroups() ubNumTroopsInGroup = pGroup->pEnemyGroup->ubNumTroops; ubNumAdminsInGroup = pGroup->pEnemyGroup->ubNumAdmins; ubNumTanksInGroup = pGroup->pEnemyGroup->ubNumTanks; + ubNumJeepsInGroup = pGroup->pEnemyGroup->ubNumJeeps; for( i = 0; i < gpAR->ubEnemies; i++ ) { if( !(gpEnemies[ i ].uiFlags & CELL_ASSIGNED) ) @@ -894,6 +915,13 @@ void AssociateEnemiesWithStrategicGroups() ubNumTanks--; ubNumTanksInGroup--; } + else if ( ubNumJeeps && ubNumJeepsInGroup && gpEnemies[i].uiFlags & CELL_JEEP ) + { + gpEnemies[i].pSoldier->ubGroupID = pGroup->ubGroupID; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + ubNumJeeps--; + ubNumJeepsInGroup--; + } else if (ubNumElites && ubNumElitesInGroup && gpEnemies[i].uiFlags & CELL_ELITE) { gpEnemies[ i ].pSoldier->ubGroupID = pGroup->ubGroupID; @@ -932,10 +960,11 @@ void AssociateEnemiesWithStrategicGroups() ubISNumTroops = pSector->ubNumTroops; ubISNumElites = pSector->ubNumElites; ubISNumTanks = pSector->ubNumTanks; + ubISNumJeeps = pSector->ubNumJeeps; for( i = 0; i < gpAR->ubEnemies; ++i ) { - if( ubISNumAdmins + ubISNumTroops + ubISNumElites + ubISNumTanks <= gubReinforcementMinEnemyStaticGroupSize ) break; //if group would be left understaffed, it wont reinforce - go chceck another sector (what if are there more groups here?) + if ( ubISNumAdmins + ubISNumTroops + ubISNumElites + ubISNumTanks + ubISNumJeeps <= gubReinforcementMinEnemyStaticGroupSize ) break; //if group would be left understaffed, it wont reinforce - go chceck another sector (what if are there more groups here?) if( !(gpEnemies[ i ].uiFlags & CELL_ASSIGNED) ) { @@ -948,6 +977,15 @@ void AssociateEnemiesWithStrategicGroups() ubISNumTanks--; ubNumTanks--; } + else if ( gpEnemies[i].uiFlags & CELL_JEEP && ubISNumJeeps && ubNumJeeps ) + { + gpEnemies[i].pSoldier->ubGroupID = 0; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + gpEnemies[i].pSoldier->sSectorX = SECTORX( pSectors[ubCurrSI] ); + gpEnemies[i].pSoldier->sSectorY = SECTORY( pSectors[ubCurrSI] ); + ubISNumJeeps--; + ubNumJeeps--; + } else if ( gpEnemies[i].uiFlags & CELL_ELITE && ubISNumElites && ubNumElites ) { gpEnemies[ i ].pSoldier->ubGroupID = 0; @@ -980,7 +1018,7 @@ void AssociateEnemiesWithStrategicGroups() } /*at this point, all enemies should have been assigned to their cell and group. If not, there is a bug around Because number and type of cells should be computed for the same composition of enemies as the one we see in this function, it should not happen though*/ - AssertMsg(!(ubISNumAdmins & ubISNumTroops & ubISNumElites & ubISNumTanks), "Mapping between actual enemies and autoresolve cells is wrong."); + AssertMsg( !(ubISNumAdmins & ubISNumTroops & ubISNumElites & ubISNumTanks & ubISNumJeeps), "Mapping between actual enemies and autoresolve cells is wrong." ); } @@ -1090,14 +1128,16 @@ void CalculateSoldierCells( BOOLEAN fReset ) if( gubEnemyEncounterCode != CREATURE_ATTACK_CODE ) { - if ( index < gpAR->ubTanks ) - gpEnemies[index].uiFlags = CELL_TANK; - else if ( index < gpAR->ubTanks + gpAR->ubElites ) - gpEnemies[ index ].uiFlags = CELL_ELITE; - else if ( index < gpAR->ubTanks + gpAR->ubElites + gpAR->ubTroops ) - gpEnemies[ index ].uiFlags = CELL_TROOP; - else + if ( index < gpAR->ubElites ) + gpEnemies[index].uiFlags = CELL_ELITE; + else if ( index < gpAR->ubElites + gpAR->ubTroops ) + gpEnemies[index].uiFlags = CELL_TROOP; + else if ( index < gpAR->ubElites + gpAR->ubTroops + gpAR->ubAdmins ) gpEnemies[index].uiFlags = CELL_ADMIN; + else if ( index < gpAR->ubElites + gpAR->ubTroops + gpAR->ubAdmins + gpAR->ubTanks ) + gpEnemies[index].uiFlags = CELL_TANK; + else + gpEnemies[index].uiFlags = CELL_JEEP; } else { @@ -1177,6 +1217,8 @@ void RenderSoldierCell( SOLDIERCELL *pCell ) BltVideoObjectFromIndex( FRAME_BUFFER, gpAR->iFaces, CREATURE_SKULL, pCell->xp + 3 + x, pCell->yp + 3, VO_BLT_SRCTRANSPARENCY, NULL ); else if ( (pCell->uiFlags & CELL_TANK) ) BltVideoObjectFromIndex( FRAME_BUFFER, gpAR->iFaces, TANK_WRECK, pCell->xp + 3 + x, pCell->yp + 3, VO_BLT_SRCTRANSPARENCY, NULL ); + else if ( (pCell->uiFlags & CELL_JEEP) ) + BltVideoObjectFromIndex( FRAME_BUFFER, gpAR->iFaces, JEEP_WRECK, pCell->xp + 3 + x, pCell->yp + 3, VO_BLT_SRCTRANSPARENCY, NULL ); else BltVideoObjectFromIndex( FRAME_BUFFER, gpAR->iFaces, HUMAN_SKULL, pCell->xp+3+x, pCell->yp+3, VO_BLT_SRCTRANSPARENCY, NULL ); } @@ -2182,6 +2224,7 @@ 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(); @@ -2191,6 +2234,17 @@ void CreateAutoResolveInterface() gpEnemies[index].pSoldier->sSectorY = gpAR->ubSectorY; swprintf( gpEnemies[index].pSoldier->name, gpStrategicString[STR_AR_TANK_NAME] ); } + + for ( i = 0; i < gpAR->ubJeeps; ++i, ++index ) + { + gpEnemies[index].pSoldier = TacticalCreateEnemyJeep( ); + gpEnemies[index].uiVObjectID = gpAR->iFaces; + gpEnemies[index].usIndex = JEEP_FACE; + gpEnemies[index].pSoldier->sSectorX = gpAR->ubSectorX; + gpEnemies[index].pSoldier->sSectorY = gpAR->ubSectorY; + swprintf( gpEnemies[index].pSoldier->name, gpStrategicString[STR_AR_JEEP_NAME] ); + } + AssociateEnemiesWithStrategicGroups(); } else @@ -2900,8 +2954,8 @@ void CalculateAutoResolveInfo() { // GetNumberOfEnemiesInSector( gpAR->ubSectorX, gpAR->ubSectorY, GetNumberOfEnemiesInFiveSectors( gpAR->ubSectorX, gpAR->ubSectorY, - &gpAR->ubAdmins, &gpAR->ubTroops, &gpAR->ubElites, &gpAR->ubTanks ); - gpAR->ubEnemies = (UINT8)min( gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubElites + gpAR->ubTanks, MAX_AR_TEAM_SIZE ); + &gpAR->ubAdmins, &gpAR->ubTroops, &gpAR->ubElites, &gpAR->ubTanks, &gpAR->ubJeeps ); + gpAR->ubEnemies = (UINT8)min( gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubElites + gpAR->ubTanks + gpAR->ubJeeps, MAX_AR_TEAM_SIZE ); } else { @@ -2987,20 +3041,22 @@ void ResetAutoResolveInterface() //Make sure the number of enemy portraits is the same as needed. //The debug keypresses may add or remove more than one at a time. - while ( gpAR->ubElites + gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubTanks > gpAR->ubEnemies ) + while ( gpAR->ubElites + gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubTanks + gpAR->ubJeeps > gpAR->ubEnemies ) { switch( PreRandom( 5 ) ) { - case 0: if( gpAR->ubElites ) { gpAR->ubElites--; break; } - case 1: case 2: if( gpAR->ubAdmins ) { gpAR->ubAdmins--; break; } - case 3: case 4: if( gpAR->ubTroops ) { gpAR->ubTroops--; break; } + case 0: if ( gpAR->ubElites ) { gpAR->ubElites--; break; } + case 1: if ( gpAR->ubAdmins ) { gpAR->ubAdmins--; break; } + case 2: if ( gpAR->ubTroops ) { gpAR->ubTroops--; break; } + case 3: if ( gpAR->ubTanks ) { gpAR->ubTanks--; break; } + case 4: if ( gpAR->ubJeeps ) { gpAR->ubJeeps--; break; } } } - while ( gpAR->ubElites + gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubTanks < gpAR->ubEnemies ) + while ( gpAR->ubElites + gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubTanks + gpAR->ubJeeps< gpAR->ubEnemies ) { switch( PreRandom( 5 ) ) { - case 0: gpAR->ubElites++; break; + case 0: gpAR->ubElites++; break; case 1: case 2: gpAR->ubAdmins++; break; case 3: case 4: gpAR->ubTroops++; break; } @@ -4066,7 +4122,7 @@ BOOLEAN FireTankCannon( SOLDIERCELL *pAttacker ) pSoldier = pAttacker->pSoldier; // we need to be a tank to do this... - if ( !pSoldier || (pAttacker->uiFlags & CELL_TANK) == 0 || pSoldier->ubSoldierClass != SOLDIER_CLASS_TANK ) + if ( !pSoldier || (pAttacker->uiFlags & CELL_TANK) == 0 || pSoldier->ubSoldierClass != SOLDIER_CLASS_TANK || COMBAT_JEEP( pSoldier ) ) return FALSE; // a tank has several guns, don't fire the main gun all the time @@ -4296,7 +4352,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget ) usAttack *= 1.5; } // if our target is a tank, we use heavy weapons if we have any - else if ( TANK( pTarget->pSoldier ) && FireAntiTankWeapon( pAttacker ) ) + else if ( ARMED_VEHICLE( pTarget->pSoldier ) && FireAntiTankWeapon( pAttacker ) ) { fAntiTank = TRUE; @@ -4454,10 +4510,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget ) UINT8 ubAmmoType = Magazine[Item[(&pAttacker->pSoldier->inv[pAttacker->bWeaponSlot])->usItem].ubClassIndex].ubAmmoType; - if ( AmmoTypes[ubAmmoType].antiTank ) - { - ubImpact *= 2; - } + ubImpact *= AmmoTypes[ubAmmoType].dDamageModifierTank; iRandom = Random( 100 ); if ( iRandom < 15 ) @@ -4646,7 +4699,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget ) default : if ( CREATURE_OR_BLOODCAT( pTarget->pSoldier ) ) gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsCreatures++; - else if ( TANK( pTarget->pSoldier ) ) // we hardly can kill a tank in autoresolve, but well.. who knows.. + else if ( ARMED_VEHICLE( pTarget->pSoldier ) ) // we hardly can kill a tank in autoresolve, but well.. who knows.. gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsTanks++; else if ( pTarget->pSoldier->bTeam == CIV_TEAM && !pTarget->pSoldier->aiData.bNeutral && pTarget->pSoldier->bSide != gbPlayerNum ) gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsHostiles++; @@ -4794,7 +4847,7 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index ) } //bullet hit -- play an impact sound and a merc hit sound - if ( TANK( pTarget->pSoldier ) ) + if ( ARMED_VEHICLE( pTarget->pSoldier ) ) PlayAutoResolveSample( (UINT8)(S_METAL_IMPACT1 + PreRandom( 3 )), RATE_11025, 50, 1, MIDDLEPAN ); else PlayAutoResolveSample( (UINT8)(BULLET_IMPACT_1+PreRandom(3)), RATE_11025, 50, 1, MIDDLEPAN ); @@ -4860,7 +4913,7 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index ) default : if ( CREATURE_OR_BLOODCAT( pTarget->pSoldier ) ) gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsCreatures++; - else if ( TANK( pTarget->pSoldier ) ) // we hardly can kill a tank in autoresolve, but well.. who knows.. + else if ( ARMED_VEHICLE( pTarget->pSoldier ) ) // we hardly can kill a tank in autoresolve, but well.. who knows.. gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsTanks++; else if ( pTarget->pSoldier->bTeam == CIV_TEAM && !pTarget->pSoldier->aiData.bNeutral && pTarget->pSoldier->bSide != gbPlayerNum ) gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsHostiles++; @@ -4949,7 +5002,7 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index ) { //Normal death if( gpAR->fSound ) { - if ( TANK( pTarget->pSoldier ) ) + if ( ARMED_VEHICLE( pTarget->pSoldier ) ) PlayAutoResolveSample( (UINT8)(S_RAID_TB_BOMB), RATE_11025, 50, 1, MIDDLEPAN ); else pTarget->pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 ); diff --git a/Strategic/Campaign Init.cpp b/Strategic/Campaign Init.cpp index 9226e55e..645b2994 100644 --- a/Strategic/Campaign Init.cpp +++ b/Strategic/Campaign Init.cpp @@ -339,25 +339,25 @@ void GeneratePatrolGroups() GROUP *pGroup; UINT8 ubNumTroops; ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 )); - pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_C7, 0, ubNumTroops, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_C7, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_D9, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_B9, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_A14, 0, ubNumTroops, 0, 0, 0 ); pGroup->ubMoveType = ENDTOEND_FORWARDS; AddWaypointToPGroup( pGroup, 13, 1 ); //A13 AddWaypointToPGroup( pGroup, 15, 1 ); //A15 @@ -368,13 +368,13 @@ void GeneratePatrolGroups() pGroup->ubTransportationMask = TRACKED; ubNumTroops = (UINT8)(5 + gGameOptions.ubDifficultyLevel * 2 + Random( 4 )); - pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N6, 0, ubNumTroops, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N6, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N10, 0, ubNumTroops, 0, 0, 0 ); AddWaypointToPGroup( pGroup, 10, 11 ); //K10 AddWaypointToPGroup( pGroup, 10, 14 ); //N10 pGroup->ubTransportationMask = CAR; diff --git a/Strategic/Campaign Types.h b/Strategic/Campaign Types.h index 5d203fb0..8d05201c 100644 --- a/Strategic/Campaign Types.h +++ b/Strategic/Campaign Types.h @@ -528,7 +528,10 @@ typedef struct SECTORINFO FLOAT dFortification_MaxPossible; // the amount of fortification that can still be done in this sector, given the current layout plans. Is updated every time we unload a sector FLOAT dFortification_UnappliedProgress; // progress done via assignment work. As we cannot update unloaded sectors, update happens once sector is loaded - INT8 bPadding[ 4 ]; + UINT8 ubNumJeeps; + UINT8 ubJeepsInBattle; + + INT8 bPadding[ 22 ]; }SECTORINFO; @@ -574,7 +577,10 @@ typedef struct UNDERGROUND_SECTORINFO FLOAT dFortification_MaxPossible; // the amount of fortification that can still be done in this sector, given the current layout plans. Is updated every time we unload a sector FLOAT dFortification_UnappliedProgress; // progress done via assignment work. As we cannot update unloaded sectors, update happens once sector is loaded - INT8 bPadding[16]; + UINT8 ubNumJeeps; + UINT8 ubJeepsInBattle; + + INT8 bPadding[14]; //no padding left! }UNDERGROUND_SECTORINFO; diff --git a/Strategic/Ja25 Strategic Ai.cpp b/Strategic/Ja25 Strategic Ai.cpp index 0681960c..70abed5e 100644 --- a/Strategic/Ja25 Strategic Ai.cpp +++ b/Strategic/Ja25 Strategic Ai.cpp @@ -126,13 +126,13 @@ BOOLEAN AddEnemiesToInitialSectorH7(); 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, UINT8 ubNumTanks ); +void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps ); 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, UINT8 ubNumTanks ); +void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps ); void ResetJa25SectorProbabilities(); BOOLEAN InitJa25StrategicSectorAI( BOOLEAN fReset ); @@ -281,17 +281,18 @@ BOOLEAN AddEnemiesToInitialSectorH7() UINT8 ubNumTroops; UINT8 ubNumElites; UINT8 ubNumTanks; + UINT8 ubNumJeeps; UINT8 ubNumRemovedAdmins=0; UINT8 ubNumRemovedTroops=0; UINT8 ubNumRemovedElites=0; UINT8 ubNumRemovedTanks=0; + UINT8 ubNumRemovedJeeps=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, &ubNumTanks ); - + GetNumberOfJA25EnemiesInSector( 8, MAP_ROW_H, 0, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); //determine the #of enemies to travel to the initial heli sector if( ubNumAdmins > 1 ) @@ -306,13 +307,17 @@ BOOLEAN AddEnemiesToInitialSectorH7() if( ubNumTanks > 1 ) ubNumRemovedTanks = ubNumTanks / 3 + + Random( 3 ); + if( ubNumJeeps > 1 ) + ubNumRemovedJeeps = ubNumJeeps / 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), (UINT8)(ubNumTanks-ubNumRemovedTanks) ); + SetNumberJa25EnemiesInSector( 8, MAP_ROW_H, 0, (UINT8)(ubNumAdmins-ubNumRemovedAdmins), (UINT8)(ubNumTroops-ubNumRemovedTroops), (UINT8)(ubNumElites-ubNumRemovedElites), + (UINT8)(ubNumTanks-ubNumRemovedTanks), (UINT8)(ubNumJeeps-ubNumRemovedJeeps) ); uiWorldMin = GetWorldTotalMin(); - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, ubNumRemovedAdmins, ubNumRemovedTroops, ubNumRemovedElites, ubNumRemovedTanks ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, ubNumRemovedAdmins, ubNumRemovedTroops, ubNumRemovedElites, ubNumRemovedTanks, ubNumRemovedJeeps ); if( pGroup == NULL ) { @@ -403,19 +408,19 @@ void InitJa25UnderGroundSectors() */ } -void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks ) +void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps ) { //if its a ground level if( bSectorZ == 0 ) { - SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); } //its an underground level else { - SetNumberJa25EnemiesInUnderGroundSector( sSectorX, sSectorY, bSectorZ, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInUnderGroundSector( sSectorX, sSectorY, bSectorZ, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); } } @@ -857,6 +862,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) UINT8 ubNumTroops=0; UINT8 ubNumElites=0; UINT8 ubNumTanks; + UINT8 ubNumJeeps; //Mine Sector Level 1 switch( gGameOptions.ubDifficultyLevel ) @@ -877,7 +883,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 13, 9, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 13, 9, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); //Power Generator Level 1 @@ -899,7 +905,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 13, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 13, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); //Tunnel First Part, Level 1 @@ -921,7 +927,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); //Tunnel Second Part, Level 1 @@ -943,7 +949,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); @@ -966,7 +972,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 6 + Random( 4 ); break; } - SetNumberJa25EnemiesInSector( 15, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 15, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); //Complex, Level 2, K15 @@ -988,7 +994,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 10 + Random( 2 ); break; } - SetNumberJa25EnemiesInSector( 15, 11, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 15, 11, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); //Complex, Level 2, L15 @@ -1010,7 +1016,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 14 + Random( 2 ); break; } - SetNumberJa25EnemiesInSector( 15, 12, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 15, 12, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); //Complex, Level 3, L15 @@ -1032,7 +1038,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 15 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 15, 12, 3, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 15, 12, 3, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); } void InitJa25SaveStruct() @@ -1325,10 +1331,11 @@ void AddEnemiesToFirstTunnelSector() UINT8 ubNumTroops=0; UINT8 ubNumElites=0; UINT8 ubNumTanks=0; + UINT8 ubNumJeeps=0; - NumEnemiesToAttackFirstTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + NumEnemiesToAttackFirstTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); - SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); } void AddEnemiesToSecondTunnelSector() @@ -1337,17 +1344,19 @@ void AddEnemiesToSecondTunnelSector() UINT8 ubNumTroops=0; UINT8 ubNumElites=0; UINT8 ubNumTanks=0; + UINT8 ubNumJeeps=0; - NumEnemiesToAttackSecondTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); - SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + NumEnemiesToAttackSecondTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); + SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); } -UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks ) +UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps ) { UINT8 ubNumAdmins=0; UINT8 ubNumTroops=0; UINT8 ubNumElites=0; UINT8 ubNumTanks=0; + UINT8 ubNumJeeps=0; //if the player blew up the fan, add a ton of enemies to the sector //1st Tunnel Sector @@ -1382,15 +1391,19 @@ UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 if( pTanks ) *pTanks = ubNumTanks; - return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks ); + if( pJeeps ) + *pJeeps = ubNumJeeps; + + return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps ); } -UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks ) +UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps ) { UINT8 ubNumAdmins=0; UINT8 ubNumTroops=0; UINT8 ubNumElites=0; UINT8 ubNumTanks=0; + UINT8 ubNumJeeps=0; //if the player blew up the fan, add a ton of enemies to the sector //1st Tunnel Sector @@ -1422,8 +1435,10 @@ UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT *pElites = ubNumElites; if( pTanks ) *pTanks = ubNumTanks; + if( pJeeps ) + *pJeeps = ubNumJeeps; - return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks ); + return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps ); } @@ -2186,7 +2201,7 @@ BOOLEAN HandleAddEnemiesToSectorPlayerIsntIn( INT16 sSaiSector, UINT8 ubNumEnemi gubEnemyEncounterCode = ENEMY_INVASION_CODE; } - SetNumberJa25EnemiesInSector( sSectorX, sSectorY, bSectorZ, 0, ubNumEnemies, 0, 0 ); + SetNumberJa25EnemiesInSector( sSectorX, sSectorY, bSectorZ, 0, ubNumEnemies, 0, 0, 0 ); SetThisSectorAsEnemyControlled( sSectorX, sSectorY, bSectorZ, FALSE ); @@ -2231,7 +2246,7 @@ if ( gGameUBOptions.pJA2UB == TRUE ) if( gJa25AiSectorStruct[ sSaiSector ].bSectorZ == 0 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( sSector, 0, ubNumEnemies, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( sSector, 0, ubNumEnemies, 0, 0, 0 ); if( sGridNo != -1 ) { diff --git a/Strategic/Ja25 Strategic Ai.h b/Strategic/Ja25 Strategic Ai.h index 5e6b397f..832aa3c2 100644 --- a/Strategic/Ja25 Strategic Ai.h +++ b/Strategic/Ja25 Strategic Ai.h @@ -188,12 +188,12 @@ BOOLEAN ShouldEnemiesBeAddedToInitialSector(); void InitJa25StrategicAi(); -extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks ); +extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps ); void InitJa25SaveStruct(); void InitJa25StrategicAiBloodcats( ); -extern void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks ); +extern void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps ); 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, UINT8 ubNumTanks ); +extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps ); 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, UINT8 ubNumTanks ); +extern void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps ); #ifdef JA2BETAVERSION BOOLEAN InitJa25StrategicAiDecisions( BOOLEAN fLoadedGame ); diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 7cb29755..c41a0a9a 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -562,7 +562,7 @@ void ShowSAMSitesOnStrategicMap( void ); void MilitiaBoxMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ); // display potential path, yes or no? -void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies, UINT16 usNumTanks, UINT8 ubIconPosition ); +void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies, UINT16 usNumEnemyArmedVehicles, UINT8 ubIconPosition ); void ShowUncertainNumberEnemiesInSector( INT16 sSectorX, INT16 sSectorY ); void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubIconPosition ); @@ -1256,7 +1256,7 @@ INT32 ShowVehicles(INT16 sMapX, INT16 sMapY, INT32 iCount) } -void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies, UINT16 usNumTanks, UINT8 ubIconPosition ) +void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies, UINT16 usNumEnemyArmedVehicles, UINT8 ubIconPosition ) { HVOBJECT hIconHandle; INT16 sEnemy, s10xEnemy, sEnemyLessTank; @@ -1264,7 +1264,7 @@ void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies // get the video object GetVideoObject(&hIconHandle, guiCHARICONS); - sEnemyLessTank = sNumberOfEnemies - usNumTanks; + sEnemyLessTank = sNumberOfEnemies - usNumEnemyArmedVehicles; // no 10x icon for easy enemy quantity gauge in low resolution if (iResolution >= _640x480 && iResolution < _800x600) @@ -1285,17 +1285,17 @@ void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies { // Flugente: the tank icon has is 4 icons wide and 2 rows high, thus this odd code bit // if we want to display a tank and have not yet done so, pick the first position that still has enough space to the right - if ( usNumTanks && secondtankrowstart < 0 && ( ubIconPosition % MERC_ICONS_PER_LINE ) < 3 ) + if ( usNumEnemyArmedVehicles && secondtankrowstart < 0 && (ubIconPosition % MERC_ICONS_PER_LINE) < 3 ) { DrawMapBoxIcon( hIconHandle, ENEMY_TANK_BIG, sSectorX, sSectorY, ubIconPosition ); secondtankrowstart = ubIconPosition + 6; ubIconPosition += 4; } // if this is the second row of a tank, don't draw anything - else if ( usNumTanks && secondtankrowstart > -1 && ubIconPosition == secondtankrowstart ) + else if ( usNumEnemyArmedVehicles && secondtankrowstart > -1 && ubIconPosition == secondtankrowstart ) { // for now display only one tank icon - usNumTanks = 0; + usNumEnemyArmedVehicles = 0; ubIconPosition += 4; sEnemy = max( 0, sEnemy - 1 ); } @@ -6598,6 +6598,7 @@ BOOLEAN CanMercsScoutThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubIconPosition ) { INT16 sNumberOfEnemies = 0; + UINT16 usNumEnemyArmedVehicles = 0; // ATE: If game has just started, don't do it! if ( DidGameJustStart() ) @@ -6677,10 +6678,10 @@ void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bS case KNOWS_HOW_MANY: { // Flugente: tanks get a special icon, so we need to count them separately - UINT16 usNumTanks = NumTanksInSector( sSectorX, sSectorY, ENEMY_TEAM ); + usNumEnemyArmedVehicles = NumEnemyArmedVehiclesInSector( sSectorX, sSectorY, ENEMY_TEAM ); // display individual icons for each enemy, starting at the received icon position index - ShowEnemiesInSector( sSectorX, sSectorY, sNumberOfEnemies, usNumTanks, ubIconPosition ); + ShowEnemiesInSector( sSectorX, sSectorY, sNumberOfEnemies, usNumEnemyArmedVehicles, ubIconPosition ); } break; @@ -6688,10 +6689,10 @@ void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bS case KNOWS_HOW_MANY_AND_WHERE_GOING: { // Flugente: tanks get a special icon, so we need to count them separately - UINT16 usNumTanks = NumTanksInSector( sSectorX, sSectorY, ENEMY_TEAM ); + usNumEnemyArmedVehicles = NumEnemyArmedVehiclesInSector( sSectorX, sSectorY, ENEMY_TEAM ); // display individual icons for each enemy, starting at the received icon position index - ShowEnemiesInSector( sSectorX, sSectorY, sNumberOfEnemies, usNumTanks, ubIconPosition ); + ShowEnemiesInSector( sSectorX, sSectorY, sNumberOfEnemies, usNumEnemyArmedVehicles, ubIconPosition ); // display their direction of movement, if valid. ShowNonPlayerGroupsInMotion( sSectorX, sSectorY, ENEMY_TEAM ); diff --git a/Strategic/PreBattle Interface.cpp b/Strategic/PreBattle Interface.cpp index 380aff94..6ffa7f0b 100644 --- a/Strategic/PreBattle Interface.cpp +++ b/Strategic/PreBattle Interface.cpp @@ -227,13 +227,14 @@ void ValidateAndCorrectInBattleCounters( GROUP *pLocGroup ) { if( pGroup->ubSectorX == pLocGroup->ubSectorX && pGroup->ubSectorY == pLocGroup->ubSectorY ) { - if( pGroup->pEnemyGroup->ubAdminsInBattle || pGroup->pEnemyGroup->ubTroopsInBattle || pGroup->pEnemyGroup->ubElitesInBattle || pGroup->pEnemyGroup->ubTanksInBattle ) + if ( pGroup->pEnemyGroup->ubAdminsInBattle || pGroup->pEnemyGroup->ubTroopsInBattle || pGroup->pEnemyGroup->ubElitesInBattle || pGroup->pEnemyGroup->ubTanksInBattle || pGroup->pEnemyGroup->ubJeepsInBattle ) { ++ubInvalidGroups; pGroup->pEnemyGroup->ubAdminsInBattle = 0; pGroup->pEnemyGroup->ubTroopsInBattle = 0; pGroup->pEnemyGroup->ubElitesInBattle = 0; pGroup->pEnemyGroup->ubTanksInBattle = 0; + pGroup->pEnemyGroup->ubJeepsInBattle = 0; } } } @@ -251,19 +252,21 @@ 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) Ta(%02d:%02d)", + L"G(%02d:%c%d_b%d) A(%02d:%02d) T(%02d:%02d) E(%02d:%02d) C(%02d:%02d) Ta(%02d:%02d) J(%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->ubNumTanks, pSector->ubTanksInBattle ); + pSector->ubNumTanks, pSector->ubTanksInBattle, + pSector->ubNumJeeps, pSector->ubJeepsInBattle ); DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL ); pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; pSector->ubCreaturesInBattle = 0; pSector->ubTanksInBattle = 0; + pSector->ubJeepsInBattle = 0; } } #endif diff --git a/Strategic/Queen Command.cpp b/Strategic/Queen Command.cpp index 2d5e8f1e..81da3f7e 100644 --- a/Strategic/Queen Command.cpp +++ b/Strategic/Queen Command.cpp @@ -282,11 +282,11 @@ UINT8 NumNonPlayerTeamMembersInSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubT return ubNumTroops; } -UINT16 NumTanksInSector( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam ) +UINT16 NumEnemyArmedVehiclesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam ) { SECTORINFO *pSector; GROUP *pGroup; - UINT8 ubNum; + UINT16 ubNum; // HEADROCK: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution, // probably isn't. But I need this bit to work. @@ -306,18 +306,14 @@ UINT16 NumTanksInSector( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam ) pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )]; if ( usTeam == ENEMY_TEAM ) - ubNum = (UINT16)(pSector->ubNumTanks); - - // TODO - //if ( is_networked ) - //ubNumTroops += numenemyLAN( (UINT8)sSectorX, (UINT8)sSectorY ); //hayden - + ubNum = (UINT16)(pSector->ubNumTanks + pSector->ubNumJeeps); + pGroup = gpGroupList; while ( pGroup ) { if ( pGroup->usGroupTeam == usTeam && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) { - ubNum += pGroup->pEnemyGroup->ubNumTanks; + ubNum += pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps; } pGroup = pGroup->next; } @@ -383,7 +379,7 @@ UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) return ubNumTroops; } -void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ) +void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { GROUP *pGroup; SECTORINFO *pSector; @@ -393,7 +389,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 = *pubNumTanks = 0; + *pubNumTroops = *pubNumElites = *pubNumAdmins = *pubNumTanks = *pubNumJeeps =0; pGroup = gpGroupList; while( pGroup ) { @@ -403,6 +399,7 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu *pubNumElites += pGroup->pEnemyGroup->ubNumElites; *pubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins; *pubNumTanks += pGroup->pEnemyGroup->ubNumTanks; + *pubNumJeeps += pGroup->pEnemyGroup->ubNumJeeps; } pGroup = pGroup->next; } @@ -415,10 +412,11 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu *pubNumTroops += pSector->ubNumTroops; *pubNumElites += pSector->ubNumElites; *pubNumTanks += pSector->ubNumTanks; + *pubNumJeeps += pSector->ubNumJeeps; } } -void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ) +void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { GROUP *pGroup; AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE); @@ -427,7 +425,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 = *pubNumTanks = 0; + *pubNumTroops = *pubNumElites = *pubNumAdmins = *pubNumTanks = *pubNumJeeps = 0; pGroup = gpGroupList; while( pGroup ) { @@ -437,13 +435,14 @@ void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSe *pubNumElites += pGroup->pEnemyGroup->ubNumElites; *pubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins; *pubNumTanks += pGroup->pEnemyGroup->ubNumTanks; + *pubNumJeeps += pGroup->pEnemyGroup->ubNumJeeps; } pGroup = pGroup->next; } } -void GetNumberOfStationaryEnemiesInSector( 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, UINT8 *pubNumJeeps ) { SECTORINFO *pSector; AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE); @@ -457,20 +456,22 @@ void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumTroops = pSector->ubNumTroops; *pubNumElites = pSector->ubNumElites; *pubNumTanks = pSector->ubNumTanks; + *pubNumJeeps = pSector->ubNumJeeps; } -void GetNumberOfEnemiesInSector( 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, UINT8 *pubNumJeeps ) { - UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; - GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks ); + GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks, pubNumJeeps ); - GetNumberOfMobileEnemiesInSector( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + GetNumberOfMobileEnemiesInSector( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; *pubNumElites += ubNumElites; *pubNumTanks += ubNumTanks; + *pubNumJeeps += ubNumJeeps; } void EndTacticalBattleForEnemy() @@ -487,6 +488,7 @@ void EndTacticalBattleForEnemy() pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; pSector->ubTanksInBattle = 0; + pSector->ubJeepsInBattle = 0; } else if( !gbWorldSectorZ ) { @@ -497,6 +499,7 @@ void EndTacticalBattleForEnemy() pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; pSector->ubTanksInBattle = 0; + pSector->ubJeepsInBattle = 0; pSector->ubNumCreatures = 0; pSector->ubCreaturesInBattle = 0; } @@ -516,6 +519,7 @@ void EndTacticalBattleForEnemy() pGroup->pEnemyGroup->ubElitesInBattle = 0; pGroup->pEnemyGroup->ubAdminsInBattle = 0; pGroup->pEnemyGroup->ubTanksInBattle = 0; + pGroup->pEnemyGroup->ubJeepsInBattle = 0; } pGroup = pGroup->next; } @@ -570,8 +574,8 @@ BOOLEAN PrepareEnemyForSectorBattle() SECTORINFO *pSector; GROUP *pGroup; SOLDIERTYPE *pSoldier; - unsigned ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks; - unsigned ubTotalAdmins, ubTotalElites, ubTotalTroops, ubTotalTanks = 0; + unsigned ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; + unsigned ubTotalAdmins, ubTotalElites, ubTotalTroops, ubTotalTanks, ubTotalJeeps = 0; unsigned totalCountOfStationaryEnemies = 0; unsigned totalCountOfMobileEnemies = 0; int sNumSlots; @@ -627,7 +631,8 @@ BOOLEAN PrepareEnemyForSectorBattle() !pGroup->pEnemyGroup->ubAdminsInBattle && !pGroup->pEnemyGroup->ubTroopsInBattle && !pGroup->pEnemyGroup->ubElitesInBattle && - !pGroup->pEnemyGroup->ubTanksInBattle) + !pGroup->pEnemyGroup->ubTanksInBattle && + !pGroup->pEnemyGroup->ubJeepsInBattle ) { HandleArrivalOfReinforcements( pGroup ); } @@ -665,12 +670,13 @@ 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 + pSector->ubNumTanks); + float totalEnemies = (float)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps); ubTotalAdmins = (unsigned int)(((float)pSector->ubNumAdmins / totalEnemies) * mapMaximumNumberOfEnemies); ubTotalTroops = (unsigned int)(((float)pSector->ubNumTroops / totalEnemies) * mapMaximumNumberOfEnemies); ubTotalElites = (unsigned int)(((float)pSector->ubNumElites / totalEnemies) * mapMaximumNumberOfEnemies); ubTotalTanks = (unsigned int)(((float)pSector->ubNumTanks / totalEnemies) * mapMaximumNumberOfEnemies); - totalEnemies = (float)(ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks); + ubTotalJeeps = (unsigned int)(((float)pSector->ubNumJeeps / totalEnemies) * mapMaximumNumberOfEnemies); + totalEnemies = (float)(ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks + ubTotalJeeps); // take care of any rounding losses while (totalEnemies < mapMaximumNumberOfEnemies) @@ -684,10 +690,12 @@ BOOLEAN PrepareEnemyForSectorBattle() pSector->ubNumTroops = ubTotalTroops; pSector->ubNumElites = ubTotalElites; pSector->ubNumTanks = ubTotalTanks; + pSector->ubNumJeeps = ubTotalJeeps; pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; pSector->ubTanksInBattle = 0; + pSector->ubJeepsInBattle = 0; } else { @@ -706,6 +714,7 @@ BOOLEAN PrepareEnemyForSectorBattle() case SOLDIER_CLASS_ARMY: ubTotalTroops++; break; case SOLDIER_CLASS_ELITE: ubTotalElites++; break; case SOLDIER_CLASS_TANK: ubTotalTanks++; break; + case SOLDIER_CLASS_JEEP: ubTotalJeeps++; break; } } curr = curr->next; @@ -714,10 +723,12 @@ BOOLEAN PrepareEnemyForSectorBattle() pSector->ubNumTroops = ubTotalTroops; pSector->ubNumElites = ubTotalElites; pSector->ubNumTanks = ubTotalTanks; + pSector->ubNumJeeps = ubTotalJeeps; pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; pSector->ubTanksInBattle = 0; + pSector->ubJeepsInBattle = 0; } else { @@ -725,10 +736,11 @@ BOOLEAN PrepareEnemyForSectorBattle() ubTotalTroops = pSector->ubNumTroops - pSector->ubTroopsInBattle; ubTotalElites = pSector->ubNumElites - pSector->ubElitesInBattle; ubTotalTanks = pSector->ubNumTanks - pSector->ubTanksInBattle; + ubTotalJeeps = pSector->ubNumJeeps - pSector->ubJeepsInBattle; } } - totalCountOfStationaryEnemies = ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks; + totalCountOfStationaryEnemies = ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks + ubTotalJeeps; if( totalCountOfStationaryEnemies > mapMaximumNumberOfEnemies ) { @@ -743,20 +755,22 @@ BOOLEAN PrepareEnemyForSectorBattle() ubTotalTroops = min( mapMaximumNumberOfEnemies-ubTotalAdmins, ubTotalTroops ); ubTotalElites = min( mapMaximumNumberOfEnemies-ubTotalAdmins-ubTotalTroops, ubTotalElites ); ubTotalTanks = min( mapMaximumNumberOfEnemies-ubTotalAdmins-ubTotalTroops-ubTotalElites, ubTotalTanks ); + ubTotalJeeps = min( mapMaximumNumberOfEnemies - ubTotalAdmins - ubTotalTroops - ubTotalElites - ubTotalTanks, ubTotalJeeps ); } pSector->ubAdminsInBattle += ubTotalAdmins; pSector->ubTroopsInBattle += ubTotalTroops; pSector->ubElitesInBattle += ubTotalElites; pSector->ubTanksInBattle += ubTotalTanks; + pSector->ubJeepsInBattle += ubTotalJeeps; #ifdef JA2TESTVERSION if( gfOverrideSector ) { //if there are no troops in the current groups, then we're done. - if( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks ) + if ( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks && !ubTotalJeeps ) return FALSE; - AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks ); + AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks, ubTotalJeeps ); ValidateEnemiesHaveWeapons(); return TRUE; } @@ -783,7 +797,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 + ubTotalTanks; + sNumSlots -= ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks + ubTotalJeeps; //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 @@ -850,6 +864,21 @@ BOOLEAN PrepareEnemyForSectorBattle() pGroup->pEnemyGroup->ubTanksInBattle += ubNumTanks; ubTotalTanks += ubNumTanks; } + if ( sNumSlots > 0 ) + { + //Add jeeps + AssertGE( pGroup->pEnemyGroup->ubNumJeeps, pGroup->pEnemyGroup->ubJeepsInBattle ); + ubNumJeeps = pGroup->pEnemyGroup->ubNumJeeps - pGroup->pEnemyGroup->ubJeepsInBattle; + sNumSlots -= ubNumJeeps; + if ( sNumSlots < 0 ) + { //adjust the value to zero + ubNumJeeps += sNumSlots; + sNumSlots = 0; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; + } + pGroup->pEnemyGroup->ubJeepsInBattle += ubNumJeeps; + ubTotalJeeps += ubNumJeeps; + } //NOTE: //no provisions for profile troop leader or retreat groups yet. } @@ -871,12 +900,12 @@ BOOLEAN PrepareEnemyForSectorBattle() } //if there are no troops in the current groups, then we're done. - if( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks ) + if ( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks && !ubTotalJeeps ) { return FALSE; } - AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks ); + AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks, ubTotalJeeps ); //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 @@ -895,7 +924,8 @@ BOOLEAN PrepareEnemyForSectorBattle() ubNumTroops = pGroup->pEnemyGroup->ubTroopsInBattle; ubNumElites = pGroup->pEnemyGroup->ubElitesInBattle; ubNumTanks = pGroup->pEnemyGroup->ubTanksInBattle; - unsigned num = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks; + ubNumJeeps = pGroup->pEnemyGroup->ubJeepsInBattle; + unsigned num = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps; unsigned firstSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; unsigned lastSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; @@ -974,6 +1004,15 @@ BOOLEAN PrepareEnemyForSectorBattle() pSoldier->ubGroupID = pGroup->ubGroupID; } break; + case SOLDIER_CLASS_JEEP: + if ( ubNumTanks ) + { + num--; + sNumSlots--; + ubNumJeeps--; + pSoldier->ubGroupID = pGroup->ubGroupID; + } + break; } } @@ -983,6 +1022,7 @@ BOOLEAN PrepareEnemyForSectorBattle() AssertEQ( ubNumTroops , 0); AssertEQ( ubNumAdmins , 0); AssertEQ( ubNumTanks , 0); + AssertEQ( ubNumJeeps , 0); AssertEQ( num , 0);*/ } pGroup = pGroup->next; @@ -996,7 +1036,7 @@ BOOLEAN PrepareEnemyForSectorBattle() BOOLEAN PrepareEnemyForUndergroundBattle() { UNDERGROUND_SECTORINFO *pUnderground; - unsigned ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks; + unsigned ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks, ubTotalJeeps; pUnderground = gpUndergroundSectorInfoHead; while( pUnderground ) @@ -1011,14 +1051,16 @@ BOOLEAN PrepareEnemyForUndergroundBattle() ubTotalTroops = (UINT8)(pUnderground->ubNumTroops - pUnderground->ubTroopsInBattle); ubTotalElites = (UINT8)(pUnderground->ubNumElites - pUnderground->ubElitesInBattle); ubTotalTanks = (UINT8)(pUnderground->ubNumTanks - pUnderground->ubTanksInBattle); + ubTotalJeeps = (UINT8)(pUnderground->ubNumJeeps - pUnderground->ubJeepsInBattle); pUnderground->ubAdminsInBattle += ubTotalAdmins; pUnderground->ubTroopsInBattle += ubTotalTroops; pUnderground->ubElitesInBattle += ubTotalElites; pUnderground->ubTanksInBattle += ubTotalTanks; - AddSoldierInitListEnemyDefenceSoldiers( pUnderground->ubNumAdmins, pUnderground->ubNumTroops, pUnderground->ubNumElites, pUnderground->ubNumTanks ); + pUnderground->ubJeepsInBattle += ubTotalJeeps; + AddSoldierInitListEnemyDefenceSoldiers( pUnderground->ubNumAdmins, pUnderground->ubNumTroops, pUnderground->ubNumElites, pUnderground->ubNumTanks, pUnderground->ubNumJeeps ); ValidateEnemiesHaveWeapons(); } - return ( ( BOOLEAN) ( pUnderground->ubNumAdmins + pUnderground->ubNumTroops + pUnderground->ubNumElites + pUnderground->ubNumTanks > 0 ) ); + return ((BOOLEAN)(pUnderground->ubNumAdmins + pUnderground->ubNumTroops + pUnderground->ubNumElites + pUnderground->ubNumTanks + pUnderground->ubNumJeeps > 0)); } pUnderground = pUnderground->next; } @@ -1544,7 +1586,7 @@ void AddPossiblePendingEnemiesToBattle() #endif UINT8 ubSlots, ubNumAvailable; - UINT8 ubNumElites, ubNumTroops, ubNumAdmins, ubNumTanks; + UINT8 ubNumElites, ubNumTroops, ubNumAdmins, ubNumTanks, ubNumJeeps; UINT8 ubNumGroupsInSector; UINT8 ubGroupIndex; GROUP *pGroup; @@ -1639,11 +1681,12 @@ void AddPossiblePendingEnemiesToBattle() //return; } - if( pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks ) + if ( pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps ) { - ubNumElites = ubNumTroops = ubNumAdmins = ubNumTanks = 0; + ubNumElites = ubNumTroops = ubNumAdmins = ubNumTanks = ubNumJeeps = 0; - ubNumAvailable = pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks - pSector->ubElitesInBattle - pSector->ubTroopsInBattle - pSector->ubAdminsInBattle - pSector->ubTanksInBattle; + ubNumAvailable = pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps + - pSector->ubElitesInBattle - pSector->ubTroopsInBattle - pSector->ubAdminsInBattle - pSector->ubTanksInBattle - pSector->ubJeepsInBattle; while( ubNumAvailable && ubSlots ) { // So they just magically appear out of nowhere from the edge? @@ -1677,6 +1720,14 @@ void AddPossiblePendingEnemiesToBattle() ubSlots--; ubNumTanks++; } + else if ( pSector->ubJeepsInBattle < pSector->ubNumJeeps ) + { + //Add a jeep + pSector->ubJeepsInBattle++; + ubNumAvailable--; + ubSlots--; + ubNumJeeps++; + } else { AssertMsg( 0, "AddPossiblePendingEnemiesToBattle(): Logic Error -- by Kris" ); @@ -1684,7 +1735,7 @@ void AddPossiblePendingEnemiesToBattle() } - if( ubNumAdmins || ubNumTroops || ubNumElites || ubNumTanks ) + if ( ubNumAdmins || ubNumTroops || ubNumElites || ubNumTanks || ubNumJeeps ) { //This group has contributed forces, then add them now, because different //groups appear on different sides of the map. UINT8 ubStrategicInsertionCode = ubPredefinedInsertionCode; @@ -1725,7 +1776,7 @@ void AddPossiblePendingEnemiesToBattle() if( ubStrategicInsertionCode < INSERTION_CODE_NORTH ||ubStrategicInsertionCode > INSERTION_CODE_WEST ) ubStrategicInsertionCode = INSERTION_CODE_NORTH + Random( 4 ); - AddEnemiesToBattle( 0, ubStrategicInsertionCode, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, FALSE ); + AddEnemiesToBattle( 0, ubStrategicInsertionCode, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, FALSE ); gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; } } @@ -1755,7 +1806,8 @@ void AddPossiblePendingEnemiesToBattle() pGroup = pGroupInSectorList[ ubGroupIndex]; // Flugente fix: check for underflow... - UINT8 currentgroupsize = pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + pGroup->pEnemyGroup->ubTanksInBattle; + UINT8 currentgroupsize = pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + + pGroup->pEnemyGroup->ubTanksInBattle + pGroup->pEnemyGroup->ubJeepsInBattle; if ( currentgroupsize > pGroup->ubGroupSize ) ubNumAvailable = 0; else @@ -1816,25 +1868,32 @@ void AddPossiblePendingEnemiesToBattle() { //Add an elite troop pGroup->pEnemyGroup->ubElitesInBattle++; ubSlots--; - AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 1, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 1, 0, 0, FALSE ); } else if( pGroup->pEnemyGroup->ubTroopsInBattle < pGroup->pEnemyGroup->ubNumTroops ) { //Add a regular troop. pGroup->pEnemyGroup->ubTroopsInBattle++; ubSlots--; - AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 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, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 1, 0, 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 ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 0, 1, 0, FALSE ); + } + else if ( pGroup->pEnemyGroup->ubJeepsInBattle < pGroup->pEnemyGroup->ubNumJeeps ) + { + //Add a jeep + pGroup->pEnemyGroup->ubJeepsInBattle++; + ubSlots--; + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 0, 0, 1, FALSE ); } else { @@ -1843,7 +1902,7 @@ void AddPossiblePendingEnemiesToBattle() pGroup->pEnemyGroup->ubTroopsInBattle++; ubSlots--; - AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 0, 0, FALSE ); } } @@ -1913,7 +1972,7 @@ void NotifyPlayersOfNewEnemies() } } -void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, BOOLEAN fMagicallyAppeared ) +void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, BOOLEAN fMagicallyAppeared ) { SOLDIERTYPE *pSoldier; MAPEDGEPOINTINFO MapEdgepointInfo; @@ -1946,6 +2005,8 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub pSector->ubElitesInBattle += ubNumElites; pSector->ubNumTanks += ubNumTanks; pSector->ubTanksInBattle += ubNumTanks; + pSector->ubNumJeeps += ubNumJeeps; + pSector->ubJeepsInBattle += ubNumJeeps; } else { @@ -1960,13 +2021,15 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub pSector->ubElitesInBattle += ubNumElites; pSector->ubNumTanks += ubNumTanks; pSector->ubTanksInBattle += ubNumTanks; + pSector->ubNumJeeps += ubNumJeeps; + pSector->ubJeepsInBattle += ubNumJeeps; } } //Because the enemies magically appeared, have one of our soldiers say something... NotifyPlayersOfNewEnemies(); } - ubTotalSoldiers = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks; + ubTotalSoldiers = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps; #ifdef JA2UB if( gsGridNoForMapEdgePointInfo != -1 ) @@ -2093,6 +2156,30 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub } UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 ); } + else if ( ubNumJeeps && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumTroops + ubNumAdmins + ubNumTanks + ubNumJeeps) && ubNumberOfVehicles < 9 ) + { + ubNumJeeps--; + ubTotalSoldiers--; + Assert( pSoldier = TacticalCreateEnemyJeep( ) ); + 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) { @@ -2808,7 +2895,8 @@ BOOLEAN CheckPendingNonPlayerTeam( UINT8 usTeam ) if ( usTeam == ENEMY_TEAM ) { - if( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks) > ( pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle + pSector->ubTanksInBattle) ) + if ( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps) > + (pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle + pSector->ubTanksInBattle + pSector->ubJeepsInBattle) ) return TRUE; } @@ -2821,7 +2909,8 @@ BOOLEAN CheckPendingNonPlayerTeam( UINT8 usTeam ) { if ( usTeam == ENEMY_TEAM ) { - if ( pGroup->ubGroupSize > pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + pGroup->pEnemyGroup->ubTanksInBattle ) + if ( pGroup->ubGroupSize > pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + + pGroup->pEnemyGroup->ubTanksInBattle + pGroup->pEnemyGroup->ubJeepsInBattle ) return TRUE; } else if ( usTeam == MILITIA_TEAM ) diff --git a/Strategic/Queen Command.h b/Strategic/Queen Command.h index ea82bdba..b8bb92ad 100644 --- a/Strategic/Queen Command.h +++ b/Strategic/Queen Command.h @@ -22,13 +22,13 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ); // returns how many members of a team are in a sector - not intended for OUR_TEAM! UINT8 NumNonPlayerTeamMembersInSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubTeam ); -UINT16 NumTanksInSector( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam ); +UINT16 NumEnemyArmedVehiclesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam ); UINT8 NumStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY ); UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY ); -void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ); -void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, 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 ); +void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); +void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); +void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); +void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); //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 @@ -36,7 +36,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, UINT8 ubNumTanks, BOOLEAN fMagicallyAppeared ); +void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 abNumJeeps, BOOLEAN fMagicallyAppeared ); void AddMilitiaToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumGreens, UINT8 ubNumRegulars, UINT8 ubNumElites, BOOLEAN fMagicallyAppeared ); void AddPossiblePendingEnemiesToBattle(); void EndTacticalBattleForEnemy(); diff --git a/Strategic/Reinforcement.cpp b/Strategic/Reinforcement.cpp index b0060f34..c40b056d 100644 --- a/Strategic/Reinforcement.cpp +++ b/Strategic/Reinforcement.cpp @@ -33,20 +33,21 @@ UINT8 gubReinforcementMinEnemyStaticGroupSize = 12; UINT32 guiMilitiaReinforceTurn = 0, guiMilitiaArrived = 0;//dnl ch68 090913 -void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ) +void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { - UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; UINT16 pusMoveDir[4][3]; //first column in this matrix is number of sector, except for 4th row UINT8 ubDirNumber, ubIndex; - GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks ); + GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks, pubNumJeeps ); - GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; *pubNumElites += ubNumElites; *pubNumTanks += ubNumTanks; + *pubNumJeeps += ubNumJeeps; if( !gGameExternalOptions.gfAllowReinforcements ) return; @@ -56,21 +57,23 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir, FALSE, TRUE ); - for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ ) + for( ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex ) { //take number of the involved sector, find its X and Y coordintes and then ask for number of troops there - GetNumberOfStationaryEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + GetNumberOfStationaryEnemiesInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); - while( ubNumElites + ubNumTroops + ubNumAdmins + ubNumTanks > gubReinforcementMinEnemyStaticGroupSize) //count how many of static group will reinforce the battle, but leave minimal group size to guard + while ( ubNumElites + ubNumTroops + ubNumAdmins + ubNumTanks + ubNumJeeps > gubReinforcementMinEnemyStaticGroupSize ) //count how many of static group will reinforce the battle, but leave minimal group size to guard { if( ubNumElites ) { *pubNumElites += 1; ubNumElites--; - }else if( ubNumTroops ) + } + else if( ubNumTroops ) { *pubNumTroops += 1; ubNumTroops--; - }else if( ubNumAdmins ) + } + else if( ubNumAdmins ) { *pubNumAdmins += 1; ubNumAdmins--; @@ -80,24 +83,30 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub *pubNumTanks += 1; ubNumTanks--; } + else if ( ubNumJeeps ) + { + *pubNumJeeps += 1; + ubNumJeeps--; + } } - GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; *pubNumElites += ubNumElites; *pubNumTanks += ubNumTanks; + *pubNumJeeps += ubNumJeeps; } } UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY ) { - UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; - GetNumberOfEnemiesInFiveSectors( sMapX, sMapY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + GetNumberOfEnemiesInFiveSectors( sMapX, sMapY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); - return ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks; + return ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps; } BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 sSectorY ) @@ -255,28 +264,35 @@ UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam (pThisSector->ubNumElites)++; (pSector->ubNumElites)--; (pThisSector->ubElitesInBattle)++; - AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 1, 0, FALSE ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 1, 0, 0, FALSE ); } else if( pSector->ubNumTroops ) { (pThisSector->ubNumTroops)++; (pSector->ubNumTroops)--; (pThisSector->ubTroopsInBattle)++; - AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 1, 0, 0, FALSE ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 1, 0, 0, 0, FALSE ); } else if( pSector->ubNumAdmins ) { (pThisSector->ubNumAdmins)++; (pSector->ubNumAdmins)--; (pThisSector->ubAdminsInBattle)++; - AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 1, 0, 0, 0, FALSE ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 1, 0, 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 ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 0, 1, 0, FALSE ); + } + else if ( pSector->ubNumJeeps ) + { + (pThisSector->ubNumJeeps)++; + (pSector->ubNumJeeps)--; + (pThisSector->ubJeepsInBattle)++; + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ubIndex][2], 0, 0, 0, 0, 1, FALSE ); } return (UINT8)pusMoveDir[ ubIndex ][ 2 ]; diff --git a/Strategic/Reinforcement.h b/Strategic/Reinforcement.h index 2ea84467..e4a57807 100644 --- a/Strategic/Reinforcement.h +++ b/Strategic/Reinforcement.h @@ -2,7 +2,7 @@ #define __REINFORCEMENT_H__ //For Autoresolve (mostly) -void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ); +void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 sSectorY ); UINT8 GetAdjacentSectors( UINT8 pSectors[4], INT16 sSectorX, INT16 sSectorY ); UINT8 CountAllMilitiaInFiveSectors(INT16 sMapX, INT16 sMapY); diff --git a/Strategic/Strategic AI.cpp b/Strategic/Strategic AI.cpp index f4c4109d..f2a96a02 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -468,7 +468,7 @@ BOOLEAN SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup ); void ClearPreviousAIGroupAssignment( GROUP *pGroup ); -void CalcNumTroopsBasedOnComposition( UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 ubTotal, INT32 iCompositionID ); +void CalcNumTroopsBasedOnComposition( UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 ubTotal, INT32 iCompositionID ); void ConvertGroupTroopsToComposition( GROUP *pGroup, INT32 iCompositionID ); void RemoveSoldiersFromGarrisonBasedOnComposition( INT32 iGarrisonID, UINT8 ubSize ); @@ -550,28 +550,28 @@ INT32 GarrisonReinforcementsRequested( INT32 iGarrisonID, UINT8 *pubExtraReinfor INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic1"); - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ - pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; - iExistingForces = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; + iExistingForces = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; 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 //until it is finally excepted or an absolute max is made. - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - iExtraReinforcements = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - iExtraReinforcements = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - iExtraReinforcements = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - iExtraReinforcements = 4; - else - { - iExtraReinforcements = Random (4); - if (iExtraReinforcements == 0) iExtraReinforcements = 1; - } + if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) + iExtraReinforcements = 1; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) + iExtraReinforcements = 2; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) + iExtraReinforcements = 3; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) + iExtraReinforcements = 4; + else + { + iExtraReinforcements = Random (4); + if (iExtraReinforcements == 0) iExtraReinforcements = 1; + } *pubExtraReinforcements = (UINT8)(gubGarrisonReinforcementsDenied[ iGarrisonID ] / (6 - iExtraReinforcements)); //*pubExtraReinforcements = (UINT8)(gubGarrisonReinforcementsDenied[ iGarrisonID ] / (6 - gGameOptions.ubDifficultyLevel)); @@ -605,8 +605,8 @@ 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 + pSector->ubNumTanks; + pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; + iReinforcementsAvailable = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps; iReinforcementsAvailable -= gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation; switch( gGarrisonGroup[ iGarrisonID ].ubComposition ) @@ -685,7 +685,7 @@ BOOLEAN AdjacentSectorIsImportantAndUndefended( UINT8 ubSectorID ) pSector = &SectorInfo[ ubSectorID ]; - if( pSector->ubNumTroops || pSector->ubNumElites || pSector->ubNumAdmins || pSector->ubNumTanks ) + if ( pSector->ubNumTroops || pSector->ubNumElites || pSector->ubNumAdmins || pSector->ubNumTanks || pSector->ubNumJeeps ) { return FALSE; } @@ -827,7 +827,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic2"); } } #ifdef JA2BETAVERSION - if( pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks != pGroup->ubGroupSize || + if ( pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps != pGroup->ubGroupSize || pGroup->ubGroupSize > iMaxEnemyGroupSize ) { SAIReportError( L"Strategic AI: Internal error (bad group populations). Please send PRIOR save file and Strategic Decisions.txt." ); @@ -1132,7 +1132,7 @@ void InitStrategicAI() SECTORINFO *pSector = NULL; GROUP *pGroup; UINT8 ubNumTroops; - UINT8 ubNumTanks; + UINT8 ubNumTanks, ubNumJeeps; INT32 iPercentElitesBonus; INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic3"); @@ -1436,9 +1436,9 @@ void InitStrategicAI() } // fill up deficit with admins if total enemies less than min enemy group size - if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks < gubMinEnemyGroupSize ) + if ( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps < gubMinEnemyGroupSize ) { - pSector->ubNumAdmins = gubMinEnemyGroupSize - pSector->ubNumTroops - pSector->ubNumElites - pSector->ubNumTanks; + pSector->ubNumAdmins = gubMinEnemyGroupSize - pSector->ubNumTroops - pSector->ubNumElites - pSector->ubNumTanks - pSector->ubNumJeeps; } //Calculate weight (range is -20 to +20 before multiplier). @@ -1485,7 +1485,7 @@ void InitStrategicAI() } //Now, initialize each of the patrol groups - for( i = 0; i < giPatrolArraySize; i++ ) + for( i = 0; i < giPatrolArraySize; ++i ) { // IGNORE COMMENT, FEATURE REMOVED! //Some of the patrol groups aren't there at the beginning of the game. This is //based on the difficulty settings in the above patrol table. @@ -1495,8 +1495,9 @@ void InitStrategicAI() ubNumTroops = (UINT8)(gPatrolGroup[ i ].bSize + Random( 3 ) - 1); ubNumTroops = (UINT8)max( gubMinEnemyGroupSize, min( iMaxEnemyGroupSize, ubNumTroops ) ); ubNumTanks = 0; + ubNumJeeps = 0; - if ( ubNumTroops && gGameExternalOptions.fArmyUsesTanksInPatrols && HighestPlayerProgressPercentage() >= gGameExternalOptions.usTankMinimumProgress ) + if ( ubNumTroops ) { UINT32 val2; if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) @@ -1515,8 +1516,16 @@ void InitStrategicAI() if ( Random( 10 ) < val2 && i != 3 && i != 4 ) { - ubNumTroops--; - ubNumTanks++; + if ( gGameExternalOptions.fArmyUsesJeepsInPatrols && ASDSoldierUpgradeToJeep( ) ) + { + ubNumTroops--; + ubNumJeeps++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInPatrols && ASDSoldierUpgradeToTank( ) ) + { + ubNumTroops--; + ubNumTanks++; + } } } @@ -1524,7 +1533,7 @@ void InitStrategicAI() //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, ubNumTanks ); + pGroup = CreateNewEnemyGroupDepartingFromSector( gPatrolGroup[ i ].ubSectorID[ 1 ], 0, ubNumTroops, 0, ubNumTanks, ubNumJeeps ); Assert( pGroup ); if( i == 3 || i == 4 ) @@ -1859,7 +1868,8 @@ BOOLEAN HandlePlayerGroupNoticedByPatrolGroup( GROUP *pPlayerGroup, GROUP *pEnem usOffensePoints = pEnemyGroup->pEnemyGroup->ubNumAdmins * 2 + pEnemyGroup->pEnemyGroup->ubNumTroops * 4 + pEnemyGroup->pEnemyGroup->ubNumElites * 6 + - pEnemyGroup->pEnemyGroup->ubNumTanks * 20; + pEnemyGroup->pEnemyGroup->ubNumTanks * 20 + + pEnemyGroup->pEnemyGroup->ubNumJeeps * 12; if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) ) { RequestAttackOnSector( ubSectorID, usDefencePoints ); @@ -1912,19 +1922,20 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID ) usOffensePoints = pSector->ubNumAdmins * 2 + pSector->ubNumTroops * 4 + pSector->ubNumElites * 6 + - pSector->ubNumTanks * 20; + pSector->ubNumTanks * 20 + + pSector->ubNumJeeps * 12; if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) ) { RequestAttackOnSector( ubSectorID, usDefencePoints ); return; } - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ 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 + pSector->ubNumTanks); + ubEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps); if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) iReinforcementsApproved = (ubEnemies - gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation ); else @@ -1932,7 +1943,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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ); @@ -1941,12 +1952,12 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID ) if ( pGroup ) RemoveSoldiersFromGarrisonBasedOnComposition( pSector->ubGarrisonID, pGroup->ubGroupSize ); - if( pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks > iMaxEnemyGroupSize ) + if ( pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps > 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 + pSector->ubNumTanks, iMaxEnemyGroupSize ); + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps, iMaxEnemyGroupSize ); #endif } @@ -1969,7 +1980,8 @@ BOOLEAN HandleMilitiaNoticedByPatrolGroup( UINT8 ubSectorID, GROUP *pEnemyGroup usOffensePoints = pEnemyGroup->pEnemyGroup->ubNumAdmins * 2 + pEnemyGroup->pEnemyGroup->ubNumTroops * 4 + pEnemyGroup->pEnemyGroup->ubNumElites * 6 + - pEnemyGroup->pEnemyGroup->ubNumTanks * 20; + pEnemyGroup->pEnemyGroup->ubNumTanks * 20 + + pEnemyGroup->pEnemyGroup->ubNumJeeps * 12; if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) ) { RequestAttackOnSector( ubSectorID, usDefencePoints ); @@ -2118,11 +2130,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 + pSector->ubNumTanks; + ubAvailableTroops = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps; 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubGarrisonSectorID, 0, (UINT8)(ubAvailableTroops / 2), 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ ubDstGarrisonID ].ubComposition ); RemoveSoldiersFromGarrisonBasedOnComposition( ubSrcGarrisonID, pGroup->ubGroupSize ); gGarrisonGroup[ ubDstGarrisonID ].ubPendingGroupID = pGroup->ubGroupID; @@ -2228,11 +2240,12 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); pSector->ubNumTroops = (UINT8)(pSector->ubNumTroops + pGroup->pEnemyGroup->ubNumTroops); pSector->ubNumElites = (UINT8)(pSector->ubNumElites + pGroup->pEnemyGroup->ubNumElites); pSector->ubNumTanks = (UINT8)(pSector->ubNumTanks + pGroup->pEnemyGroup->ubNumTanks); + pSector->ubNumJeeps = (UINT8)(pSector->ubNumJeeps + pGroup->pEnemyGroup->ubNumJeeps); #ifdef JA2BETAVERSION LogStrategicEvent( "%d reinforcements have arrived to garrison sector %c%d", pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + - pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX ); + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX ); #endif if( IsThisSectorASAMSector( pGroup->ubSectorX, pGroup->ubSectorY, 0 ) ) @@ -2305,10 +2318,12 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); pPatrolGroup->pEnemyGroup->ubNumElites += pGroup->pEnemyGroup->ubNumElites; pPatrolGroup->pEnemyGroup->ubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins; pPatrolGroup->pEnemyGroup->ubNumTanks += pGroup->pEnemyGroup->ubNumTanks; - pPatrolGroup->ubGroupSize += (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks); + pPatrolGroup->pEnemyGroup->ubNumJeeps += pGroup->pEnemyGroup->ubNumJeeps; + pPatrolGroup->ubGroupSize += (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps); #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->ubNumTanks, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps, pPatrolGroup->ubSectorY + 'A' - 1, pPatrolGroup->ubSectorX, pPatrolGroup->ubGroupSize ); #endif if( pPatrolGroup->ubGroupSize > iMaxEnemyGroupSize ) @@ -2347,12 +2362,18 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); pGroup->pEnemyGroup->ubNumTanks--; pPatrolGroup->pEnemyGroup->ubNumTanks--; } + else if ( pGroup->pEnemyGroup->ubNumJeeps ) + { + pGroup->pEnemyGroup->ubNumJeeps--; + pPatrolGroup->pEnemyGroup->ubNumJeeps--; + } } pPatrolGroup->ubGroupSize = iMaxEnemyGroupSize; Assert( pPatrolGroup->pEnemyGroup->ubNumAdmins + pPatrolGroup->pEnemyGroup->ubNumTroops + pPatrolGroup->pEnemyGroup->ubNumElites + - pPatrolGroup->pEnemyGroup->ubNumTanks == iMaxEnemyGroupSize ); + pPatrolGroup->pEnemyGroup->ubNumTanks + + pPatrolGroup->pEnemyGroup->ubNumJeeps == iMaxEnemyGroupSize ); } RemovePGroup( pGroup ); RecalculatePatrolWeight( i ); @@ -2378,7 +2399,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->ubNumTanks, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX ); #endif RecalculatePatrolWeight( i ); @@ -2553,7 +2574,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup ) return FALSE; } pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY-1 ) ]; - ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY-1 ) ); @@ -2569,7 +2590,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 + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX+1, pPlayerGroup->ubSectorY ) ); @@ -2585,7 +2606,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup ) return FALSE; } pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY+1 ) ]; - ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY+1 ) ); @@ -2601,7 +2622,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup ) return FALSE; } pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX-1, pPlayerGroup->ubSectorY ) ]; - ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX-1, pPlayerGroup->ubSectorY ) ); @@ -2665,7 +2686,8 @@ void CheckEnemyControlledSector( UINT8 ubSectorID ) } } } - if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks ) + + if ( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps ) { //The sector is still controlled, so look around to see if there are any players nearby. @@ -2820,7 +2842,7 @@ void RecalculateGarrisonWeight( INT32 iGarrisonID ) pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; iDesiredPop = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation; - iCurrentPop = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + iCurrentPop = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; iPriority = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bPriority; //First, remove the previous weight from the applicable field. @@ -3058,7 +3080,7 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi #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->ubNumTanks, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX, ubDstSectorY + 'A' - 1, ubDstSectorX ); #endif @@ -3118,7 +3140,7 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi } } - pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ iDstGarrisonID ].ubComposition ); pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY ); //Madd: unlimited reinforcements? @@ -3128,7 +3150,7 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi pGroup->ubMoveType = ONE_WAY; gGarrisonGroup[ iDstGarrisonID ].ubPendingGroupID = pGroup->ubGroupID; - ubGroupSize = (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks); + ubGroupSize = (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps); if( ubNumExtraReinforcements ) { @@ -3208,13 +3230,13 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi } } - pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 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 + pGroup->pEnemyGroup->ubNumTanks ); + ubGroupSize = (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps); if( ubNumExtraReinforcements ) { @@ -3280,7 +3302,7 @@ BOOLEAN 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->ubNumTanks, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX, ubDstSectorY + 'A' - 1, ubDstSectorX ); #endif @@ -3298,7 +3320,7 @@ BOOLEAN SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup ) { //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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0, 0 ); pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY ); //Madd: unlimited reinforcements? @@ -3309,7 +3331,7 @@ BOOLEAN 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->ubNumTanks, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps, ubDstSectorY + 'A' - 1, ubDstSectorX ); #endif @@ -3349,7 +3371,7 @@ BOOLEAN SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup ) if ( !iReinforcementsApproved ) continue; - pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0 ); pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY ); gPatrolGroup[ iPatrolID ].ubPendingGroupID = pGroup->ubGroupID; @@ -3357,7 +3379,7 @@ BOOLEAN 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->ubNumTanks, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps, ubSrcSectorY + 'A' - 1, ubSrcSectorX, ubDstSectorY + 'A' - 1, ubDstSectorX ); #endif @@ -4449,9 +4471,12 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto UINT8 assaultsector0, assaultsector1, assaultsector2, assaultsector3; unsigned ubNumSoldiers; UINT8 ubNumTanks = 0; + UINT8 ubNumJeeps = 0; + UINT32 totalusedsoldiers = 0; UINT32 grouptroops[4] = {0,0,0,0}; UINT32 groupelites[4] = {0,0,0,0}; UINT32 grouptanks[4] = {0,0,0,0}; + UINT32 groupjeeps[4] = {0, 0, 0, 0}; switch( usActionCode ) { @@ -4531,46 +4556,59 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); UINT8 val; - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - val = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - val = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - val = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - val = 4; - else - { - val = Random (4); - if (val == 0) val = 1; - } - - ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + val * 3); - //ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3); - // anv: replace one of soldiers with tank - for( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) + if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) + val = 1; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) + val = 2; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) + val = 3; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) + val = 4; + else { - grouptroops[ubCounter] = ubNumSoldiers; - grouptanks[ubCounter] = 0; - if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks && HighestPlayerProgressPercentage() >= gGameExternalOptions.usTankMinimumProgress ) + val = Random (4); + if (val == 0) + val = 1; + } + + ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + val * 3); + + // anv: replace one of soldiers with tank + if ( ubNumSoldiers ) + { + for( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) { - if ( Random( 10 ) < val && ASDSoldierUpgradeToTank( ) ) + grouptroops[ubCounter] = ubNumSoldiers; + groupelites[ubCounter] = 0; + grouptanks[ubCounter] = 0; + groupjeeps[ubCounter] = 0; + + if ( Random( 10 ) < val ) { - grouptroops[ubCounter]--; - grouptanks[ubCounter]++; + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[ubCounter]--; + groupjeeps[ubCounter]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[ubCounter]--; + grouptanks[ubCounter]++; + } } + + if ( val > 0 ) + groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / val; + + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } } - pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], grouptroops[0] - grouptroops[0] / val, grouptanks[0] ); - pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], grouptroops[1] - grouptroops[1] / val, grouptanks[1] ); - pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], grouptroops[2] - grouptroops[2] / val, grouptanks[2] ); - pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], grouptroops[3] - grouptroops[3] / val, grouptanks[3] ); - /* - 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] ); - */ + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouptanks[3], groupjeeps[3] ); + if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { pGroup0->pEnemyGroup->ubIntention = STAGE; @@ -4590,10 +4628,12 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto } //Madd: unlimited reinforcements? - //if ( !gfUnlimitedTroops ) - // giReinforcementPool -= ubNumSoldiers; + if ( !gfUnlimitedTroops ) + { + giReinforcementPool -= totalusedsoldiers; - giReinforcementPool = max( giReinforcementPool, 0 ); + giReinforcementPool = max( giReinforcementPool, 0 ); + } MoveSAIGroupToSector( &pGroup0, SEC_D14, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); MoveSAIGroupToSector( &pGroup1, SEC_E13, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); @@ -4615,45 +4655,53 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto } UINT8 value; - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - value = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - value = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - value = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - value = 4; - else - { - value = Random (4); - if (value == 0) value = 1; - } + if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) + value = 1; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) + value = 2; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) + value = 3; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) + value = 4; + else + { + value = Random (4); + if (value == 0) value = 1; + } ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + value * 3); - //ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3); + // anv: replace one of soldiers with tank for( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) { - grouptroops[ubCounter] = ubNumSoldiers; + grouptroops[ubCounter] = ubNumSoldiers; + groupelites[ubCounter] = 0; grouptanks[ubCounter] = 0; - if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks && HighestPlayerProgressPercentage() >= gGameExternalOptions.usTankMinimumProgress ) + groupjeeps[ubCounter] = 0; + + if( ubNumSoldiers ) { - if ( Random( 10 ) < value && ASDSoldierUpgradeToTank( ) ) + if ( Random( 10 ) < value ) { - grouptroops[ubCounter]--; - grouptanks[ubCounter]++; + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[ubCounter]--; + groupjeeps[ubCounter]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[ubCounter]--; + grouptanks[ubCounter]++; + } } } - groupelites[ubCounter] = 0; + if ( value > 0 ) groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / value; - //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); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + } + switch( usActionCode ) { case NPC_ACTION_SEND_SOLDIERS_TO_CHITZENA: @@ -4778,10 +4826,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto break; } - 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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( stagesector0, 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( stagesector1, 0, grouptroops[1], groupelites[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( stagesector2, 0, grouptroops[2], groupelites[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( stagesector3, 0, grouptroops[3], groupelites[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -4791,7 +4839,6 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto pGroup3->pEnemyGroup->ubIntention = REINFORCEMENTS; gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID = pGroup3->ubGroupID; - } else { @@ -4809,9 +4856,11 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto //Madd: unlimited reinforcements? if ( !gfUnlimitedTroops ) + { giReinforcementPool -= totalusedsoldiers; - giReinforcementPool = max( giReinforcementPool, 0 ); + giReinforcementPool = max( giReinforcementPool, 0 ); + } } break; @@ -4846,38 +4895,50 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto { value2 = Random (4); if (value2 == 0) value2 = 1; - } - ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + value2 * 3); - //ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3); - // anv: replace one of soldiers with tank - if ( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks && HighestPlayerProgressPercentage( ) >= gGameExternalOptions.usTankMinimumProgress && ASDSoldierUpgradeToTank( ) ) - { - ubNumSoldiers--; - ubNumTanks++; } - UINT32 grouptroops = ubNumSoldiers; - UINT32 groupelites = 0; - if ( value2 > 0 ) - //if ( gGameOptions.ubDifficultyLevel > 0 ) - groupelites = ubNumSoldiers - ubNumSoldiers / value2; - //groupelites = ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel; - UINT32 totalusedsoldiers = 0; - + ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + value2 * 3); + if ( fAttack_Grumm ) { + // anv: replace one of soldiers with tank + for ( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) + { + grouptroops[ubCounter] = ubNumSoldiers; + groupelites[ubCounter] = 0; + grouptanks[ubCounter] = 0; + groupjeeps[ubCounter] = 0; + + if ( ubNumSoldiers ) + { + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[ubCounter]--; + groupjeeps[ubCounter]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[ubCounter]--; + grouptanks[ubCounter]++; + } + } + + if ( value2 > 0 ) + groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / value2; + + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + } + ubSourceSectorID = SEC_M6; ubTargetSectorID = SEC_H3; if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); - 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 + ubNumTanks, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[1], groupelites[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[2], groupelites[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -4906,6 +4967,34 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto if ( fAttack_Cambria ) { + // anv: replace one of soldiers with tank + for ( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) + { + grouptroops[ubCounter] = ubNumSoldiers; + groupelites[ubCounter] = 0; + grouptanks[ubCounter] = 0; + groupjeeps[ubCounter] = 0; + + if ( ubNumSoldiers ) + { + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[ubCounter]--; + groupjeeps[ubCounter]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[ubCounter]--; + grouptanks[ubCounter]++; + } + } + + if ( value2 > 0 ) + groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / value2; + + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + } + ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); // if the SAM was liberated by the player, we cannot stage there... @@ -4929,13 +5018,11 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto assaultsector3 = SEC_H9; } - 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 + ubNumTanks, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize); - + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouptanks[3], groupjeeps[3] ); + if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { pGroup0->pEnemyGroup->ubIntention = STAGE; @@ -4963,18 +5050,44 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto if ( fAttack_Alma ) { + // anv: replace one of soldiers with tank + for ( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) + { + grouptroops[ubCounter] = ubNumSoldiers; + groupelites[ubCounter] = 0; + grouptanks[ubCounter] = 0; + groupjeeps[ubCounter] = 0; + + if ( ubNumSoldiers ) + { + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[ubCounter]--; + groupjeeps[ubCounter]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[ubCounter]--; + grouptanks[ubCounter]++; + } + } + + if ( value2 > 0 ) + groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / value2; + + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + } + ubSourceSectorID = SEC_M6; ubTargetSectorID = SEC_I13; if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); - 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 + ubNumTanks, (UINT32)gGameExternalOptions.iMaxEnemyGroupSize); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -4984,7 +5097,6 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto pGroup3->pEnemyGroup->ubIntention = REINFORCEMENTS; gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID = pGroup3->ubGroupID; - } else { @@ -5003,18 +5115,44 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto if ( fAttack_Balime ) { + // anv: replace one of soldiers with tank + for ( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) + { + grouptroops[ubCounter] = ubNumSoldiers; + groupelites[ubCounter] = 0; + grouptanks[ubCounter] = 0; + groupjeeps[ubCounter] = 0; + + if ( ubNumSoldiers ) + { + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[ubCounter]--; + groupjeeps[ubCounter]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[ubCounter]--; + grouptanks[ubCounter]++; + } + } + + if ( value2 > 0 ) + groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / value2; + + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + } + ubSourceSectorID = SEC_M2; ubTargetSectorID = SEC_L11; if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); - 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); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -5043,6 +5181,34 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto if ( fAttack_Chitzena ) { + // anv: replace one of soldiers with tank + for ( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) + { + grouptroops[ubCounter] = ubNumSoldiers; + groupelites[ubCounter] = 0; + grouptanks[ubCounter] = 0; + groupjeeps[ubCounter] = 0; + + if ( ubNumSoldiers ) + { + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[ubCounter]--; + groupjeeps[ubCounter]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[ubCounter]--; + grouptanks[ubCounter]++; + } + } + + if ( value2 > 0 ) + groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / value2; + + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + } + ubSourceSectorID = SEC_H2; ubTargetSectorID = SEC_B2; @@ -5050,12 +5216,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, 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); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -5085,9 +5249,11 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto //Madd: unlimited reinforcements? if ( !gfUnlimitedTroops ) + { giReinforcementPool -= totalusedsoldiers; - giReinforcementPool = max( giReinforcementPool, 0 ); + giReinforcementPool = max( giReinforcementPool, 0 ); + } } break; @@ -5097,39 +5263,62 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto ubSectorID = (UINT8)STRATEGIC_INDEX_TO_SECTOR_INFO( sWorldSectorLocationOfFirstBattle ); pSector = &SectorInfo[ ubSectorID ]; - UINT8 value4; - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - value4 = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - value4 = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - value4 = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - value4 = 4; - else - { - value4 = Random (4); - if (value4 == 0) value4 = 1; - } - ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + value4 * 4); - //ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 4); - // anv: replace one of soldiers with tank - if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks && HighestPlayerProgressPercentage() >= gGameExternalOptions.usTankMinimumProgress ) + UINT8 value2; + if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) + value2 = 1; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) + value2 = 2; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) + value2 = 3; + else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) + value2 = 4; + else { - if ( Random( 10 ) < value4 && ASDSoldierUpgradeToTank( ) ) - { - ubNumSoldiers--; - ubNumTanks++; - } + value2 = Random( 4 ); + + if ( value2 == 0 ) + value2 = 1; } - pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubNumSoldiers, 0, ubNumTanks ); + ubNumSoldiers = (UINT8)(gubMinEnemyGroupSize + value2 * 4); + + // anv: replace one of soldiers with tank + if ( ubNumSoldiers ) + { + grouptroops[0] = ubNumSoldiers; + groupelites[0] = 0; + grouptanks[0] = 0; + groupjeeps[0] = 0; + + if ( ubNumSoldiers ) + { + if ( Random( 10 ) < value2 ) + { + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + grouptroops[0]--; + groupjeeps[0]++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + grouptroops[0]--; + grouptanks[0]++; + } + } + } + + totalusedsoldiers += grouptroops[0] + groupelites[0] + grouptanks[0] + groupjeeps[0]; + } + + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); //Madd: unlimited reinforcements? if ( !gfUnlimitedTroops ) - giReinforcementPool -= ( ubNumSoldiers + ubNumTanks ); + { + giReinforcementPool -= totalusedsoldiers; - giReinforcementPool = max( giReinforcementPool, 0 ); + giReinforcementPool = max( giReinforcementPool, 0 ); + } //Determine if the battle location actually has a garrison assignment. If so, and the following //checks succeed, the enemies will be sent to attack and reinforce that sector. Otherwise, the @@ -5157,7 +5346,8 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto // WDS - New AI case NPC_ACTION_SEND_WEIGHTED_ASSAULT_TO_LOCATION: // USES OPTIONAL PARAMETERS - if (gGameExternalOptions.useNewAI) { + if (gGameExternalOptions.useNewAI) + { // Send troops to assault the specified location. // ** 1st optional parm is a "direness" rating from the queens point of view @@ -5222,6 +5412,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto unsigned troopsThisSquad = 0; unsigned elitesThisSquad = 0; unsigned tanksThisSquad = 0; + unsigned jeepsThisSquad = 0; if (direness < 25) { adminsThisSquad = soldiersThisSquad * (40 + Random(20)) / 100; // 40-60% of total troopsThisSquad = soldiersThisSquad - adminsThisSquad; // The rest @@ -5240,16 +5431,23 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto } Assert(adminsThisSquad + troopsThisSquad + elitesThisSquad == soldiersThisSquad); // anv: replace one of soldiers with tank - if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks && HighestPlayerProgressPercentage() >= gGameExternalOptions.usTankMinimumProgress ) - { - - if ( Random( 10 * 100 ) < value5 * direness && ASDSoldierUpgradeToTank( ) ) + if( ubNumSoldiers ) + { + if ( Random( 10 * 100 ) < value5 * direness ) { - elitesThisSquad--; - tanksThisSquad++; + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + elitesThisSquad--; + jeepsThisSquad++; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + elitesThisSquad--; + tanksThisSquad++; + } } } - pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, tanksThisSquad ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, tanksThisSquad, jeepsThisSquad ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { pGroup0->pEnemyGroup->ubIntention = STAGE; if (groupCnt > 2) { @@ -5318,7 +5516,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, 0 ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, 0, 0 ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { pGroup0->pEnemyGroup->ubIntention = STAGE; if (groupCnt > 2) { @@ -5351,7 +5549,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto } ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + value6 * 6); //6, 12, or 18 based on difficulty. // 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), 0 ); //add 1 elite to normal, and 2 for hard + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubNumSoldiers, (UINT8)(ubNumSoldiers/7), 0, 0 ); //add 1 elite to normal, and 2 for hard ubNumSoldiers = (UINT8)(ubNumSoldiers + ubNumSoldiers / 7); //Madd: unlimited reinforcements @@ -5396,17 +5594,25 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto giReinforcementPool -= ubNumSoldiers; // anv: replace one of soldiers with tank - if( ubNumSoldiers && gGameExternalOptions.fArmyUsesTanksInAttacks && HighestPlayerProgressPercentage() >= gGameExternalOptions.usTankMinimumProgress ) + if( ubNumSoldiers ) { - if ( Random( 10 * 100 ) < value7 * HighestPlayerProgressPercentage( ) && ASDSoldierUpgradeToTank( ) ) + if ( Random( 10 * 100 ) < value7 * HighestPlayerProgressPercentage( ) ) { - ubNumSoldiers--; - ubNumTanks++; + if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) + { + --ubNumSoldiers; + ++ubNumJeeps; + } + else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) + { + --ubNumSoldiers; + ++ubNumTanks; + } } } giReinforcementPool = max( giReinforcementPool, 0 ); - pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, 0, ubNumSoldiers, ubNumTanks ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, 0, ubNumSoldiers, ubNumTanks, ubNumJeeps ); MoveSAIGroupToSector( &pGroup, ubSectorID, STAGE, REINFORCEMENTS ); // WANNE: This should fix the assertion in UC in the cutscene! @@ -5660,16 +5866,16 @@ void InvestigateSector( UINT8 ubSectorID ) switch( i ) { case 0: //NORTH - AddEnemiesToBattle( NULL, INSERTION_CODE_NORTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_NORTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); break; case 1: //EAST - AddEnemiesToBattle( NULL, INSERTION_CODE_EAST, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_EAST, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); break; case 2: //SOUTH - AddEnemiesToBattle( NULL, INSERTION_CODE_SOUTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_SOUTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); break; case 3: //WEST - AddEnemiesToBattle( NULL, INSERTION_CODE_WEST, ubAdmins[i], ubTroops[i], ubElites[i], 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_WEST, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); break; } } @@ -5881,7 +6087,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, 0 ); + pNewGroup = CreateNewEnemyGroupDepartingFromSector( (UINT8)SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ), 0, 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. @@ -5966,7 +6172,7 @@ void RequestHighPriorityGarrisonReinforcements( INT32 iGarrisonID, UINT8 ubSoldi if ( giReinforcementPool > 0 ) { pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), - 0, min( ubSoldiersRequested, giReinforcementPool ), 0, 0 ); + 0, min( ubSoldiersRequested, giReinforcementPool ), 0, 0, 0 ); pGroup->ubMoveType = ONE_WAY; pGroup->pEnemyGroup->ubIntention = REINFORCEMENTS; gGarrisonGroup[ iGarrisonID ].ubPendingGroupID = pGroup->ubGroupID; @@ -6004,7 +6210,7 @@ void MassFortifyTowns() for( i = 0; i < giGarrisonArraySize; i++ ) { pSector = &SectorInfo[ gGarrisonGroup[ i ].ubSectorID ]; - ubNumTroops = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + ubNumTroops = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; ubDesiredTroops = (UINT8)gArmyComp[ gGarrisonGroup[ i ].ubComposition ].bDesiredPopulation; if( ubNumTroops < ubDesiredTroops ) @@ -6037,13 +6243,13 @@ void MassFortifyTowns() void RenderAIViewerGarrisonInfo( INT32 x, INT32 y, SECTORINFO *pSector ) { - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ if( pSector->ubGarrisonID != NO_GARRISON ) { INT32 iDesired, iSurplus; iDesired = gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation; - iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites + pSector->ubNumTanks- iDesired; + iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps - iDesired; SetFontForeground( FONT_WHITE ); if( iSurplus >= 0 ) { @@ -6100,7 +6306,7 @@ BOOLEAN GarrisonCanProvideMinimumReinforcements( INT32 iGarrisonID ) pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; - iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; iDesired = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation; if( iAvailable - iDesired >= gubMinEnemyGroupSize ) @@ -6132,7 +6338,7 @@ BOOLEAN GarrisonRequestingMinimumReinforcements( INT32 iGarrisonID ) } pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; - iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; iDesired = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation; if( iDesired - iAvailable >= gubMinEnemyGroupSize ) @@ -6183,8 +6389,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 + pGroup->pEnemyGroup->ubNumTanks + - pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks; + iTotal = pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps; if( iTotal <= iMaxEnemyGroupSize ) { return; @@ -6296,6 +6502,32 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic8"); iTotal = 0; } } + else if ( pGroup->pEnemyGroup->ubNumJeeps ) + { + if ( pGroup->pEnemyGroup->ubNumJeeps < iTotal ) + { + iTotal -= pGroup->pEnemyGroup->ubNumJeeps; + pGroup->pEnemyGroup->ubNumJeeps = 0; + } + else + { + pGroup->pEnemyGroup->ubNumJeeps -= (UINT8)iTotal; + iTotal = 0; + } + } + else if ( pSector->ubNumJeeps ) + { + if ( pSector->ubNumJeeps < iTotal ) + { + iTotal -= pSector->ubNumJeeps; + pSector->ubNumJeeps = 0; + } + else + { + pSector->ubNumJeeps -= (UINT8)iTotal; + iTotal = 0; + } + } } } diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index d1b5fbdf..6e359c6e 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -700,7 +700,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, UINT8 ubNumTanks ) +GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps ) { GROUP *pNew; AssertMsg( uiSector >= 0 && uiSector <= 255, String( "CreateNewEnemyGroup with out of range value of %d", uiSector ) ); @@ -711,7 +711,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 + ubNumTanks > gGameExternalOptions.iMaxEnemyGroupSize) + while ( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps > gGameExternalOptions.iMaxEnemyGroupSize ) { if (ubNumTroops) { @@ -729,6 +729,10 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin { ubNumTanks--; } + else if ( ubNumJeeps ) + { + ubNumJeeps--; + } } pNew->pWaypoints = NULL; pNew->ubSectorX = (UINT8)SECTORX( uiSector ); @@ -743,7 +747,8 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin pNew->pEnemyGroup->ubNumTroops = ubNumTroops; pNew->pEnemyGroup->ubNumElites = ubNumElites; pNew->pEnemyGroup->ubNumTanks = ubNumTanks; - pNew->ubGroupSize = (UINT8)(ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks); + pNew->pEnemyGroup->ubNumJeeps = ubNumJeeps; + pNew->ubGroupSize = (UINT8)(ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps); pNew->ubTransportationMask = FOOT; pNew->fVehicle = FALSE; pNew->ubCreatedSectorID = pNew->ubOriginalSector; diff --git a/Strategic/Strategic Movement.h b/Strategic/Strategic Movement.h index 37c01f83..5911516c 100644 --- a/Strategic/Strategic Movement.h +++ b/Strategic/Strategic Movement.h @@ -73,7 +73,9 @@ typedef struct ENEMYGROUP // WDS - New AI UINT8 ubNumTanks; UINT8 ubTanksInBattle; - INT8 bPadding[18]; + UINT8 ubNumJeeps; + UINT8 ubJeepsInBattle; + INT8 bPadding[16]; }ENEMYGROUP; //NOTE: ALL FLAGS ARE CLEARED WHENEVER A GROUP ARRIVES IN A SECTOR, OR ITS WAYPOINTS ARE @@ -181,7 +183,7 @@ 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, UINT8 ubNumTanks ); +GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanksm, UINT8 ubNumJeeps ); GROUP* CreateNewMilitiaGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites ); diff --git a/Strategic/UndergroundInit.cpp b/Strategic/UndergroundInit.cpp index 7a83a8b3..df4735f5 100644 --- a/Strategic/UndergroundInit.cpp +++ b/Strategic/UndergroundInit.cpp @@ -89,6 +89,7 @@ BOOLEAN LuaUnderground::InitializeSectorList() sectorData.getValue("numTroops", s->ubNumTroops); sectorData.getValue("numElites", s->ubNumElites); sectorData.getValue("numTanks", s->ubNumTanks); + sectorData.getValue("numJeeps", s->ubNumJeeps ); sectorData.getValue("numBloodcats", s->ubNumBloodcats); sectorData.getValue("numCreatures", s->ubNumCreatures); @@ -106,6 +107,7 @@ BOOLEAN LuaUnderground::InitializeSectorList() m_log << "\t\tTroops: " << static_cast(s->ubNumTroops) << LF; m_log << "\t\tElites: " << static_cast(s->ubNumElites) << LF; m_log << "\t\tTanks: " << static_cast(s->ubNumTanks) << LF; + m_log << "\t\tJeeps: " << static_cast(s->ubNumJeeps) << LF; m_log << "\t- Creature population" << LF; m_log << "\t\tBloodcats: " << static_cast(s->ubNumBloodcats) << LF; m_log << "\t\tCrepitus: " << static_cast(s->ubNumCreatures) << LF; diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index 641fffeb..ca973e1c 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -5349,56 +5349,47 @@ BOOLEAN LoadStrategicInfoFromSavedFile( HWFILE hFile ) UINT32 uiNumBytesRead = 0; UINT32 uiSize = sizeof(StrategicMapElement); - - if ( guiCurrentSaveGameVersion >= MILITIA_MOVEMENT ) - { - for ( UINT16 i = 0; i < MAP_WORLD_X * MAP_WORLD_Y; ++i ) - { - // Load the strategic map information - FileRead( hFile, &StrategicMap[i], uiSize, &uiNumBytesRead ); - if ( uiNumBytesRead != uiSize ) - { - return(FALSE); - } - } - } - else - { + if ( guiCurrentSaveGameVersion < MILITIA_MOVEMENT ) uiSize = 41; - for ( UINT16 i = 0; i < MAP_WORLD_X * MAP_WORLD_Y; ++i ) - { - // Load the strategic map information - FileRead( hFile, &StrategicMap[i], uiSize, &uiNumBytesRead ); - if ( uiNumBytesRead != uiSize ) - { - return(FALSE); - } - - StrategicMap[i].usFlags = 0; - } - } - - // Load the Sector Info - for ( int sectorID = 0; sectorID <= 255; ++sectorID ) + for ( UINT16 i = 0; i < MAP_WORLD_X * MAP_WORLD_Y; ++i ) { - FileRead( hFile, &SectorInfo[sectorID], sizeof(SECTORINFO), &uiNumBytesRead ); - if ( uiNumBytesRead != sizeof(SECTORINFO) ) + // Load the strategic map information + FileRead( hFile, &StrategicMap[i], uiSize, &uiNumBytesRead ); + if ( uiNumBytesRead != uiSize ) { return(FALSE); } - // Flugente: changes in SECTORINFO require a weird-looking remapping - if ( guiCurrentSaveGameVersion < PRISONER_EXPANSION ) - { - SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_GENERAL] = 0; - SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_CIVILIAN] = 0; - SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_SECRET1] = 0; - SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_SECRET2] = 0; - SectorInfo[sectorID].ubNumTanks = SectorInfo[sectorID].uiInterrogationHundredsLeft[PRISONER_GENERAL]; - SectorInfo[sectorID].ubTanksInBattle = SectorInfo[sectorID].uiInterrogationHundredsLeft[PRISONER_CIVILIAN]; - } + if ( guiCurrentSaveGameVersion < MILITIA_MOVEMENT ) + StrategicMap[i].usFlags = 0; + } + + // Load the Sector Info + uiSize = sizeof(SECTORINFO); + if ( guiCurrentSaveGameVersion < ENEMY_JEEPS ) + uiSize = 116; + + for ( int sectorID = 0; sectorID <= 255; ++sectorID ) + { + FileRead( hFile, &SectorInfo[sectorID], uiSize, &uiNumBytesRead ); + if ( uiNumBytesRead != uiSize ) + { + return(FALSE); } + + // Flugente: changes in SECTORINFO require a weird-looking remapping + if ( guiCurrentSaveGameVersion < PRISONER_EXPANSION ) + { + SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_GENERAL] = 0; + SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_CIVILIAN] = 0; + SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_SECRET1] = 0; + SectorInfo[sectorID].uiNumberOfPrisonersOfWar[PRISONER_SECRET2] = 0; + SectorInfo[sectorID].ubNumTanks = SectorInfo[sectorID].uiInterrogationHundredsLeft[PRISONER_GENERAL]; + SectorInfo[sectorID].ubTanksInBattle = SectorInfo[sectorID].uiInterrogationHundredsLeft[PRISONER_CIVILIAN]; + } + } + // uiSize = sizeof( SECTORINFO ) * 256; // FileRead( hFile, SectorInfo, uiSize, &uiNumBytesRead ); // if( uiNumBytesRead != uiSize) diff --git a/Tactical/Animation Control.cpp b/Tactical/Animation Control.cpp index b55c7b65..dcf52a90 100644 --- a/Tactical/Animation Control.cpp +++ b/Tactical/Animation Control.cpp @@ -1118,6 +1118,7 @@ ANI_SPEED_DEF gubAnimWalkSpeeds[ TOTALBODYTYPES ] = -10, (FLOAT)4.0, //ELDORADO -10, (FLOAT)4.0, //ICECREAMTRUCK -10, (FLOAT)4.0, //JEEP + -10, (FLOAT)4.0, //COMBAT_JEEP }; extern INT16 gubMaxActionPoints[TOTALBODYTYPES] = {0}; @@ -3592,7 +3593,10 @@ void InitAnimationSurfacesPerBodytype( ) gubAnimSurfaceIndex[ TANK_NW ][ TANK_SHOOT ] = TANKNW_SHOOT; gubAnimSurfaceIndex[ TANK_NW ][ TANK_BURST ] = TANKNW_SHOOT; gubAnimSurfaceIndex[ TANK_NW ][ VEHICLE_DIE ] = TANKNW_DIE; - gubAnimSurfaceCorpseID[ TANK_NW ][ STANDING ] = TANK1_DEAD; + gubAnimSurfaceCorpseID[TANK_NW][STANDING] = TANK1_DEAD; + gubAnimSurfaceCorpseID[TANK_NW][WALKING] = TANK1_DEAD; + gubAnimSurfaceCorpseID[TANK_NW][RUNNING] = TANK1_DEAD; + gubAnimSurfaceCorpseID[TANK_NW][WALK_BACKWARDS] = TANK1_DEAD; // TANK gubAnimSurfaceIndex[ TANK_NE ][ STANDING ] = TANKNE_READY; @@ -3603,6 +3607,9 @@ void InitAnimationSurfacesPerBodytype( ) gubAnimSurfaceIndex[ TANK_NE ][ TANK_BURST ] = TANKNE_SHOOT; gubAnimSurfaceIndex[ TANK_NE ][ VEHICLE_DIE ] = TANKNE_DIE; gubAnimSurfaceCorpseID[ TANK_NE ][ STANDING ] = TANK2_DEAD; + gubAnimSurfaceCorpseID[ TANK_NE ][WALKING] = TANK2_DEAD; + gubAnimSurfaceCorpseID[ TANK_NE ][RUNNING] = TANK2_DEAD; + gubAnimSurfaceCorpseID[ TANK_NE ][WALK_BACKWARDS] = TANK2_DEAD; // ELDORADO gubAnimSurfaceIndex[ ELDORADO ][ STANDING ] = ELDORADO_BASIC; @@ -3610,21 +3617,45 @@ void InitAnimationSurfacesPerBodytype( ) gubAnimSurfaceIndex[ ELDORADO ][ RUNNING ] = ELDORADO_BASIC; gubAnimSurfaceIndex[ ELDORADO ][ WALK_BACKWARDS ] = ELDORADO_BASIC; gubAnimSurfaceIndex[ ELDORADO ][ VEHICLE_DIE ] = ELDORADO_DIE; + gubAnimSurfaceCorpseID[ELDORADO][STANDING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[ELDORADO][WALKING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[ELDORADO][RUNNING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[ELDORADO][WALK_BACKWARDS] = ICECREAM_DEAD; // ICECREAMTRUCK gubAnimSurfaceIndex[ ICECREAMTRUCK ][ STANDING ] = ICECREAMTRUCK_BASIC; gubAnimSurfaceIndex[ ICECREAMTRUCK ][ WALKING ] = ICECREAMTRUCK_BASIC; gubAnimSurfaceIndex[ ICECREAMTRUCK ][ RUNNING ] = ICECREAMTRUCK_BASIC; gubAnimSurfaceIndex[ ICECREAMTRUCK ][ WALK_BACKWARDS ] = ICECREAMTRUCK_BASIC; - gubAnimSurfaceIndex[ ICECREAMTRUCK ][ VEHICLE_DIE ] = HUMVEE_DIE; - gubAnimSurfaceCorpseID[ ICECREAMTRUCK ][ STANDING ] = ICECREAM_DEAD; + gubAnimSurfaceIndex[ ICECREAMTRUCK ][ VEHICLE_DIE ] = HUMVEE_DIE; + gubAnimSurfaceCorpseID[ICECREAMTRUCK][STANDING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[ICECREAMTRUCK][WALKING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[ICECREAMTRUCK][RUNNING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[ICECREAMTRUCK][WALK_BACKWARDS] = ICECREAM_DEAD; // JEEP gubAnimSurfaceIndex[ JEEP ][ STANDING ] = JEEP_BASIC; gubAnimSurfaceIndex[ JEEP ][ WALKING ] = JEEP_BASIC; gubAnimSurfaceIndex[ JEEP ][ RUNNING ] = JEEP_BASIC; gubAnimSurfaceIndex[ JEEP ][ WALK_BACKWARDS ] = JEEP_BASIC; - gubAnimSurfaceIndex[ JEEP ][ VEHICLE_DIE ] = JEEP_DIE; + gubAnimSurfaceIndex[ JEEP ][ VEHICLE_DIE ] = JEEP_DIE; + gubAnimSurfaceCorpseID[JEEP][STANDING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[JEEP][WALKING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[JEEP][RUNNING] = ICECREAM_DEAD; + gubAnimSurfaceCorpseID[JEEP][WALK_BACKWARDS] = ICECREAM_DEAD; + + // COMBAT_JEEP + gubAnimSurfaceIndex[COMBAT_JEEP][STANDING] = ARMED_CAR_READY; + gubAnimSurfaceIndex[COMBAT_JEEP][WALKING] = ARMED_CAR_READY; + gubAnimSurfaceIndex[COMBAT_JEEP][RUNNING] = ARMED_CAR_READY; + gubAnimSurfaceIndex[COMBAT_JEEP][WALK_BACKWARDS] = ARMED_CAR_READY; + gubAnimSurfaceIndex[COMBAT_JEEP][TANK_SHOOT] = ARMED_CAR_SHOOT; + gubAnimSurfaceIndex[COMBAT_JEEP][TANK_BURST] = ARMED_CAR_SHOOT; + gubAnimSurfaceIndex[COMBAT_JEEP][VEHICLE_DIE] = ARMED_CAR_DIE; + gubAnimSurfaceCorpseID[COMBAT_JEEP][STANDING] = HUMMER_DEAD; + gubAnimSurfaceCorpseID[COMBAT_JEEP][WALKING] = HUMMER_DEAD; + gubAnimSurfaceCorpseID[COMBAT_JEEP][RUNNING] = HUMMER_DEAD; + gubAnimSurfaceCorpseID[COMBAT_JEEP][WALK_BACKWARDS] = HUMMER_DEAD; } BOOLEAN LoadAnimationStateInstructions( ) @@ -3991,6 +4022,7 @@ INT8 GetBodyTypePaletteSubstitutionCode( SOLDIERTYPE *pSoldier, UINT8 ubBodyType case ROBOTNOWEAPON: case TANK_NW: case TANK_NE: + case COMBAT_JEEP: return( 0 ); } diff --git a/Tactical/Animation Data.cpp b/Tactical/Animation Data.cpp index 2c529dce..ad949eab 100644 --- a/Tactical/Animation Data.cpp +++ b/Tactical/Animation Data.cpp @@ -472,6 +472,10 @@ AnimationSurfaceType gAnimSurfaceDatabase[ NUMANIMATIONSURFACETYPES ] = JEEP_BASIC, "ANIMS\\VEHICLES\\JEEP.STI", S_STRUCT, ANIM_DATA_FLAG_NOFRAMES, 32, TO_INIT, NULL, NULL, 0, -1, JEEP_DIE, "ANIMS\\VEHICLES\\HM_WREK.STI", NO_STRUCT, 0, 2, TO_INIT, NULL, NULL, 0, -1, + ARMED_CAR_READY, "ANIMS\\VEHICLES\\LATV_ROT.STI", S_STRUCT, ANIM_DATA_FLAG_NOFRAMES, 32, TO_INIT, NULL, NULL, 0, -1, + ARMED_CAR_SHOOT, "ANIMS\\VEHICLES\\LATV_SHT.STI", S_STRUCT, 0, 8, TO_INIT, NULL, NULL, 0, -1, + ARMED_CAR_DIE, "ANIMS\\VEHICLES\\LATV_DIE.STI", S_STRUCT, 0, 2, TO_INIT, NULL, NULL, 0, -1, + BODYEXPLODE, "ANIMS\\S_MERC\\BOD_BLOW.STI", NO_STRUCT, 0, 1, TO_INIT, NULL, NULL, 0, -1, // crouch throwing @@ -802,6 +806,13 @@ AnimationStructureType gAnimStructureDatabase[ TOTALBODYTYPES ][ NUM_STRUCT_IDS "ANIMS\\STRUCTDATA\\JEEP.JSD", NULL, "ANIMS\\STRUCTDATA\\M_CROUCH.JSD",NULL, // default + //COMBAT_JEEP + "ANIMS\\STRUCTDATA\\HMMV.JSD", NULL, + "ANIMS\\STRUCTDATA\\HMMV.JSD", NULL, + "ANIMS\\STRUCTDATA\\HMMV.JSD", NULL, + "ANIMS\\STRUCTDATA\\HMMV.JSD", NULL, + "ANIMS\\STRUCTDATA\\HMMV.JSD", NULL, + "ANIMS\\STRUCTDATA\\M_CROUCH.JSD",NULL, // default }; diff --git a/Tactical/Animation Data.h b/Tactical/Animation Data.h index c452b135..9ddb45bd 100644 --- a/Tactical/Animation Data.h +++ b/Tactical/Animation Data.h @@ -66,6 +66,7 @@ enum SoldierBodyTypes ELDORADO, ICECREAMTRUCK, JEEP, + COMBAT_JEEP, // Flugente, smeagol & DepressivesBrot: lightly armored tactical vehicle TOTALBODYTYPES @@ -503,6 +504,10 @@ typedef enum JEEP_BASIC, JEEP_DIE, + ARMED_CAR_READY, + ARMED_CAR_SHOOT, + ARMED_CAR_DIE, + BODYEXPLODE, // crouch throwing diff --git a/Tactical/End Game.cpp b/Tactical/End Game.cpp index 3afaeabe..aaa8adef 100644 --- a/Tactical/End Game.cpp +++ b/Tactical/End Game.cpp @@ -321,6 +321,7 @@ void DoneFadeOutKilledQueen( void ) SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTroopsInBattle = 0; SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubElitesInBattle = 0; SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTanksInBattle = 0; + SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubJeepsInBattle = 0; // ATE: banish elliot... dead or alive gMercProfiles[ ELLIOT ].sSectorX = 0; diff --git a/Tactical/Enemy Soldier Save.cpp b/Tactical/Enemy Soldier Save.cpp index a008dbac..ea39d24a 100644 --- a/Tactical/Enemy Soldier Save.cpp +++ b/Tactical/Enemy Soldier Save.cpp @@ -44,7 +44,7 @@ int gCivPreservedTempFileVersion[256]; BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *pNode, GROUP *pGroup = NULL ); -BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks ); +BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); BOOLEAN gfRestoringEnemySoldiersFromTempFile = FALSE; BOOLEAN gfRestoringCiviliansFromTempFile = FALSE; @@ -105,8 +105,8 @@ BOOLEAN LoadEnemySoldiersFromTempFile() #endif INT8 bSectorZ; UINT8 ubSectorID; - UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0; - UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks; + UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0, ubNumJeeps = 0; + UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks, ubStrategicJeeps; gfRestoringEnemySoldiersFromTempFile = TRUE; @@ -255,6 +255,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile() ubStrategicTroops = pSector->ubNumTroops; ubStrategicAdmins = pSector->ubNumAdmins; ubStrategicTanks = pSector->ubNumTanks; + ubStrategicJeeps = pSector->ubNumJeeps; ubStrategicCreatures = pSector->ubNumCreatures; } else @@ -262,7 +263,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile() SECTORINFO *pSector; pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; ubStrategicCreatures = pSector->ubNumCreatures; - GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks ); + GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks, &ubStrategicJeeps ); } for( i = 0; i < slots; i++ ) @@ -359,6 +360,16 @@ BOOLEAN LoadEnemySoldiersFromTempFile() } } break; + case SOLDIER_CLASS_JEEP: + if ( COMBAT_JEEP( curr->pBasicPlacement ) ) + { + ++ubNumJeeps; + if ( ubNumJeeps < ubStrategicJeeps ) + { + AddPlacementToWorld( curr ); + } + } + break; } break; } @@ -386,14 +397,16 @@ BOOLEAN LoadEnemySoldiersFromTempFile() } //now add any extra enemies that have arrived since the temp file was made. - if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks ) + if ( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks || ubStrategicJeeps > ubNumJeeps ) { ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0; ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0; ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0; ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0; - AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks ); + ubStrategicJeeps = (ubStrategicJeeps > ubNumJeeps) ? ubStrategicJeeps - ubNumJeeps : 0; + AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks, ubStrategicJeeps ); } + if( ubStrategicCreatures > ubNumCreatures ) { ubStrategicCreatures; //not sure if this wil ever happen. If so, needs to be handled. @@ -675,8 +688,8 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() #endif INT8 bSectorZ; UINT8 ubSectorID; - UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0; - UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks; + UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0, ubNumJeeps = 0; + UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks, ubStrategicJeeps; gfRestoringEnemySoldiersFromTempFile = TRUE; @@ -716,16 +729,17 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() ubNumTroops = pSector->ubNumTroops; ubNumAdmins = pSector->ubNumAdmins; ubNumTanks = pSector->ubNumTanks; + ubNumJeeps = pSector->ubNumJeeps; ubNumCreatures = pSector->ubNumCreatures; } if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) { // Get the number of enemies form the temp file - CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicElites, &ubStrategicTroops, &ubStrategicAdmins, &ubStrategicCreatures, &ubStrategicTanks ); + CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicElites, &ubStrategicTroops, &ubStrategicAdmins, &ubStrategicCreatures, &ubStrategicTanks, &ubStrategicJeeps ); //If any of the counts differ from what is in memory - if( ubStrategicElites != ubNumElites || ubStrategicTroops != ubNumTroops || ubStrategicAdmins != ubNumAdmins || ubStrategicCreatures != ubNumCreatures || ubStrategicTanks != ubNumTanks ) + if ( ubStrategicElites != ubNumElites || ubStrategicTroops != ubNumTroops || ubStrategicAdmins != ubNumAdmins || ubStrategicCreatures != ubNumCreatures || ubStrategicTanks != ubNumTanks || ubStrategicJeeps != ubNumJeeps ) { //remove the file RemoveEnemySoldierTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); @@ -734,7 +748,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() } //reset - ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = ubNumTanks = 0; + ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = ubNumTanks = ubNumJeeps = 0; //Open the file for reading @@ -875,6 +889,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() ubStrategicTroops = pSector->ubNumTroops; ubStrategicAdmins = pSector->ubNumAdmins; ubStrategicTanks = pSector->ubNumTanks; + ubStrategicJeeps = pSector->ubNumJeeps; ubStrategicCreatures = pSector->ubNumCreatures; } else @@ -882,7 +897,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() SECTORINFO *pSector; pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; ubStrategicCreatures = pSector->ubNumCreatures; - GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks ); + GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks, &ubStrategicJeeps ); } for( i = 0; i < slots; i++ ) @@ -969,6 +984,16 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() } } break; + case SOLDIER_CLASS_JEEP: + if ( COMBAT_JEEP( curr->pBasicPlacement ) ) + { + ++ubNumJeeps; + if ( ubNumJeeps <= ubStrategicJeeps ) + { + //def: AddPlacementToWorld( curr ); + } + } + break; } break; } @@ -994,21 +1019,21 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() } //now add any extra enemies that have arrived since the temp file was made. - if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks ) + if ( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks || ubStrategicJeeps > ubNumJeeps ) { ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0; ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0; ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0; ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0; - AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks ); + ubStrategicJeeps = (ubStrategicJeeps > ubNumJeeps) ? ubStrategicJeeps - ubNumJeeps : 0; + AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks, ubStrategicJeeps ); } + if( ubStrategicCreatures > ubNumCreatures ) { ubStrategicCreatures; //not sure if this wil ever happen. If so, needs to be handled. } - - //set the number of enemies in the sector if( bSectorZ ) { @@ -1593,7 +1618,7 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY -BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks ) +BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { // SOLDIERINITNODE *curr; SOLDIERCREATE_STRUCT tempDetailedPlacement; @@ -1617,6 +1642,7 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( *pubNumRegulars = 0; *pubNumAdmins = 0; *pubNumTanks = 0; + *pubNumJeeps = 0; *pubNumCreatures = 0; //STEP ONE: Set up the temp file to read from. @@ -1785,6 +1811,12 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( (*pubNumTanks)++; } break; + case SOLDIER_CLASS_JEEP: + if ( COMBAT_JEEP( (&tempDetailedPlacement) ) ) + { + (*pubNumJeeps)++; + } + break; } /* while( curr ) diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index 845a4897..e4a6713c 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -5315,6 +5315,7 @@ void BombMessageBoxCallBack( UINT8 ubExitValue ) } } +#include "Strategic AI.h" // Flugente: callback after deciding what tactical function to use void TacticalFunctionSelectionMessageBoxCallBack( UINT8 ubExitValue ) { @@ -5356,6 +5357,8 @@ void TacticalFunctionSelectionMessageBoxCallBack( UINT8 ubExitValue ) break; case 8: + ExecuteStrategicAIAction( NPC_ACTION_SEND_SOLDIERS_TO_DRASSEN, 0, 0 ); + break; default: break; } diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index 93691197..3cb229b0 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -1156,13 +1156,21 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent ) return( GAME_SCREEN ); } - usRandom = (UINT16)Random( 12 ); - if( usRandom < 3 ) + // Flugente hack + /*if ( Water(usMapPos) ) + pSoldier = TacticalCreateEnemyBoat( ); + else + pSoldier = TacticalCreateEnemyJeep( );*/ + + usRandom = (UINT16)Random( 20 ); + if( usRandom < 5 ) pSoldier = TacticalCreateAdministrator(); - else if( usRandom < 6 ) + else if( usRandom < 10 ) pSoldier = TacticalCreateArmyTroop(); - else if ( usRandom < 9 ) + else if ( usRandom < 12 ) pSoldier = TacticalCreateEnemyTank( ); + else if ( usRandom < 15 ) + pSoldier = TacticalCreateEnemyJeep( ); else pSoldier = TacticalCreateEliteEnemy( ); @@ -1178,6 +1186,7 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent ) case SOLDIER_CLASS_ARMY: pSector->ubNumTroops++; pSector->ubTroopsInBattle++; break; case SOLDIER_CLASS_ELITE: pSector->ubNumElites++; pSector->ubElitesInBattle++; break; case SOLDIER_CLASS_TANK: pSector->ubNumTanks++; pSector->ubTanksInBattle++; break; + case SOLDIER_CLASS_JEEP: pSector->ubNumJeeps++; pSector->ubJeepsInBattle++; break; } } else @@ -1191,6 +1200,7 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent ) case SOLDIER_CLASS_ARMY: pSector->ubNumTroops++; pSector->ubTroopsInBattle++; break; case SOLDIER_CLASS_ELITE: pSector->ubNumElites++; pSector->ubElitesInBattle++; break; case SOLDIER_CLASS_TANK: pSector->ubNumTanks++; pSector->ubTanksInBattle++; break; + case SOLDIER_CLASS_JEEP: pSector->ubNumJeeps++; pSector->ubJeepsInBattle++; break; } } } @@ -1205,6 +1215,71 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent ) return( GAME_SCREEN ); } +/*void TankBattlefun() +{ + int teamsize = 1; + + for ( int i = 0; i < teamsize; ++i) + { + { + SOLDIERTYPE *pSoldier = TacticalCreateTankFuntime(ENEMY_TEAM); + + if( pSoldier ) + { + if( !gbWorldSectorZ ) + { + SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; + switch( pSoldier->ubSoldierClass ) + { + case SOLDIER_CLASS_ADMINISTRATOR: pSector->ubNumAdmins++; pSector->ubAdminsInBattle++; break; + case SOLDIER_CLASS_ARMY: pSector->ubNumTroops++; pSector->ubTroopsInBattle++; break; + case SOLDIER_CLASS_ELITE: pSector->ubNumElites++; pSector->ubElitesInBattle++; break; + } + } + else + { + UNDERGROUND_SECTORINFO *pSector = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + if( pSector ) + { + switch( pSoldier->ubSoldierClass ) + { + case SOLDIER_CLASS_ADMINISTRATOR: pSector->ubNumAdmins++; pSector->ubAdminsInBattle++; break; + case SOLDIER_CLASS_ARMY: pSector->ubNumTroops++; pSector->ubTroopsInBattle++; break; + case SOLDIER_CLASS_ELITE: pSector->ubNumElites++; pSector->ubElitesInBattle++; break; + } + } + } + + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_NORTH; + //pSoldier->usStrategicInsertionData = gMapInformation.sSouthGridNo; + UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + AllTeamsLookForAll( NO_INTERRUPTS ); + } + } + + { + SOLDIERTYPE *pSoldier = TacticalCreateTankFuntime(MILITIA_TEAM); + + if( pSoldier ) + { + pSoldier->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA; + + if( !gbWorldSectorZ ) + { + SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; + pSector->ubNumberOfCivsAtLevel[ELITE_MILITIA]++; + } + + + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_SOUTH; + //pSoldier->usStrategicInsertionData = gMapInformation.sSouthGridNo; + UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + AllTeamsLookForAll( NO_INTERRUPTS ); + } + } + } +}*/ + UINT32 UIHandleEnterEditMode( UI_EVENT *pUIEvent ) { diff --git a/Tactical/Interface Enhanced.cpp b/Tactical/Interface Enhanced.cpp index 614c3ce6..86118291 100644 --- a/Tactical/Interface Enhanced.cpp +++ b/Tactical/Interface Enhanced.cpp @@ -2365,7 +2365,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr } /////////////////// ANTI-TANK AMMO - if ( AmmoTypes[Magazine[Item[ gpItemDescObject->usItem ].ubClassIndex].ubAmmoType].antiTank ) + if ( AmmoTypes[Magazine[Item[gpItemDescObject->usItem].ubClassIndex].ubAmmoType].dDamageModifierTank >= 0.1f ) { swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[ 1 ], szUDBGenSecondaryStatsExplanationsTooltipText[ 1 ]); SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + cnt ]), pStr ); @@ -5946,8 +5946,8 @@ void DrawSecondaryStats( OBJECTTYPE * gpItemDescObject ) } /////////////////// ANTI-TANK AMMO - if ( ( AmmoTypes[Magazine[Item[ gpItemDescObject->usItem ].ubClassIndex].ubAmmoType].antiTank && !fComparisonMode ) || - ( fComparisonMode && AmmoTypes[Magazine[Item[ gpComparedItemDescObject->usItem ].ubClassIndex].ubAmmoType].antiTank ) ) + if ( (AmmoTypes[Magazine[Item[gpItemDescObject->usItem].ubClassIndex].ubAmmoType].dDamageModifierTank >= 0.1f && !fComparisonMode) || + (fComparisonMode && AmmoTypes[Magazine[Item[gpComparedItemDescObject->usItem].ubClassIndex].ubAmmoType].dDamageModifierTank >= 0.1f ) ) { BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 1, gItemDescGenSecondaryRegions[cnt].sLeft+sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL ); cnt++; diff --git a/Tactical/Interface.cpp b/Tactical/Interface.cpp index 709b8d9e..63fd6b2e 100644 --- a/Tactical/Interface.cpp +++ b/Tactical/Interface.cpp @@ -2024,7 +2024,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) swprintf( NameStr, zGrod[0] ); } //Legion - else if ( TANK( pSoldier ) ) + else if ( ARMED_VEHICLE( pSoldier ) ) { swprintf( NameStr, gNewVehicle[164].NewVehicleStrings ); } diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index d9939969..2c8aa7fd 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -91,7 +91,7 @@ ARMY_GUN_CHOICE_TYPE gExtendedArmyGunChoices[SOLDIER_GUN_CHOICE_SELECTIONS][ARMY ARMY_GUN_CHOICE_TYPE gArmyItemChoices[SOLDIER_GUN_CHOICE_SELECTIONS][MAX_ITEM_TYPES]; void RandomlyChooseWhichItemsAreDroppable( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass ); -void EquipTank( SOLDIERCREATE_STRUCT *pp ); +void EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp, BOOLEAN fTank = TRUE ); void ChooseKitsForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bKitClass ); void ChooseMiscGearForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bMiscClass ); @@ -251,13 +251,13 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 return; } - if ( TANK( pp ) ) + if ( ARMED_VEHICLE( pp ) ) { - EquipTank( pp ); + EquipArmouredVehicle( pp, TANK( pp ) ); return; } - Assert( ( bSoldierClass >= SOLDIER_CLASS_NONE ) && ( bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA ) || bSoldierClass == SOLDIER_CLASS_TANK ); + Assert( (bSoldierClass >= SOLDIER_CLASS_NONE) && (bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA) || bSoldierClass == SOLDIER_CLASS_TANK || bSoldierClass == SOLDIER_CLASS_JEEP ); Assert( ( bEquipmentRating >= 0 ) && ( bEquipmentRating <= 4 ) ); // equipment level is modified by 1/10 of the difficulty percentage, -5, so it's between -5 to +5 @@ -3406,24 +3406,33 @@ UINT16 SelectStandardArmyGun( UINT8 uiGunLevel, INT8 bSoldierClass ) -void EquipTank( SOLDIERCREATE_STRUCT *pp ) +void EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp, BOOLEAN fTank ) { // tanks get special equipment, and they drop nothing (MGs are hard-mounted & non-removable) - // main cannon - CreateItem( TANK_CANNON, ( INT8 )( 80 + Random( 21 ) ), &( pp->Inv[ HANDPOS ]) ); - pp->Inv[ HANDPOS ].fFlags |= OBJECT_UNDROPPABLE; + // tanks get a main cannon and a MG, other vehicles just get the MG + if ( fTank ) + { + CreateItem( TANK_CANNON, ( INT8 )( 80 + Random( 21 ) ), &( pp->Inv[ HANDPOS ]) ); + pp->Inv[ HANDPOS ].fFlags |= OBJECT_UNDROPPABLE; - // machine gun - CreateItems( MINIMI, ( INT8 )( 80 + Random( 21 ) ), 1, &gTempObject ); - gTempObject.fFlags |= OBJECT_UNDROPPABLE; - PlaceObjectInSoldierCreateStruct( pp, &gTempObject ); - - // tanks don't deplete shells or ammo... - CreateItems( TANK_SHELL, 100, 1, &gTempObject ); - gTempObject.fFlags |= OBJECT_UNDROPPABLE; - PlaceObjectInSoldierCreateStruct( pp, &gTempObject ); + // tanks don't deplete shells or ammo... + CreateItems( TANK_SHELL, 100, 1, &gTempObject ); + gTempObject.fFlags |= OBJECT_UNDROPPABLE; + PlaceObjectInSoldierCreateStruct( pp, &gTempObject ); + // machine gun + CreateItems( MINIMI, (INT8)(80 + Random( 21 )), 1, &gTempObject ); + gTempObject.fFlags |= OBJECT_UNDROPPABLE; + PlaceObjectInSoldierCreateStruct( pp, &gTempObject ); + } + else + { + // machine gun + CreateItems( MINIMI, (INT8)(80 + Random( 21 )), 1, &(pp->Inv[HANDPOS]) ); + pp->Inv[HANDPOS].fFlags |= OBJECT_UNDROPPABLE; + } + // armour equal to spectra all over (for vs explosives) CreateItem( SPECTRA_VEST, 100, &(pp->Inv[ VESTPOS ]) ); pp->Inv[ VESTPOS ].fFlags |= OBJECT_UNDROPPABLE; @@ -3431,7 +3440,6 @@ void EquipTank( SOLDIERCREATE_STRUCT *pp ) pp->Inv[ HELMETPOS ].fFlags |= OBJECT_UNDROPPABLE; CreateItem( SPECTRA_LEGGINGS, 100, &(pp->Inv[ LEGPOS ]) ); pp->Inv[ LEGPOS ].fFlags |= OBJECT_UNDROPPABLE; - } diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 338cb166..f706dad6 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -3229,7 +3229,7 @@ void SwapObjs(SOLDIERTYPE* pSoldier, int leftSlot, int rightSlot, BOOLEAN fPerma { SwapObjs(&pSoldier->inv[ leftSlot ], &pSoldier->inv[ rightSlot ]); - if(fPermanent && !TANK(pSoldier))//dnl ch64 290813 for current tank don't go further as it lead to invalid animation + if ( fPermanent && !ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 for current tank don't go further as it lead to invalid animation { //old usItem for the left slot is now stored in the right slot, and vice versa HandleTacticalEffectsOfEquipmentChange(pSoldier, leftSlot, pSoldier->inv[ rightSlot ].usItem, pSoldier->inv[ leftSlot ].usItem); @@ -8953,7 +8953,7 @@ void CheckEquipmentForDamage( SOLDIERTYPE *pSoldier, INT32 iDamage ) BOOLEAN fBlowsUp; UINT8 ubNumberOfObjects; - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { return; } diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index 6dccb372..1ec0e7ef 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -2047,7 +2047,7 @@ BOOLEAN CalculateSoldierZPos( SOLDIERTYPE * pSoldier, UINT8 ubPosType, FLOAT * p ubPosType = TORSO_TARGET_POS; } } - else if ( TANK( pSoldier ) ) + else if ( ARMED_VEHICLE( pSoldier ) ) { // high up! //ubPosType = HEAD_TARGET_POS; @@ -2184,7 +2184,7 @@ BOOLEAN CalculateSoldierZPos( SOLDIERTYPE * pSoldier, UINT8 ubPosType, FLOAT * p // robot is 1/3 the height of regular people *pdZPos = *pdZPos / 3; } - else if ( TANK ( pSoldier ) ) + else if ( ARMED_VEHICLE( pSoldier ) ) { *pdZPos = (*pdZPos * 4) / 3; } @@ -2311,7 +2311,7 @@ INT32 SoldierToSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE fSmell = HasThermalOptics( pStartSoldier); } - if ( TANK( pStartSoldier ) ) + if ( ARMED_VEHICLE( pStartSoldier ) ) { INT16 sDistance; @@ -2352,7 +2352,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 ) || gGameExternalOptions.fEnemyTanksAnyPartVisible ) ) + if ( pEndSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && (!ARMED_VEHICLE( pEndSoldier ) || gGameExternalOptions.fEnemyTanksAnyPartVisible) ) { STRUCTURE *pBase = pEndSoldier->pLevelNode->pStructureData; if( pBase == NULL ) @@ -2917,7 +2917,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend { usExpGain /= 2; } - else if ( pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTarget ) || TANK( pTarget ) ) + else if ( pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTarget ) || ARMED_VEHICLE( pTarget ) ) { // no exp from shooting a vehicle that you can't damage and can't move! usExpGain = 0; @@ -3305,7 +3305,7 @@ INT32 HandleBulletStructureInteraction( BULLET * pBullet, STRUCTURE * pStructure //else if ( pBullet->usFlags & BULLET_FLAG_SMALL_MISSILE ) //{ // stops if using HE ammo - else if ( AmmoTypes[ubAmmoType].highExplosive && !AmmoTypes[ubAmmoType].antiTank ) + else if ( AmmoTypes[ubAmmoType].highExplosive && AmmoTypes[ubAmmoType].dDamageModifierTank < 0.1f ) { *pfHit = TRUE; return( 0 ); @@ -3457,7 +3457,7 @@ INT32 CTGTHandleBulletStructureInteraction( BULLET * pBullet, STRUCTURE * pStruc //else if ( pBullet->usFlags & BULLET_FLAG_SMALL_MISSILE ) //{ // stops if using HE ammo - else if ( AmmoTypes[pBullet->pFirer->inv[ pBullet->pFirer->ubAttackingHand ][0]->data.gun.ubGunAmmoType].highExplosive && !AmmoTypes[pBullet->pFirer->inv[ pBullet->pFirer->ubAttackingHand ][0]->data.gun.ubGunAmmoType].antiTank ) + else if ( AmmoTypes[pBullet->pFirer->inv[pBullet->pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType].highExplosive && AmmoTypes[pBullet->pFirer->inv[pBullet->pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType].dDamageModifierTank < 0.1f ) { return( pBullet->iImpact ); } diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 54e78836..ff4bde3b 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -3585,7 +3585,7 @@ void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld ) // gMercProfiles[ pSoldierOld->ubProfile ].bLife = 0; - if ( !(pSoldierOld->flags.uiStatusFlags & SOLDIER_VEHICLE) && !TANK( pSoldierOld) ) + if ( !(pSoldierOld->flags.uiStatusFlags & SOLDIER_VEHICLE) && !ARMED_VEHICLE( pSoldierOld ) ) { if ( pSoldierOld->ubAttackerID != NOBODY ) { @@ -7021,16 +7021,16 @@ void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { SECTORINFO *pSectorInfo = &(SectorInfo[SECTOR( sMapX, sMapY )]); - pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = 0; - pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = 0; + pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = pSectorInfo->ubNumJeeps = 0; + pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = pSectorInfo->ubJeepsInBattle = 0; } else { UNDERGROUND_SECTORINFO *pSectorInfo; pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ ); - pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = 0; - pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = 0; + pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = pSectorInfo->ubNumJeeps = 0; + pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = pSectorInfo->ubJeepsInBattle = 0; } } @@ -10485,7 +10485,7 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue ) { enemysidestrength += pSoldier->GetSurrenderStrength(); - if ( pSoldier->ubProfile != NO_PROFILE || TANK(pSoldier) ) + if ( pSoldier->ubProfile != NO_PROFILE || ARMED_VEHICLE(pSoldier) ) fNoSurrender = TRUE; } } diff --git a/Tactical/PATHAI.cpp b/Tactical/PATHAI.cpp index af310555..f3eac262 100644 --- a/Tactical/PATHAI.cpp +++ b/Tactical/PATHAI.cpp @@ -2621,7 +2621,10 @@ if(!GridNoOnVisibleWorldTile(iDestination)) fPathingForPlayer = ( (s->bTeam == gbPlayerNum) && (!gTacticalStatus.fAutoBandageMode) && !(s->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL) ); fNonFenceJumper = !( IS_MERC_BODY_TYPE( s ) ) || (UsingNewInventorySystem() == true && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND);//Moa: added backpack check - fNonSwimmer = !( IS_MERC_BODY_TYPE( s ) ); + + // Flugente: nonswimmers are those who are not mercs and not boats + fNonSwimmer = !(IS_MERC_BODY_TYPE( s ) ); + if ( fNonSwimmer ) { if ( Water( sDestination, ubLevel ) ) @@ -2638,13 +2641,13 @@ if(!GridNoOnVisibleWorldTile(iDestination)) fVehicleIgnoreObstacles = TRUE; } // AI can't press shift, let's assume only tanks ram through (we wouldn't want AI cars to get destroyed kamikazing through walls, no matter how funny that would be) - else if( !fPathingForPlayer && TANK(s) ) + else if ( !fPathingForPlayer && ARMED_VEHICLE( s ) ) { fVehicleIgnoreObstacles = TRUE; } if( fVehicleIgnoreObstacles && - ( ( gGameExternalOptions.fAllowCarsDrivingOverPeople && !TANK(s) ) || - ( gGameExternalOptions.fAllowTanksDrivingOverPeople && TANK(s) ) ) ) + ((gGameExternalOptions.fAllowCarsDrivingOverPeople && !ARMED_VEHICLE( s )) || + (gGameExternalOptions.fAllowTanksDrivingOverPeople && ARMED_VEHICLE( s ))) ) { fPathAroundPeople = FALSE; } @@ -2846,9 +2849,9 @@ if(!GridNoOnVisibleWorldTile(iDestination)) else { if (ISWATER(gubWorldMovementCosts[iOrigination][0][ubLevel]) && ISWATER(gubWorldMovementCosts[iDestination][0][ubLevel])) - iWaterToWater = 1; + iWaterToWater = 1; else - iWaterToWater = 0; + iWaterToWater = 0; } //setup Q and first path record @@ -4617,7 +4620,7 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl sMovementAPsCost = sTileCost + APBPConstants[AP_MODIFIER_RUN]; break; case WALKING: - if (!(pSold->MercInWater()) && ( (gAnimControl[ pSold->usAnimState ].uiFlags & ANIM_FIREREADY ) || (gAnimControl[ pSold->usAnimState ].uiFlags & ANIM_FIRE ) )) + if ( 0 && !(pSold->MercInWater()) && ( (gAnimControl[ pSold->usAnimState ].uiFlags & ANIM_FIREREADY ) || (gAnimControl[ pSold->usAnimState ].uiFlags & ANIM_FIRE ) )) { sMovementAPsCost = sTileCost + APBPConstants[AP_MODIFIER_WALK] + APBPConstants[AP_MODIFIER_READY]; } diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index 29008442..73293fc4 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -57,17 +57,17 @@ INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState ); INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, INT8 bLevel ) { // SANDRO - Note: this procedure was changed a bit - INT16 sAPCost = 0; + INT16 sAPCost = 0; INT16 sSwitchValue; - BOOLEAN fHiddenStructVisible; // Used for hidden struct visiblity + BOOLEAN fHiddenStructVisible; // Used for hidden struct visiblity // SANDRO - removed AP cost of moving stealthy or reversed outside this procedure //if (GridCost[gridno] == NPCMINECOST) // switchValue = BackupGridCost[gridno]; //else - - sSwitchValue = gubWorldMovementCosts[sGridNo][bDir][ bLevel ]; + + sSwitchValue = gubWorldMovementCosts[sGridNo][bDir][ bLevel ]; // Check reality vs what the player knows.... if ( pSoldier->bTeam == gbPlayerNum ) @@ -83,15 +83,16 @@ INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, INT8 } } } + //ddd window if ( sSwitchValue == TRAVELCOST_JUMPABLEWINDOW || sSwitchValue == TRAVELCOST_JUMPABLEWINDOW_N || sSwitchValue == TRAVELCOST_JUMPABLEWINDOW_W) { if (bDir & 1) - return -1; - + return -1; } + //ddd if we don't check this condition, then when we approach to the tile with a window, when the distance to that tile will be 1 //we'll get nice message, that the way is blocked if ( sSwitchValue == TRAVELCOST_NOT_STANDING)// || sSwitchValue == TRAVELCOST_JUMPABLEWINDOW) @@ -106,6 +107,7 @@ INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, INT8 { return -1; } + sSwitchValue = DoorTravelCost( pSoldier, sGridNo, (UINT8) sSwitchValue, (BOOLEAN) (pSoldier->bTeam == gbPlayerNum), NULL ); } else if (gfPlotPathToExitGrid && sSwitchValue == TRAVELCOST_EXITGRID) @@ -138,20 +140,20 @@ INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, INT8 case TRAVELCOST_DEBRIS : sAPCost += APBPConstants[AP_MOVEMENT_RUBBLE]; break; case TRAVELCOST_SHORE : sAPCost += APBPConstants[AP_MOVEMENT_SHORE]; // wading shallow water - if (!IS_MERC_BODY_TYPE( pSoldier )) + if ( !IS_MERC_BODY_TYPE( pSoldier ) ) { return -1; } break; case TRAVELCOST_KNEEDEEP : sAPCost += APBPConstants[AP_MOVEMENT_LAKE]; // wading waist/chest deep - very slow - if (!IS_MERC_BODY_TYPE( pSoldier )) + if ( !IS_MERC_BODY_TYPE( pSoldier ) ) { return -1; } break; case TRAVELCOST_DEEPWATER: sAPCost += APBPConstants[AP_MOVEMENT_OCEAN]; // can swim, so it's faster than wading - if (!IS_MERC_BODY_TYPE( pSoldier )) + if ( !IS_MERC_BODY_TYPE( pSoldier ) ) { return -1; } @@ -1474,7 +1476,7 @@ INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState ) sBreathPerAP = APBPConstants[BP_PER_AP_MIN_EFFORT]; // OK, check if we are in water and are waling/standing - if ( pSoldier->MercInWater( ) ) + if ( 0 && pSoldier->MercInWater( ) ) { switch( usAnimState ) { @@ -2481,7 +2483,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 bAimTime, } } - if ( AM_A_ROBOT( pSoldier ) || TANK( pSoldier ) || ubForceRaiseGunCost == 2 )//dnl ch64 300813 robots and tanks cannot do this //dnl ch69 150913 need option to override raise gun cost + if ( AM_A_ROBOT( pSoldier ) || ARMED_VEHICLE( pSoldier ) || ubForceRaiseGunCost == 2 )//dnl ch64 300813 robots and tanks cannot do this //dnl ch69 150913 need option to override raise gun cost { fAddingRaiseGunCost = FALSE; } @@ -2632,7 +2634,7 @@ INT16 MinPtsToMove(SOLDIERTYPE *pSoldier) INT16 sCost; INT32 sGridNo; - if ( TANK( pSoldier ) && !gGameExternalOptions.fEnemyTanksCanMoveInTactical ) + if ( ARMED_VEHICLE( pSoldier ) && !gGameExternalOptions.fEnemyTanksCanMoveInTactical ) { return(sLowest);//dnl ch64 290813 100AP made INT8 return obsolete } @@ -2837,7 +2839,7 @@ void DeductAmmo( SOLDIERTYPE *pSoldier, OBJECTTYPE* pObj ) { // tanks never run out of MG ammo! // unlimited cannon ammo is handled in AI - if ( TANK( pSoldier ) && !Item[pObj->usItem].cannon ) + if ( ARMED_VEHICLE( pSoldier ) && !Item[pObj->usItem].cannon ) return; if ( Item[pObj->usItem].cannon ) @@ -4031,7 +4033,7 @@ INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAim Assert(pSoldier != NULL); Assert(&pSoldier->inv[HANDPOS] != NULL); #ifndef dnlCALCBESTSHOT//dnl ch69 150913 if this is turn on we get incorrect APs as MinAPsToShootOrStab always include raise gun cost - if (!TANK(pSoldier) && !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_FIREREADY | ANIM_FIRE )))//dnl ch64 310813 + if (!ARMED_VEHICLE(pSoldier) && !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_FIREREADY | ANIM_FIRE )))//dnl ch64 310813 { // Weapon not ready, check aiming from hip, else add raise gun cost //if (!pSoldier->IsValidShotFromHip(bAimTime,sTargetGridNo)) @@ -4238,7 +4240,7 @@ INT32 GetBPCostPer10APsForGunHolding( SOLDIERTYPE * pSoldier, BOOLEAN fEstimate return 0; if ( !(gAnimControl[ pSoldier->usAnimState ].uiFlags & (ANIM_FIRE | ANIM_FIREREADY) ) && !fEstimate ) // don't if weapon not raised, but do if we are gonna estimate the cost return 0; - if ( TANK( pSoldier ) || AM_A_ROBOT( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier ) ) return 0; ////////////////////////////////////////////////////////////////////////////// // THE BASIC COST FOR HOLDING THE GUN RAISED (per AP) @@ -4379,7 +4381,7 @@ INT32 GetBPCostForRecoilkick( SOLDIERTYPE * pSoldier ) return 0; if ( Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].usItemClass != IC_GUN && Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].usItemClass != IC_LAUNCHER ) return 0; - if ( TANK( pSoldier ) || AM_A_ROBOT( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier ) ) return 0; ////////////////////////////////////////////////////////////////////////////// // THE GUN RECOIL KICK ENERGY COST diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index a72fa41c..dfcd36d1 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -3949,7 +3949,7 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse ) default : if ( CREATURE_OR_BLOODCAT( pSoldier ) ) gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++; - else if ( TANK( pSoldier ) ) + else if ( ARMED_VEHICLE( pSoldier ) ) gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsTanks++; else if ( pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral && pSoldier->bSide != gbPlayerNum ) gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsHostiles++; @@ -4209,6 +4209,7 @@ void CheckForAndHandleSoldierIncompacitated( SOLDIERTYPE *pSoldier ) case QUEENMONSTER: case TANK_NW: case TANK_NE: + case COMBAT_JEEP: pSoldier->stats.bLife = 0; break; diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 4a20b372..8156f265 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -5122,7 +5122,7 @@ UINT16 SelectFireAnimation( SOLDIERTYPE *pSoldier, UINT8 ubHeight ) return(TANK_SHOOT); } - if ( TANK(pSoldier) ) + if ( ARMED_VEHICLE( pSoldier ) ) { return(TANK_BURST); } @@ -5474,7 +5474,7 @@ UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOL return(INVALID_ANIMATION); } - if ( TANK(pSoldier) ) + if ( ARMED_VEHICLE( pSoldier ) ) { return(INVALID_ANIMATION); } @@ -8095,7 +8095,7 @@ void SOLDIERTYPE::TurnSoldier( void ) if ( ((gAnimControl[this->usAnimState].uiFlags & ANIM_FIREREADY) && this->flags.bTurningFromPronePosition == TURNING_FROM_PRONE_OFF) || this->ubBodyType == ROBOTNOWEAPON || - TANK(this) ) + ARMED_VEHICLE( this ) ) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "TurnSoldier: EVENT_InitNewSoldierAnim" ) ); this->EVENT_InitNewSoldierAnim( SelectFireAnimation( this, gAnimControl[this->usAnimState].ubEndHeight ), 0, FALSE ); @@ -8175,7 +8175,7 @@ void SOLDIERTYPE::TurnSoldier( void ) // Don't do anything if we are at dest direction! if ( this->ubDirection == this->pathing.bDesiredDirection ) { - if ( TANK(this) ) + if ( ARMED_VEHICLE( this ) ) { if ( this->iTuringSoundID != NO_SAMPLE ) { @@ -8324,7 +8324,7 @@ void SOLDIERTYPE::TurnSoldier( void ) } } - if ( TANK(this) ) + if ( ARMED_VEHICLE( this ) ) { if ( this->iTuringSoundID == NO_SAMPLE ) { @@ -9871,22 +9871,23 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr // OK, If we are a vehicle.... damage vehicle...( people inside... ) if ( this->flags.uiStatusFlags & SOLDIER_VEHICLE ) { - if ( TANK( this ) ) + if ( ubReason == TAKE_DAMAGE_GUNFIRE ) { - //sLifeDeduct = (sLifeDeduct * 2) / 3; + ; } + else if ( ubReason == TAKE_DAMAGE_EXPLOSION ) + { + if ( ARMED_VEHICLE( this ) ) + ; else { - if ( ubReason == TAKE_DAMAGE_GUNFIRE ) + if ( sLifeDeduct > 50 ) { - sLifeDeduct /= 3; - } - else if ( ubReason == TAKE_DAMAGE_EXPLOSION && sLifeDeduct > 50 ) - { // boom! sLifeDeduct *= 2; } } + } VehicleTakeDamage( this->bVehicleID, ubReason, sLifeDeduct, this->sGridNo, ubAttacker ); HandleTakeDamageDeath( this, bOldLife, ubReason ); @@ -15992,7 +15993,7 @@ UINT32 SOLDIERTYPE::GetSurrenderStrength( ) value *= 0.75f; // tanks won't surrender that easy - if ( TANK( this ) ) + if ( ARMED_VEHICLE( this ) ) value *= 10; return value; @@ -16036,8 +16037,8 @@ BOOLEAN SOLDIERTYPE::CanBeCaptured( ) // if this guy is not already handcuffed, and is not an NPC if ( !(this->usSoldierFlagMask & SOLDIER_POW) && this->ubProfile == NO_PROFILE ) { - // tanks cannot be captured - if ( this->ubSoldierClass == SOLDIER_CLASS_TANK ) + // armed vehicles cannot be captured + if ( ARMED_VEHICLE(this) ) return FALSE; // enemies can be captured @@ -18241,7 +18242,7 @@ BOOLEAN SOLDIERTYPE::CanMedicAI( ) return FALSE; // this is not for tanks - if ( TANK( this ) ) + if ( ARMED_VEHICLE( this ) ) return FALSE; if ( HAS_SKILL_TRAIT( this, DOCTOR_NT ) ) @@ -18273,7 +18274,7 @@ BOOLEAN SOLDIERTYPE::AIDoctorFriend( ) return FALSE; // this is not for tanks - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) return FALSE; // if this guy is wounded, heal him (should always be the case, otherwise this function was called needlessly) @@ -20504,7 +20505,7 @@ BOOLEAN SOLDIERTYPE::IsValidShotFromHip( INT16 bAimTime, INT32 iTrgGridNo ) return(FALSE); } // robots and tanks cannot do this - if ( AM_A_ROBOT( this ) || TANK( this ) )//dnl ch64 300813 + if ( AM_A_ROBOT( this ) || ARMED_VEHICLE( this ) )//dnl ch64 300813 { return(FALSE); } @@ -20556,7 +20557,7 @@ BOOLEAN SOLDIERTYPE::IsValidPistolFastShot( INT16 bAimTime, INT32 iTrgGridNo ) return(FALSE); } // robots and tanks cannot do this - if ( AM_A_ROBOT( this ) || TANK( this ) )//dnl ch64 300813 + if ( AM_A_ROBOT( this ) || ARMED_VEHICLE( this ) )//dnl ch64 300813 { return(FALSE); } diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 8fc18adc..5cca015d 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -332,6 +332,7 @@ enum SOLDIER_CLASS_MINER, SOLDIER_CLASS_ZOMBIE, SOLDIER_CLASS_TANK, + SOLDIER_CLASS_JEEP, SOLDIER_CLASS_MAX, }; diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index fc8ad8f8..6c11c20f 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -606,7 +606,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * pCreateStruct->fPlayerPlan = 0; } - if ( is_networked && TANK( pCreateStruct ) ) + if ( is_networked && ARMED_VEHICLE( pCreateStruct ) ) { ScreenMsg( FONT_YELLOW, MSG_MPSYSTEM, L"skipping tank"); return NULL; @@ -802,7 +802,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * Soldier.bOldLife = Soldier.stats.bLifeMax; // Flugente: disease can affect a soldier's health - if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic && Soldier.bTeam != OUR_TEAM && Soldier.bTeam != CREATURE_TEAM && Soldier.ubSoldierClass != SOLDIER_CLASS_TANK ) + if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic && Soldier.bTeam != OUR_TEAM && Soldier.bTeam != CREATURE_TEAM && !ARMED_VEHICLE((&Soldier)) ) { UINT8 sector = SECTOR( Soldier.sSectorX, Soldier.sSectorY ); UINT16 population = GetSectorPopulation( Soldier.sSectorX, Soldier.sSectorY ); @@ -1073,6 +1073,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * case JEEP: case TANK_NW: case TANK_NE: + case COMBAT_JEEP: Soldier.flags.uiStatusFlags |= SOLDIER_VEHICLE; @@ -1115,6 +1116,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * */ case TANK_NW: case TANK_NE: + case COMBAT_JEEP: ubVehicleID = TANK_CAR; break; @@ -1704,7 +1706,7 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT // Flugente: soldier profiles // silversurfer: Don't replace tanks! - if ( !TANK( pCreateStruct ) ) + if ( !ARMED_VEHICLE( pCreateStruct ) ) { // We have a function for this INT8 type = pSoldier->GetSoldierProfileType( pCreateStruct->bTeam ); @@ -2476,6 +2478,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B break; case SOLDIER_CLASS_TANK: + case SOLDIER_CLASS_JEEP: pp->bExpLevel = bp->bRelativeAttributeLevel; break; @@ -3127,6 +3130,46 @@ SOLDIERTYPE* TacticalCreateEnemyTank() return( pSoldier ); } +SOLDIERTYPE* TacticalCreateEnemyJeep( ) +{ + BASIC_SOLDIERCREATE_STRUCT bp; + SOLDIERCREATE_STRUCT pp; + UINT8 ubID; + SOLDIERTYPE * pSoldier; + + if ( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI ) + { + pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_JEEP ); + + 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.ubBodyType = COMBAT_JEEP; + bp.ubSoldierClass = SOLDIER_CLASS_JEEP; + CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp ); + + 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; + + // Flugente: why would a vehicle's armour depend on game progress? Always give them 100 HP + pSoldier->stats.bLifeMax = 100; + pSoldier->stats.bLife = pSoldier->stats.bLifeMax; + } + + return(pSoldier); +} + //USED BY STRATEGIC AI and AUTORESOLVE // should to be succeeded by TacticalCreateArmyTroop/EliteEnemy and AddSoldierToVehicle SOLDIERTYPE* TacticalCreateJeep() diff --git a/Tactical/Soldier Create.h b/Tactical/Soldier Create.h index 7ee08541..b7242c65 100644 --- a/Tactical/Soldier Create.h +++ b/Tactical/Soldier Create.h @@ -443,6 +443,7 @@ SOLDIERTYPE* TacticalCreateZombie(); // Flugente Zombies SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass, INT16 sX, INT16 sY ); // Flugente: added sector coordinates SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType ); SOLDIERTYPE* TacticalCreateEnemyTank(); +SOLDIERTYPE* TacticalCreateEnemyJeep( ); SOLDIERTYPE* TacticalCreateJeep(); // Flugente: create an armed civilian diff --git a/Tactical/Soldier Init List.cpp b/Tactical/Soldier Init List.cpp index 0cd429e6..15d7d859 100644 --- a/Tactical/Soldier Init List.cpp +++ b/Tactical/Soldier Init List.cpp @@ -591,7 +591,7 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr, GROUP *pGroup = NULL ) // First check if this guy has a profile and if so check his location such that it matches! // Get profile from placement info - if ( TANK( curr->pBasicPlacement ) ) + if ( ARMED_VEHICLE( curr->pBasicPlacement ) ) { while (1) { @@ -804,7 +804,7 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr, GROUP *pGroup = NULL ) DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AddPlacementToWorld: create soldier")); - if ( is_networked && ( TANK( (&tempDetailedPlacement) ) || tempDetailedPlacement.fOnRoof ) ) + if ( is_networked && (ARMED_VEHICLE( (&tempDetailedPlacement) ) || tempDetailedPlacement.fOnRoof) ) return TRUE; pSoldier = TacticalCreateSoldier( &tempDetailedPlacement, &ubID ); @@ -1019,7 +1019,7 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum ) return ubNumAdded; } -void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks ) +void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks, UINT8 ubTotalJeeps ) { SOLDIERINITNODE *mark; SOLDIERINITNODE *curr; @@ -1029,6 +1029,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr 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 ubJeepPDSlots = 0, ubJeepDSlots = 0, ubJeepPSlots = 0, ubJeepBSlots = 0; UINT8 ubFreeSlots; UINT8 *pCurrSlots=NULL; UINT8 *pCurrTotal=NULL; @@ -1046,7 +1047,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 + ubTotalTanks; + ubMaxNum = ubTotalAdmin + ubTotalTroops + ubTotalElite + ubTotalTanks + ubTotalJeeps; AssertLE (ubMaxNum, gGameExternalOptions.ubGameMaximumNumberOfEnemies); @@ -1096,6 +1097,18 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr else ubTroopBSlots++; break; + case SOLDIER_CLASS_JEEP: + if ( COMBAT_JEEP( curr->pDetailedPlacement ) ) + { + if ( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement ) + ubJeepPDSlots++; + else if ( curr->pBasicPlacement->fPriorityExistance ) + ubJeepPSlots++; + else if ( curr->pDetailedPlacement ) + ubJeepDSlots++; + else + ubJeepBSlots++; + } case SOLDIER_CLASS_TANK: if ( TANK( curr->pDetailedPlacement ) ) { @@ -1117,7 +1130,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 + 1; ubCurrClass++ ) + for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY + 2; ++ubCurrClass ) { //First, prepare the counters. switch( ubCurrClass ) @@ -1139,6 +1152,11 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr pCurrSlots = &ubTankPDSlots; pCurrTotal = &ubTotalTanks; break; + case SOLDIER_CLASS_ARMY + 2:// SOLDIER_CLASS_JEEP + ubCurrClass = SOLDIER_CLASS_JEEP; + pCurrSlots = &ubJeepPDSlots; + pCurrTotal = &ubTotalJeeps; + break; } //Now, loop through the priority existance and detailed placement section of the list. curr = gSoldierInitHead; @@ -1317,10 +1335,16 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr } else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks ) { - curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK; + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK; curr->pBasicPlacement->ubBodyType = TANK_NW; ubTotalTanks--; } + else if ( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks + ubTotalJeeps ) + { + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_JEEP; + curr->pBasicPlacement->ubBodyType = COMBAT_JEEP; + ubTotalJeeps--; + } else Assert(0); if( AddPlacementToWorld( curr ) ) @@ -1406,18 +1430,34 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr curr = gSoldierInitHead; while( curr && ubFreeSlots && ubMaxNum ) { - if( !curr->pSoldier && curr->pBasicPlacement->bTeam == ENEMY_TEAM && ubTotalTanks && !GridNoIndoors( curr->pBasicPlacement->usStartingGridNo )) + if ( !curr->pSoldier && curr->pBasicPlacement->bTeam == ENEMY_TEAM && !GridNoIndoors( curr->pBasicPlacement->usStartingGridNo ) && (ubTotalTanks || ubTotalJeeps) ) { - curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK; - curr->pBasicPlacement->ubBodyType = TANK_NW; - ubTotalTanks--; - if( AddPlacementToWorld( curr ) ) + if ( ubTotalJeeps ) { - ubMaxNum--; + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_JEEP; + curr->pBasicPlacement->ubBodyType = COMBAT_JEEP; + ubTotalJeeps--; + if( AddPlacementToWorld( curr ) ) + { + ubMaxNum--; + } + else + return; + ubFreeSlots--; + } + else if ( ubTotalTanks ) + { + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK; + curr->pBasicPlacement->ubBodyType = TANK_NW; + ubTotalTanks--; + if ( AddPlacementToWorld( curr ) ) + { + ubMaxNum--; + } + else + return; + ubFreeSlots--; } - else - return; - ubFreeSlots--; } curr = curr->next; } @@ -1456,6 +1496,12 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr curr->pBasicPlacement->ubBodyType = TANK_NW; ubTotalTanks--; } + else if ( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks + ubTotalJeeps ) + { + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_JEEP; + curr->pBasicPlacement->ubBodyType = COMBAT_JEEP; + ubTotalJeeps--; + } else Assert(0); /* DISABLE THE OVERRIDE FOR NOW... @@ -1546,7 +1592,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl // silversurfer: Replace body type. Militia tanks are not allowed. if( curr->pBasicPlacement->fDetailedPlacement ) { - if ( TANK( curr->pDetailedPlacement ) ) + if ( ARMED_VEHICLE( curr->pDetailedPlacement ) ) { curr->pBasicPlacement->ubBodyType = PreRandom( REGFEMALE + 1 ); // check for better spot next to the tank so the militia doesn't get stuck in the tank @@ -1555,7 +1601,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl curr->pBasicPlacement->usStartingGridNo = iNewSpot; } } - else if ( TANK( curr->pBasicPlacement ) ) + else if ( ARMED_VEHICLE( curr->pBasicPlacement ) ) { curr->pBasicPlacement->ubBodyType = PreRandom( REGFEMALE + 1 ); // check for better spot next to the tank so the militia doesn't get stuck in the tank @@ -1563,14 +1609,17 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl if( iNewSpot != NOWHERE) curr->pBasicPlacement->usStartingGridNo = iNewSpot; } + if( curr->pDetailedPlacement ) - { //delete the detailed placement information. + { + //delete the detailed placement information. delete( curr->pDetailedPlacement ); curr->pDetailedPlacement = NULL; curr->pBasicPlacement->fDetailedPlacement = FALSE; RandomizeRelativeLevel( &( curr->pBasicPlacement->bRelativeAttributeLevel ), curr->pBasicPlacement->ubSoldierClass ); RandomizeRelativeLevel( &( curr->pBasicPlacement->bRelativeEquipmentLevel ), curr->pBasicPlacement->ubSoldierClass ); } + if( AddPlacementToWorld( curr ) ) { ubMaxNum--; @@ -1726,7 +1775,7 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl curr->pBasicPlacement->bAttitude = (INT8) Random( MAXATTITUDES ); // silversurfer: Replace body type. Militia tanks are not allowed. - if ( TANK(curr->pBasicPlacement) ) + if ( ARMED_VEHICLE( curr->pBasicPlacement ) ) { curr->pBasicPlacement->ubBodyType = PreRandom( REGFEMALE + 1 ); // check for better spot next to the tank so the militia doesn't get stuck in the tank @@ -1734,14 +1783,17 @@ void AddSoldierInitListMilitia( UINT8 ubNumGreen, UINT8 ubNumRegs, UINT8 ubNumEl if( iNewSpot != NOWHERE) curr->pBasicPlacement->usStartingGridNo = iNewSpot; } + if( curr->pDetailedPlacement ) - { //delete the detailed placement information. + { + //delete the detailed placement information. delete( curr->pDetailedPlacement ); curr->pDetailedPlacement = NULL; curr->pBasicPlacement->fDetailedPlacement = FALSE; RandomizeRelativeLevel( &( curr->pBasicPlacement->bRelativeAttributeLevel), curr->pBasicPlacement->ubSoldierClass ); RandomizeRelativeLevel( &( curr->pBasicPlacement->bRelativeEquipmentLevel), curr->pBasicPlacement->ubSoldierClass ); } + if( AddPlacementToWorld( curr ) ) { ubMaxNum--; diff --git a/Tactical/Soldier Init List.h b/Tactical/Soldier Init List.h index 5715500e..81a9fb11 100644 --- a/Tactical/Soldier Init List.h +++ b/Tactical/Soldier Init List.h @@ -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, UINT8 ubTotalTanks ); +void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks, UINT8 ubTotalJeeps ); void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNumInfants, UINT8 ubNumYoungMales, UINT8 ubNumYoungFemales, UINT8 ubNumAdultMales, UINT8 ubNumAdultFemales ); diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index c51630b1..56d2b866 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -1024,6 +1024,7 @@ BOOLEAN LoadMercProfiles(void) case ELDORADO: case ICECREAMTRUCK: case JEEP: + case COMBAT_JEEP: gProfilesVehicle[uiLoop].ProfilId = uiLoop; break; // Make it an RPC @@ -1051,6 +1052,7 @@ BOOLEAN LoadMercProfiles(void) case ELDORADO: case ICECREAMTRUCK: case JEEP: + case COMBAT_JEEP: gProfilesVehicle[uiLoop].ProfilId = uiLoop; break; // RPC or NPC diff --git a/Tactical/Soldier Tile.cpp b/Tactical/Soldier Tile.cpp index ff995015..fcbc8360 100644 --- a/Tactical/Soldier Tile.cpp +++ b/Tactical/Soldier Tile.cpp @@ -224,11 +224,11 @@ INT8 TileIsClear( SOLDIERTYPE *pSoldier, INT8 bDirection, INT32 sGridNo, INT8 b } // anv: vehicles can ram people - if ( !TANK(pSoldier) && gGameExternalOptions.fAllowCarsDrivingOverPeople && pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && pSoldier->usSoldierFlagMask2 & SOLDIER_RAM_THROUGH_OBSTACLES ) + if ( !ARMED_VEHICLE( pSoldier ) && gGameExternalOptions.fAllowCarsDrivingOverPeople && pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && pSoldier->usSoldierFlagMask2 & SOLDIER_RAM_THROUGH_OBSTACLES ) { return( MOVE_TILE_CLEAR ); } - else if( TANK(pSoldier) && gGameExternalOptions.fAllowTanksDrivingOverPeople && pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) + else if ( ARMED_VEHICLE( pSoldier ) && gGameExternalOptions.fAllowTanksDrivingOverPeople && pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { return( MOVE_TILE_CLEAR ); } diff --git a/Tactical/Soldier macros.h b/Tactical/Soldier macros.h index 821fcc93..eb19608b 100644 --- a/Tactical/Soldier macros.h +++ b/Tactical/Soldier macros.h @@ -32,9 +32,11 @@ #define CREATURE_OR_BLOODCAT( p ) ( (p->flags.uiStatusFlags & SOLDIER_MONSTER) || p->ubBodyType == BLOODCAT ) +#define COMBAT_JEEP( p ) ( p->ubBodyType == COMBAT_JEEP ) #define TANK( p ) (p->ubBodyType == TANK_NE || p->ubBodyType == TANK_NW ) +#define ARMED_VEHICLE( p ) ( TANK( p ) || COMBAT_JEEP(p) ) //#define OK_ENTERABLE_VEHICLE( p ) ( ( p->flags.uiStatusFlags & SOLDIER_VEHICLE ) && !TANK( p ) && p->stats.bLife >= OKLIFE ) -#define OK_ENTERABLE_VEHICLE( p ) ( ( p->flags.uiStatusFlags & SOLDIER_VEHICLE ) && (!TANK( p ) || !(p->flags.uiStatusFlags & SOLDIER_ENEMY) ) && p->stats.bLife >= OKLIFE ) +#define OK_ENTERABLE_VEHICLE( p ) ( ( p->flags.uiStatusFlags & SOLDIER_VEHICLE ) && (!ARMED_VEHICLE( p ) || !(p->flags.uiStatusFlags & SOLDIER_ENEMY) ) && p->stats.bLife >= OKLIFE ) #endif \ No newline at end of file diff --git a/Tactical/SoldierTooltips.cpp b/Tactical/SoldierTooltips.cpp index aaeb5210..e7703b8c 100644 --- a/Tactical/SoldierTooltips.cpp +++ b/Tactical/SoldierTooltips.cpp @@ -60,7 +60,7 @@ void SoldierTooltip( SOLDIERTYPE* pSoldier ) return; // WANNE: No tooltips on bloodcats, bugs, tanks, roboter - if ( CREATURE_OR_BLOODCAT( pSoldier ) || TANK ( pSoldier ) || + if ( CREATURE_OR_BLOODCAT( pSoldier ) || ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier)) { return; diff --git a/Tactical/TeamTurns.cpp b/Tactical/TeamTurns.cpp index 0432d458..73aefb88 100644 --- a/Tactical/TeamTurns.cpp +++ b/Tactical/TeamTurns.cpp @@ -1969,7 +1969,7 @@ INT8 CalcInterruptDuelPts( SOLDIERTYPE * pSoldier, UINT8 ubOpponentID, BOOLEAN f } } - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { // reduce interrupt possibilities for tanks! iPoints /= 2; diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 8349382b..4af07d42 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -4962,6 +4962,7 @@ void ChangeSoldiersBodyType( UINT8 ubBodyType, BOOLEAN fCreateNewPalette ) case TANK_NW: case TANK_NE: + case COMBAT_JEEP: pSoldier->flags.uiStatusFlags |= SOLDIER_VEHICLE; //pSoldier->inv[ HANDPOS ].usItem = TANK_CANNON; diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 11dc07f9..07b6220d 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -3320,7 +3320,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea { iHitChance = 100; } - else if ( AM_A_ROBOT( pTargetSoldier ) || TANK( pTargetSoldier ) || CREATURE_OR_BLOODCAT( pTargetSoldier ) || (SOLDIER_CLASS_MILITIA(pTargetSoldier->ubSoldierClass) && (gGameExternalOptions.ubMilitiaDropEquipment != 2)) ) // added militia here - SANDRO + else if ( AM_A_ROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) || CREATURE_OR_BLOODCAT( pTargetSoldier ) || (SOLDIER_CLASS_MILITIA( pTargetSoldier->ubSoldierClass ) && (gGameExternalOptions.ubMilitiaDropEquipment != 2)) ) // added militia here - SANDRO { iHitChance = 0; } @@ -3653,7 +3653,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea } // Give some experience - if ( iHitChance > 0 && pSoldier->bTeam == gbPlayerNum && pTargetSoldier->bTeam != gbPlayerNum && !(pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT( pTargetSoldier ) && !TANK( pTargetSoldier ) ) + if ( iHitChance > 0 && pSoldier->bTeam == gbPlayerNum && pTargetSoldier->bTeam != gbPlayerNum && !(pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT( pTargetSoldier ) && !ARMED_VEHICLE( pTargetSoldier ) ) { if (fFailure == FALSE) { @@ -3778,7 +3778,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea } } - if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || TANK( pTargetSoldier ) ) + if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) ) { ubExpGain = 0; } @@ -3828,7 +3828,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea } } - if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || TANK( pTargetSoldier ) ) + if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) ) { ubExpGain = 0; } @@ -6996,7 +6996,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, iPenalty = ((iMaxRange - (iRange-iAccRangeMod) * 3) * 10) / (17 * CELL_X_SIZE); if ( iPenalty < 0 ) iChance += iPenalty; - if ( TANK( pSoldier ) && ( iRange / CELL_X_SIZE < MaxNormalDistanceVisible() ) ) + if ( ARMED_VEHICLE( pSoldier ) && (iRange / CELL_X_SIZE < MaxNormalDistanceVisible( )) ) iChance -= 2 * ( MaxNormalDistanceVisible() - (iRange / CELL_X_SIZE) ); // Like the above modifier, only this applies to long range weapons trying to be used in close quater. Penalty will result when within 10% of max range iPenalty = (((iRange - iMinRange - iAccRangeMod) * 12) * 10) / (17 * CELL_X_SIZE); @@ -7005,7 +7005,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, // Effects of visual range // From for JA2.5: 3% bonus/penalty for each tile different from range NORMAL_RANGE. - if (!TANK(pSoldier)) // WANNE: No penalty on the tank + if ( !ARMED_VEHICLE( pSoldier ) ) // WANNE: No penalty on the tank iPenalty = 3 * ( NORMAL_RANGE - iSightRange ) / CELL_X_SIZE; if ( fCantSeeTarget ){ // CHRISL: There are conditions where iSightRange can still return 0. If that happens, the result is that "impossible" shots are actually easier then @@ -7043,7 +7043,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, switch( gAnimControl[ pTarget->usAnimState ].ubHeight ) { case ANIM_CROUCH: - if ( TANK( pSoldier ) && iRange < MIN_TANK_RANGE ) + if ( ARMED_VEHICLE( pSoldier ) && iRange < MIN_TANK_RANGE ) { // 13% penalty per tile closer than min range iChance -= (INT32)(13 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE )); @@ -7063,7 +7063,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, } break; case ANIM_PRONE: - if ( TANK( pSoldier ) && iRange < MIN_TANK_RANGE ) + if ( ARMED_VEHICLE( pSoldier ) && iRange < MIN_TANK_RANGE ) { // 25% penalty per tile closer than min range iChance -= (INT32)(25 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE ) * iPenalty); @@ -7204,7 +7204,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, // if target sees us, he may have a chance to dodge before the gun goes off // but ability to dodge is reduced if crouched or prone! - if (pTarget->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY && !TANK( pTarget ) && !(pSoldier->ubBodyType != QUEENMONSTER) ) + if ( pTarget->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY && !ARMED_VEHICLE( pTarget ) && !(pSoldier->ubBodyType != QUEENMONSTER) ) { iPenalty = ( EffectiveAgility( pTarget, FALSE ) / 5 + EffectiveExpLevel( pTarget ) * 2); switch( gAnimControl[ pTarget->usAnimState ].ubHeight ) @@ -7219,7 +7219,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, // reduce dodge ability by the attacker's stats iBonus = ( EffectiveDexterity( pSoldier, FALSE ) / 5 + EffectiveExpLevel( pSoldier ) * 2); - if ( TANK( pTarget ) || (pSoldier->ubBodyType != QUEENMONSTER) ) + if ( ARMED_VEHICLE( pTarget ) || (pSoldier->ubBodyType != QUEENMONSTER) ) { // reduce ability to track shots iBonus = iBonus / 2; @@ -7235,7 +7235,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, iChance -= iPenalty; } } - else if ( TANK( pSoldier ) && iRange < MIN_TANK_RANGE ) + else if ( ARMED_VEHICLE( pSoldier ) && iRange < MIN_TANK_RANGE ) { // 25% penalty per tile closer than min range iChance -= 25 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE ); @@ -7802,7 +7802,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, // be an effective CTH of only 1/5000 (50 chances to get a 1 out of 100 CTH, hehehe) if (iChance <= gGameExternalOptions.ubMinimumCTH) { - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { // allow absolute minimums iChance = 0; @@ -8626,12 +8626,12 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, if ( iPenalty < 0 ) { // No penalty on tanks - //if (!TANK(pSoldier)) + //if (!ARMED_VEHICLE(pSoldier)) iChance += iPenalty; } //iChance -= 20 * iRange / iMaxRange; - if ( TANK( pSoldier ) && ( iRange / CELL_X_SIZE < MaxNormalDistanceVisible() ) ) + if ( ARMED_VEHICLE( pSoldier ) && ( iRange / CELL_X_SIZE < MaxNormalDistanceVisible() ) ) { // tank; penalize at close range! // 2 percent per tile closer than max visible distance @@ -8655,7 +8655,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, // range less penalized, and longer range more penalized // WANNE: No penalty on the tank - if (!TANK(pSoldier)) + if (!ARMED_VEHICLE(pSoldier)) iChance += 3 * ( NORMAL_RANGE - iSightRange ) / CELL_X_SIZE; // if aiming at the head, reduce chance to hit if (ubAimPos == AIM_SHOT_HEAD) @@ -9567,15 +9567,31 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, ubAmmoType = Explosive[Item[usAttackingWeapon].ubClassIndex].ubFragType; } - if ( TANK( pTarget ) ) + // Flugente: ammotype can alter the damage dealt + FLOAT damagefactor = AmmoTypes[ubAmmoType].dDamageModifierLife; + + if ( pTarget->IsZombie( ) ) { - if ( !AmmoTypes[ubAmmoType].antiTank ) + damagefactor *= AmmoTypes[ubAmmoType].dDamageModifierZombie; + } + else if ( pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE ) + { + if ( COMBAT_JEEP( pTarget ) || AM_A_ROBOT( pTarget ) ) { - // ping! - return( 0 ); + damagefactor *= AmmoTypes[ubAmmoType].dDamageModifierArmouredVehicle; + } + else if ( TANK( pTarget ) ) + { + damagefactor *= AmmoTypes[ubAmmoType].dDamageModifierTank; + } + else + { + damagefactor *= AmmoTypes[ubAmmoType].dDamageModifierCivilianVehicle; } } + iOrigImpact = iOrigImpact * damagefactor; + // plus/minus up to 25% due to "random" factors (major organs hit or missed, // lucky lighter in breast pocket, divine intervention on behalf of "Rev"...) iFluke = PreRandom(51) - 25; // gives (0 to 50 -25)->-25% to +25% @@ -9622,9 +9638,6 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, pTarget->iLastArmourProtection += iTotalArmourProtection; } - // Flugente: ammotype can alter the damage dealt - iImpact *= AmmoTypes[ubAmmoType].dDamageModifierLife; - // calc minimum damage if ( AmmoTypes[ubAmmoType].zeroMinimumDamage ) { @@ -9654,14 +9667,14 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, } // Flugente: if this is cryo ammo, freeze target. - if ( !TANK( pTarget ) && !(pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE) && AmmoTypes[ubAmmoType].ammoflag & AMMO_CRYO ) + if ( !ARMED_VEHICLE( pTarget ) && !(pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE) && AmmoTypes[ubAmmoType].ammoflag & AMMO_CRYO ) { pTarget->usSkillCooldown[SOLDIER_COOLDOWN_CRYO] += 2; ShutupaYoFace( pTarget->iFaceIndex ); } - if ( iImpact > 0 && !TANK( pTarget ) ) + if ( iImpact > 0 && !ARMED_VEHICLE( pTarget ) ) { // Flugente: any bullet can have drug effects it set so in the magazine item if ( ammoitem != NOTHING ) diff --git a/Tactical/Weapons.h b/Tactical/Weapons.h index 9154b024..a79d471a 100644 --- a/Tactical/Weapons.h +++ b/Tactical/Weapons.h @@ -252,7 +252,6 @@ typedef struct INT32 multipleBulletDamageDivisor; UINT16 highExplosive; UINT8 explosionSize; //0=none, 1=small, 2=medium, 3=large - BOOLEAN antiTank; BOOLEAN dart; BOOLEAN knife; UINT16 monsterSpit; @@ -272,7 +271,11 @@ typedef struct // Flugente: modifiers for life and breath damage, 1.0 being the unmodified value FLOAT dDamageModifierLife; FLOAT dDamageModifierBreath; - + FLOAT dDamageModifierTank; + FLOAT dDamageModifierArmouredVehicle; + FLOAT dDamageModifierCivilianVehicle; + FLOAT dDamageModifierZombie; + } AMMOTYPE; enum diff --git a/Tactical/XML_AmmoTypes.cpp b/Tactical/XML_AmmoTypes.cpp index 73dd7b00..b0249f68 100644 --- a/Tactical/XML_AmmoTypes.cpp +++ b/Tactical/XML_AmmoTypes.cpp @@ -71,7 +71,6 @@ ammotypeStartElementHandle(void *userData, const XML_Char *name, const XML_Char strcmp(name, "spreadPattern") == 0 || strcmp(name, "highExplosive") == 0 || strcmp(name, "explosionSize") == 0 || - strcmp(name, "antiTank") == 0 || strcmp(name, "dart") == 0 || strcmp(name, "knife") == 0 || strcmp(name, "ignoreArmour") == 0 || @@ -83,7 +82,11 @@ ammotypeStartElementHandle(void *userData, const XML_Char *name, const XML_Char strcmp(name, "dirtModificator") == 0 || strcmp(name, "ammoflag" ) == 0 || strcmp(name, "dDamageModifierLife" ) == 0 || - strcmp(name, "dDamageModifierBreath") == 0 )) + strcmp(name, "dDamageModifierBreath" ) == 0 || + strcmp(name, "dDamageModifierTank" ) == 0 || + strcmp(name, "dDamageModifierArmouredVehicle" ) == 0 || + strcmp(name, "dDamageModifierCivilianVehicle" ) == 0 || + strcmp(name, "dDamageModifierZombie") == 0 )) { pData->curElement = ELEMENT_PROPERTY; @@ -246,11 +249,6 @@ ammotypeEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curAmmoType.explosionSize = (UINT8) atol(pData->szCharData); } - else if(strcmp(name, "antiTank") == 0) - { - pData->curElement = ELEMENT; - pData->curAmmoType.antiTank = (BOOLEAN) atol(pData->szCharData); - } else if(strcmp(name, "dart") == 0) { pData->curElement = ELEMENT; @@ -312,7 +310,39 @@ ammotypeEndElementHandle(void *userData, const XML_Char *name) // reasonable values only pData->curAmmoType.dDamageModifierBreath = min( 100.0f, max( 0.0f, pData->curAmmoType.dDamageModifierBreath ) ); } + else if ( strcmp( name, "dDamageModifierTank" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curAmmoType.dDamageModifierTank = (FLOAT)atof( pData->szCharData ); + // reasonable values only + pData->curAmmoType.dDamageModifierTank = min( 100.0f, max( 0.0f, pData->curAmmoType.dDamageModifierTank ) ); + } + else if ( strcmp( name, "dDamageModifierArmouredVehicle" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curAmmoType.dDamageModifierArmouredVehicle = (FLOAT)atof( pData->szCharData ); + + // reasonable values only + pData->curAmmoType.dDamageModifierArmouredVehicle = min( 100.0f, max( 0.0f, pData->curAmmoType.dDamageModifierArmouredVehicle ) ); + } + else if ( strcmp( name, "dDamageModifierCivilianVehicle" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curAmmoType.dDamageModifierCivilianVehicle = (FLOAT)atof( pData->szCharData ); + + // reasonable values only + pData->curAmmoType.dDamageModifierCivilianVehicle = min( 100.0f, max( 0.0f, pData->curAmmoType.dDamageModifierCivilianVehicle ) ); + } + else if ( strcmp( name, "dDamageModifierZombie" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curAmmoType.dDamageModifierZombie = (FLOAT)atof( pData->szCharData ); + + // reasonable values only + pData->curAmmoType.dDamageModifierZombie = min( 100.0f, max( 0.0f, pData->curAmmoType.dDamageModifierZombie ) ); + } + pData->maxReadDepth--; } @@ -425,7 +455,6 @@ BOOLEAN WriteAmmoTypeStats() FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].multipleBulletDamageDivisor ); FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].highExplosive ); FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].explosionSize ); - FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].antiTank ); FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].dart ); FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].knife ); FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].monsterSpit ); @@ -438,7 +467,11 @@ BOOLEAN WriteAmmoTypeStats() FilePrintf(hFile,"\t\t%d\r\n", AmmoTypes[cnt].ammoflag ); FilePrintf(hFile,"\t\t%4.2f\r\n", AmmoTypes[cnt].dDamageModifierLife ); FilePrintf(hFile,"\t\t%4.2f\r\n", AmmoTypes[cnt].dDamageModifierBreath ); - + FilePrintf(hFile,"\t\t%4.2f\r\n", AmmoTypes[cnt].dDamageModifierTank ); + FilePrintf(hFile,"\t\t%4.2f\r\n", AmmoTypes[cnt].dDamageModifierArmouredVehicle ); + FilePrintf(hFile,"\t\t%4.2f\r\n", AmmoTypes[cnt].dDamageModifierCivilianVehicle ); + FilePrintf(hFile,"\t\t%4.2f\r\n", AmmoTypes[cnt].dDamageModifierZombie ); + FilePrintf(hFile,"\t\r\n"); } FilePrintf(hFile,"\r\n"); diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index fa5855c6..a3ce718d 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -1233,7 +1233,7 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, } } - if ( bFacingDir == DIRECTION_IRRELEVANT && TANK( pSoldier ) ) + if ( bFacingDir == DIRECTION_IRRELEVANT && ARMED_VEHICLE( pSoldier ) ) { // always calculate direction for tanks so we have something to work with bFacingDir = pSoldier->pathing.bDesiredDirection; @@ -1241,7 +1241,7 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, //bSubjectDir = atan8(pSoldier->sX,pSoldier->sY,pOpponent->sX,pOpponent->sY); } - if ( !TANK( pSoldier ) && ( bFacingDir == DIRECTION_IRRELEVANT || (pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT) || (pSubject && pSubject->flags.fMuzzleFlash) ) ) + if ( !ARMED_VEHICLE( pSoldier ) && (bFacingDir == DIRECTION_IRRELEVANT || (pSoldier->flags.uiStatusFlags & SOLDIER_ROBOT) || (pSubject && pSubject->flags.fMuzzleFlash)) ) { sDistVisible = MaxNormalDistanceVisible(); } @@ -1385,10 +1385,10 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, } // let tanks see and be seen further (at night) - if ( (TANK( pSoldier ) && sDistVisible > 0) || (pSubject && TANK( pSubject ) ) ) + if ( (ARMED_VEHICLE( pSoldier ) && sDistVisible > 0) || (pSubject && ARMED_VEHICLE( pSubject )) ) { #if 0 - if ( TANK(pSoldier) && sDistVisible > 0 && pSubject) + if ( ARMED_VEHICLE(pSoldier) && sDistVisible > 0 && pSubject) { sDistVisible = __max( sDistVisible + 5, pSubject->GetMaxDistanceVisible(pSoldier->sGridNo, pSoldier->pathing.bLevel) ); } @@ -1561,7 +1561,7 @@ INT8 DecideHearing( SOLDIERTYPE * pSoldier ) // calculate the hearing value for the merc... INT8 bHearing; - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { return( -5 ); } @@ -6443,7 +6443,7 @@ void HearNoise(SOLDIERTYPE *pSoldier, UINT8 ubNoiseMaker, INT32 sGridNo, INT8 bL // (taking into account we are definitely aware of this guy now) // skip LOS check if we had to turn and we're a tank. sorry Mr Tank, no looking out of the sides for you! - if ( !( bHadToTurn && TANK( pSoldier ) ) ) + if ( !(bHadToTurn && ARMED_VEHICLE( pSoldier )) ) { if ( SoldierTo3DLocationLineOfSightTest( pSoldier, sGridNo, bLevel, 0, TRUE, sDistVisible ) ) { diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 57e36fd5..c7072446 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -346,7 +346,7 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named return; } - if ( ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ( (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !TANK( pSoldier ) ) ) || AM_A_ROBOT( pSoldier ) ) + if ( (!gGameExternalOptions.fEnemyTanksCanMoveInTactical && ((pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !ARMED_VEHICLE( 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( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK(pSoldier))//dnl ch64 290813 + if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 SkipCoverCheck = FALSE; // turn off new situation flag to stop this from repeating all the time! @@ -1501,7 +1501,7 @@ void RefreshAI(SOLDIERTYPE *pSoldier) if (pSoldier->aiData.bAlertStatus == STATUS_YELLOW) SkipCoverCheck = FALSE; - if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK(pSoldier) )//dnl ch64 290813 tanks don't have move animations + if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 tanks don't have move animations SkipCoverCheck = TRUE; // if he's in battle or knows opponents are here @@ -1589,7 +1589,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( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK(pSoldier) )//dnl ch64 290813 + if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 SkipCoverCheck = FALSE; // reset this field, too @@ -2607,6 +2607,10 @@ void HandleAITacticalTraversal( SOLDIERTYPE * pSoldier ) ++pSectorInfo->ubNumTanks; break; + case SOLDIER_CLASS_JEEP: + if ( COMBAT_JEEP( pSoldier ) ) + ++pSectorInfo->ubNumJeeps; + break; } ProcessQueenCmdImplicationsOfDeath( pSoldier ); diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index 9856dc74..1b96a032 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -2509,15 +2509,17 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 * pusFromGridNo) { // JA2 GOLD: give non-NPCs a 5 tile roam range for cover in combat when being shot at // 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 ); - } - else - { - return( 5 ); - } - case ONGUARD: return( 5 ); + case STATIONARY: + if ( (pSoldier->ubProfile != NO_PROFILE && !ARMED_VEHICLE( pSoldier )) || (pSoldier->aiData.bAlertStatus < STATUS_BLACK && !(pSoldier->aiData.bUnderFire)) ) + { + return( 0 ); + } + else + { + return( 5 ); + } + case ONGUARD: + return( 5 ); case CLOSEPATROL: if (pSoldier->aiData.bAlertStatus < STATUS_RED) { return( 5 ); @@ -3122,7 +3124,7 @@ UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au continue; // this is not for tanks - if ( TANK(pFriend) ) + if ( ARMED_VEHICLE( pFriend ) ) return FALSE; // skip if this guy is dead @@ -3175,7 +3177,7 @@ UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au continue; // this is not for tanks - if ( TANK(pFriend) ) + if ( ARMED_VEHICLE( pFriend ) ) return FALSE; // skip if this guy is dead, or not wounded (enough) @@ -3224,7 +3226,7 @@ UINT8 GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTe continue; // this is not for tanks - if ( TANK(pFriend) ) + if ( ARMED_VEHICLE( pFriend ) ) return FALSE; // skip this guy if he is dead or unconscious diff --git a/TacticalAI/Attacks.cpp b/TacticalAI/Attacks.cpp index c208a363..eddac550 100644 --- a/TacticalAI/Attacks.cpp +++ b/TacticalAI/Attacks.cpp @@ -110,7 +110,7 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier) DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("LoadWeaponIfNeeded: remove payload from its pocket, and add it as the hand weapon's first attachment")); // remove payload from its pocket, and add it as the hand weapon's first attachment - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { // don't remove ammo gTempObject = pSoldier->inv[bPayloadPocket]; @@ -375,7 +375,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns // calculate the maximum possible aiming time #if 0//dnl ch64 270813 maybe I'm wrong but don't see purpose of this - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { ubMaxPossibleAimTime = pSoldier->bActionPoints - ubMinAPcost; @@ -407,7 +407,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns //NumMessage("ubAimTime = ",ubAimTime); //dnl ch59 180813 Find true best chance to hit depending of stance so AI would be more eager to attack ubChanceToHit = AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo,ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, STANDING); - if(!TANK(pSoldier))//dnl ch64 270813 + if(!ARMED_VEHICLE(pSoldier))//dnl ch64 270813 { if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, CROUCHING)) > ubChanceToHit) ubChanceToHit = ubChanceToHit2; @@ -437,7 +437,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns ubAimTime = APBPConstants[AP_MIN_AIM_ATTACK]; //dnl ch59 180813 Find true best chance to hit depending of stance for autofire ubChanceToHit = AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, STANDING); - if(!TANK(pSoldier))//dnl ch64 270813 + if(!ARMED_VEHICLE(pSoldier))//dnl ch64 270813 { if((ubChanceToHit2=AICalcChanceToHitGun(pSoldier, pOpponent->sGridNo, ubAimTime, AIM_SHOT_TORSO, pOpponent->pathing.bLevel, CROUCHING)) > ubChanceToHit) ubChanceToHit = ubChanceToHit2; @@ -514,7 +514,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns pSoldier->usAnimState = usTrueState; pSoldier->sLastTarget = iTrueLastTarget; } - if(pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD || TANK(pSoldier) || (Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE)) + if ( pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD || ARMED_VEHICLE( pSoldier ) || (Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE) ) continue; ubStance = ANIM_CROUCH; if(IsValidStance(pSoldier, ubStance)) @@ -1102,7 +1102,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow) // they won't use them until they have 2+ opponents as long as half life left // anv: tanks don't care if ( ( ubOpponentCnt < 2 ) && ( pSoldier->stats.bLife > pSoldier->stats.bLifeMax / 2 ) && - ( !gGameExternalOptions.fEnemyTanksDontSpareShells || !TANK(pSoldier) ) && !gGameExternalOptions.fEnemiesDontSpareLaunchables ) + (!gGameExternalOptions.fEnemyTanksDontSpareShells || !ARMED_VEHICLE( pSoldier )) && !gGameExternalOptions.fEnemiesDontSpareLaunchables ) { return; } @@ -1110,7 +1110,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow) 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 ) && - ( !gGameExternalOptions.fEnemyTanksDontSpareShells || !TANK(pSoldier) ) && !gGameExternalOptions.fEnemiesDontSpareLaunchables ) + (!gGameExternalOptions.fEnemyTanksDontSpareShells || !ARMED_VEHICLE( pSoldier )) && !gGameExternalOptions.fEnemiesDontSpareLaunchables ) { return; } @@ -1350,7 +1350,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow) ubChanceToGetThrough = AISoldierToLocationChanceToGetThrough( pSoldier, sGridNo, bOpponentLevel[ubLoop], 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 ) + if ( (gGameExternalOptions.fEnemyTanksBlowObstaclesUp && ARMED_VEHICLE( pSoldier )) || gGameExternalOptions.fEnemiesBlowObstaclesUp ) { ubChanceToGetThrough = 100; } @@ -1395,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)) && ( !gGameExternalOptions.fEnemyTanksDontSpareShells || !TANK(pSoldier) ) && !gGameExternalOptions.fEnemiesDontSpareLaunchables ) + (pSoldier->stats.bLife >( pSoldier->stats.bLifeMax / 2 )) && (!gGameExternalOptions.fEnemyTanksDontSpareShells || !ARMED_VEHICLE( pSoldier )) && !gGameExternalOptions.fEnemiesDontSpareLaunchables ) { continue; // next gridno } @@ -2982,7 +2982,7 @@ void CheckIfShotPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN s pBestShot->ubPossible = FALSE; pBestShot->bWeaponIn = NO_SLOT; - if ( !TANK( pSoldier ) ) + if ( !ARMED_VEHICLE( pSoldier ) ) { // AIs never have more than one gun anyway pBestShot->bWeaponIn = FindAIUsableObjClass( pSoldier, IC_GUN ); diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index 8aa10fef..d38e1c1b 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -782,7 +782,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier) } } - if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) ) + if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE( pSoldier ) ) { return( AI_ACTION_NONE ); } @@ -793,6 +793,12 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier) // check if standing in tear gas without a gas mask on, or in smoke bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo ); + // Flugente: tanks do not care about gas + if ( ARMED_VEHICLE( pSoldier ) ) + { + bInGas = FALSE; + } + // if real-time, and not in the way, do nothing 90% of the time (for GUARDS!) // unless in water (could've started there), then we better swim to shore! @@ -1875,7 +1881,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier) } } - if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) ) + if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE( pSoldier ) ) { return( AI_ACTION_NONE ); } @@ -2480,6 +2486,12 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) // check if standing in tear gas without a gas mask on bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo ); + // Flugente: tanks do not care about gas + if ( ARMED_VEHICLE( pSoldier ) ) + { + bInGas = FALSE; + } + //////////////////////////////////////////////////////////////////////////// // WHEN LEFT IN GAS, WEAR GAS MASK IF AVAILABLE AND NOT WORN //////////////////////////////////////////////////////////////////////////// @@ -3346,7 +3358,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) } //if ( !TANK( pSoldier ) ) - if( ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK( pSoldier ) ) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) ) + if ( (gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier )) && !(pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER | SOLDIER_PASSENGER)) ) { DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: main red ai"); @@ -4112,7 +4124,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) if (pSoldier->aiData.bAttitude == DEFENSIVE) iChance += 25; - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { iChance += 50; } @@ -4184,7 +4196,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) } } - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { // try turning in a random direction as we still can't see anyone. if (!gfTurnBasedAI || GetAPsToLook( pSoldier ) <= pSoldier->bActionPoints) @@ -4569,6 +4581,12 @@ INT16 ubMinAPCost; // check if standing in tear gas without a gas mask on bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo ); + // Flugente: tanks do not care about gas + if ( ARMED_VEHICLE( pSoldier ) ) + { + bInGas = FALSE; + } + // calculate our morale pSoldier->aiData.bAIMorale = CalcMorale(pSoldier); @@ -4675,7 +4693,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 && !TANK(pSoldier) ) + if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !(gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !ARMED_VEHICLE( pSoldier ) ) { if ( gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 && gTacticalStatus.Team[ CREATURE_TEAM ].bMenInSector == 0 && NumPCsInSector() < 4 && gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector >= NumPCsInSector() * 3 ) { @@ -5089,7 +5107,7 @@ INT16 ubMinAPCost; // if the soldier does have a usable knife somewhere // 0verhaul: And is not a tank! - if (bWeaponIn != NO_SLOT && !TANK( pSoldier) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) ) + if ( bWeaponIn != NO_SLOT && !ARMED_VEHICLE( pSoldier ) && !(pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER | SOLDIER_PASSENGER)) ) { DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"try to stab"); BestStab.bWeaponIn = bWeaponIn; @@ -5157,7 +5175,7 @@ INT16 ubMinAPCost; } ///////////////////////////////////////////////////////////////////////////////////////////////////// // SANDRO - even if we don't have any blade, calculate how much damage we could do unarmed - else if ( !TANK( pSoldier) && !( pSoldier->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) ) ) + else if ( !ARMED_VEHICLE( 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 @@ -5301,7 +5319,7 @@ INT16 ubMinAPCost; } //////////////////////////////////////////////////////////////////////////////////// } - if (BestThrow.ubPossible && ((BestThrow.iAttackValue > BestAttack.iAttackValue) || (ubBestAttackAction == AI_ACTION_NONE)) && !(TANK(pSoldier) && ubBestAttackAction == AI_ACTION_FIRE_GUN && BestShot.ubChanceToReallyHit > 20 && Random(2)))//dnl ch64 290813 tank always had better chance to fire from cannon so this will increase probabilty to use machinegun too + if ( BestThrow.ubPossible && ((BestThrow.iAttackValue > BestAttack.iAttackValue) || (ubBestAttackAction == AI_ACTION_NONE)) && !(ARMED_VEHICLE( pSoldier ) && ubBestAttackAction == AI_ACTION_FIRE_GUN && BestShot.ubChanceToReallyHit > 20 && Random( 2 )) )//dnl ch64 290813 tank always had better chance to fire from cannon so this will increase probabilty to use machinegun too { ubBestAttackAction = AI_ACTION_TOSS_PROJECTILE; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"best action = throw something"); @@ -5538,7 +5556,7 @@ INT16 ubMinAPCost; { #ifndef dnlCALCBESTSHOT//dnl ch69 140913 // Do we need to change stance? NB We'll have to ready our gun again - if ( !TANK( pSoldier ) && ( pSoldier->bActionPoints >= BestAttack.ubAPCost + GetAPsCrouch( pSoldier, TRUE) + MinAPsToAttack( pSoldier, BestAttack.sTarget, ADDTURNCOST,0, 1 ) ) ) + if ( !ARMED_VEHICLE( pSoldier ) && ( pSoldier->bActionPoints >= BestAttack.ubAPCost + GetAPsCrouch( pSoldier, TRUE) + MinAPsToAttack( pSoldier, BestAttack.sTarget, ADDTURNCOST,0, 1 ) ) ) { // since the AI considers shooting chance from standing primarily, if we are not // standing we should always consider a stance change @@ -5613,7 +5631,7 @@ INT16 ubMinAPCost; } } #else - if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK(pSoldier) ) + if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( 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)); @@ -5668,7 +5686,7 @@ INT16 ubMinAPCost; if (pSoldier->bActionPoints >= BestAttack.ubAPCost + sActualAimTime + ubBurstAPs ) { // Base chance of bursting is 25% if best shot was +0 aim, down to 8% at +4 - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { iChance = 100; } @@ -5770,7 +5788,7 @@ L_NEWAIM: if (pSoldier->bActionPoints >= BestAttack.ubAPCost + sActualAimTime + ubBurstAPs ) { // Base chance of bursting is 25% if best shot was +0 aim, down to 8% at +4 - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { iChance = 100; } @@ -6038,7 +6056,7 @@ L_NEWAIM: if ( (pSoldier->bActionPoints - BestAttack.ubAPCost) >= ubBurstAPs ) { // Base chance of bursting is 25% if best shot was +0 aim, down to 8% at +4 - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { iChance = 100; } @@ -6083,7 +6101,7 @@ L_NEWAIM: } // end of tank AI - if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) ) + if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE( pSoldier ) ) { return( AI_ACTION_NONE ); } @@ -6711,7 +6729,7 @@ INT8 ZombieDecideActionGreen(SOLDIERTYPE *pSoldier) gubNPCPathCount = 0; - if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) ) + if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE( pSoldier ) ) { return( AI_ACTION_NONE ); } @@ -7223,7 +7241,7 @@ INT8 ZombieDecideActionYellow(SOLDIERTYPE *pSoldier) } } - if( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && TANK( pSoldier ) ) + if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE( pSoldier ) ) { return( AI_ACTION_NONE ); } @@ -7382,7 +7400,7 @@ INT8 ZombieDecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) // RADIO RED ALERT: determine %chance to call others and report contact //////////////////////////////////////////////////////////////////////////// - if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !TANK( pSoldier ) ) + if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier ) ) { DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: main red ai"); @@ -7878,7 +7896,7 @@ INT8 ZombieDecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) if (pSoldier->aiData.bAttitude == DEFENSIVE) iChance += 25; - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { iChance += 50; } @@ -7897,7 +7915,7 @@ INT8 ZombieDecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) } } - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { // try turning in a random direction as we still can't see anyone. if (!gfTurnBasedAI || GetAPsToLook( pSoldier ) <= pSoldier->bActionPoints) @@ -8174,7 +8192,7 @@ INT8 ZombieDecideActionBlack(SOLDIERTYPE *pSoldier) ///////////////////////////////////////////////////////////////////////////////////////////////////// // SANDRO - even if we don't have any blade, calculate how much damage we could do unarmed - if ( !TANK( pSoldier) ) + if ( !ARMED_VEHICLE( pSoldier ) ) { bWeaponIn = FindAIUsableObjClass( pSoldier, IC_PUNCH ); if (bWeaponIn == NO_SLOT) // if no punch-type weapon found, just calculate it with empty hands @@ -8518,7 +8536,7 @@ INT8 ZombieDecideActionBlack(SOLDIERTYPE *pSoldier) if ( (pSoldier->bActionPoints - BestAttack.ubAPCost) >= ubBurstAPs ) { // Base chance of bursting is 25% if best shot was +0 aim, down to 8% at +4 - if ( TANK( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) ) { iChance = 100; } @@ -8563,7 +8581,7 @@ INT8 ZombieDecideActionBlack(SOLDIERTYPE *pSoldier) } // end of tank AI - if( gGameExternalOptions.fEnemyTanksCanMoveInTactical || TANK( pSoldier ) ) + if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || ARMED_VEHICLE( pSoldier ) ) { return( AI_ACTION_NONE ); } diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 3d6ee79f..70943e1f 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -1617,7 +1617,7 @@ BOOLEAN DamageSoldierFromBlast( UINT8 ubPerson, UINT8 ubOwner, INT32 sBombGridNo sNewWoundAmt = (INT16)(((sNewWoundAmt * (100 + gSkillTraitValues.ubDEDamageOfBombsAndMines)) / 100) + 0.5); } // Heavy Weapons trait bonus damage to tanks - if ( HAS_SKILL_TRAIT( MercPtrs[ ubOwner ], HEAVY_WEAPONS_NT ) && TANK( pSoldier ) && + if ( HAS_SKILL_TRAIT( MercPtrs[ubOwner], HEAVY_WEAPONS_NT ) && ARMED_VEHICLE( pSoldier ) && Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_NORMAL ) { sNewWoundAmt = (INT16)(((sNewWoundAmt * (100 + gSkillTraitValues.ubHWDamageTanksBonusPercent * NUM_SKILL_TRAITS( MercPtrs[ ubOwner ], HEAVY_WEAPONS_NT ))) / 100) + 0.5); // +30% @@ -1633,7 +1633,7 @@ BOOLEAN DamageSoldierFromBlast( UINT8 ubPerson, UINT8 ubOwner, INT32 sBombGridNo } } // adjust damage resistance of TANKS - if ( TANK( pSoldier ) && gGameOptions.fNewTraitSystem ) + if ( ARMED_VEHICLE( pSoldier ) && gGameOptions.fNewTraitSystem ) { sNewWoundAmt = (INT16)(sNewWoundAmt * (100 - gSkillTraitValues.bTanksDamageResistanceModifier) / 100); // another half of this for ordinary grenades @@ -1651,7 +1651,7 @@ BOOLEAN DamageSoldierFromBlast( UINT8 ubPerson, UINT8 ubOwner, INT32 sBombGridNo ; // we can loose stats due to being hit by the blast else if ( gGameOptions.fNewTraitSystem && Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_NORMAL && - !AM_A_ROBOT( pSoldier ) && !(pSoldier->flags.uiStatusFlags & SOLDIER_MONSTER) && !TANK(pSoldier) && + !AM_A_ROBOT( pSoldier ) && !(pSoldier->flags.uiStatusFlags & SOLDIER_MONSTER) && !ARMED_VEHICLE( pSoldier ) && sNewWoundAmt > 2 && sNewWoundAmt < pSoldier->stats.bLife ) { if ( PreRandom( sNewWoundAmt ) > gSkillTraitValues.ubDamageNeededToLoseStats ) @@ -4496,7 +4496,7 @@ BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8 if ( !fAllBombs && ubID != NOBODY && Item[pObj->usItem].antitankmine ) { // if this is not a vehicle, not a robot and not a tank, don't activate - if ( !(MercPtrs[ubID]->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT( MercPtrs[ubID] ) && !TANK( MercPtrs[ubID] ) ) + if ( !(MercPtrs[ubID]->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT( MercPtrs[ubID] ) && !ARMED_VEHICLE( MercPtrs[ubID] ) ) continue; } diff --git a/TileEngine/structure.cpp b/TileEngine/structure.cpp index ece096df..2b7d310d 100644 --- a/TileEngine/structure.cpp +++ b/TileEngine/structure.cpp @@ -651,7 +651,11 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC { fVehicleIgnoreObstacles = TRUE; } - else if( gGameExternalOptions.ubTanksRammingMaxStructureArmour && sSoldierID != NOBODY && TANK( MercPtrs[ sSoldierID ] ) ) + else if ( gGameExternalOptions.ubEnemyJeepsRammingMaxStructureArmour && sSoldierID != NOBODY && COMBAT_JEEP( MercPtrs[sSoldierID] ) ) + { + fVehicleIgnoreObstacles = TRUE; + } + else if ( gGameExternalOptions.ubTanksRammingMaxStructureArmour && sSoldierID != NOBODY && TANK( MercPtrs[sSoldierID] ) ) { fVehicleIgnoreObstacles = TRUE; } @@ -737,15 +741,15 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC // but not monsters and such (they can't fall down due to lack of animations) // also make sure AI won't flatten their allies if( !( pSoldier->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_ROBOT | SOLDIER_MONSTER ) ) && - ( ( !TANK(MercPtrs[ sSoldierID ]) && gGameExternalOptions.fAllowCarsDrivingOverPeople ) || - ( TANK(MercPtrs[ sSoldierID ]) && gGameExternalOptions.fAllowTanksDrivingOverPeople ) ) && + ((!ARMED_VEHICLE( MercPtrs[sSoldierID] ) && gGameExternalOptions.fAllowCarsDrivingOverPeople) || + (ARMED_VEHICLE( MercPtrs[sSoldierID] ) && gGameExternalOptions.fAllowTanksDrivingOverPeople)) && ( MercPtrs[ sSoldierID ]->bTeam == gbPlayerNum || MercPtrs[ sSoldierID ]->bTeam != pSoldier->bTeam ) ) { pExistingStructure = pExistingStructure->pNext; // damage people when driving on them if( fAddingForReal ) { - if( TANK( MercPtrs[ sSoldierID ] ) ) + if ( TANK( MercPtrs[sSoldierID] ) ) { pSoldier->EVENT_SoldierGotHit( 0, Random(10)+5, Random(200)+Random(200), MercPtrs[ sSoldierID ]->ubDirection, 0, sSoldierID, FIRE_WEAPON_VEHICLE_TRAUMA, 0, 0, pSoldier->sGridNo ); } @@ -771,8 +775,9 @@ BOOLEAN OkayToAddStructureToTile( INT32 sBaseGridNo, INT16 sCubeOffset, DB_STRUC else { // only if structure is weak enough - if( ( !TANK(MercPtrs[ sSoldierID ]) && gubMaterialArmour[ pExistingStructure->pDBStructureRef->pDBStructure->ubArmour ] < gGameExternalOptions.ubCarsRammingMaxStructureArmour ) || - ( TANK(MercPtrs[ sSoldierID ]) && gubMaterialArmour[ pExistingStructure->pDBStructureRef->pDBStructure->ubArmour ] < gGameExternalOptions.ubTanksRammingMaxStructureArmour ) ) + if ( (!ARMED_VEHICLE( MercPtrs[sSoldierID] ) && gubMaterialArmour[pExistingStructure->pDBStructureRef->pDBStructure->ubArmour] < gGameExternalOptions.ubCarsRammingMaxStructureArmour) || + (COMBAT_JEEP( MercPtrs[sSoldierID] ) && gubMaterialArmour[pExistingStructure->pDBStructureRef->pDBStructure->ubArmour] < gGameExternalOptions.ubEnemyJeepsRammingMaxStructureArmour) || + (TANK( MercPtrs[sSoldierID] ) && gubMaterialArmour[pExistingStructure->pDBStructureRef->pDBStructure->ubArmour] < gGameExternalOptions.ubTanksRammingMaxStructureArmour) ) { // when not just plotting path, really destroy structure if( fAddingForReal ) @@ -1915,7 +1920,7 @@ BOOLEAN DamageStructure( STRUCTURE * pStructure, UINT8 ubDamage, UINT8 ubReason, gpWorldLevelData[ sGridNo ].uiFlags |= MAPELEMENT_STRUCTURE_DAMAGED; // handle structure revenge - damage to vehicle - if ( ubOwner != NOBODY && MercPtrs[ubOwner] && !TANK( MercPtrs[ubOwner] ) ) + if ( ubOwner != NOBODY && MercPtrs[ubOwner] && !ARMED_VEHICLE( MercPtrs[ubOwner] ) ) { MercPtrs[ ubOwner ]->SoldierTakeDamage( 0, Random(max(0,(ubBaseArmour-10)/5))+max(0,(ubBaseArmour-10)/5), 0, TAKE_DAMAGE_STRUCTURE_EXPLOSION, NOBODY, MercPtrs[ ubOwner ]->sGridNo, 0, TRUE ); } diff --git a/Utils/Text.h b/Utils/Text.h index 0e77fb41..f58b8e0a 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -1863,6 +1863,7 @@ enum STR_MILITIAMOVEMENT_NO_STAFF_ABORT, STR_AR_TANK_NAME, + STR_AR_JEEP_NAME, STR_BREATH_REGEN_SLEEP, diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index c0b601bf..1b34242c 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -1546,6 +1546,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"成年公异形", //25 //L"Adt M Monster", L"异形女王", //L"Queen Monster", L"血猫", //L"Bloodcat", + L"Humvee", // TODO.Translate }; STR16 pUpdateMercsInfoText[] = @@ -3458,6 +3459,7 @@ STR16 gpStrategicString[] = L"超出战争(地图)范围,民兵移动失败!", //L"War room isn't staffed - militia move aborted!", L"坦克", //STR_AR_TANK_NAME, + L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate L"\n每一个小时刷新一次呼吸: %d", //L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index e5eb6c97..b9db5c13 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -1548,6 +1548,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"Adt M Monster", //25 L"Queen Monster", L"Bloodcat", + L"Humvee", // TODO.Translate }; STR16 pUpdateMercsInfoText[] = @@ -3456,6 +3457,7 @@ STR16 gpStrategicString[] = L"War room isn't staffed - militia move aborted!", L"Tank", //STR_AR_TANK_NAME, + L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index f39890b3..8ab6fe9b 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -1544,6 +1544,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"Adt M Monster", //25 L"Queen Monster", L"Bloodcat", + L"Humvee", }; STR16 pUpdateMercsInfoText[] = @@ -3456,6 +3457,7 @@ STR16 gpStrategicString[] = L"War room isn't staffed - militia move aborted!", L"Tank", //STR_AR_TANK_NAME, + L"Jeep", //STR_AR_JEEP_NAME, L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index cdd78abd..2c917c60 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -1550,6 +1550,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"Monstre Adt M", //25 L"Monstre Reine", L"Chat Sauvg", + L"Humvee", // TODO.Translate }; STR16 pUpdateMercsInfoText[] = @@ -3464,6 +3465,7 @@ STR16 gpStrategicString[] = L"La salle d'opérations n'est pas ouverte... Le mouvement de la milice a avorté !", L"Tank", //STR_AR_TANK_NAME, // TODO.Translate + L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 20e6726b..4a3ef24a 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -1569,6 +1569,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"Adt M Monster", //25 L"Queen Monster", L"Bloodcat", + L"Humvee", // TODO.Translate }; STR16 pUpdateMercsInfoText[] = @@ -3467,6 +3468,7 @@ STR16 gpStrategicString[] = L"War room isn't staffed - militia move aborted!", L"Panzer", //STR_AR_TANK_NAME, + L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index b5b18084..769943f8 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -1545,6 +1545,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"Adt M Monster", //25 L"Queen Monster", L"Bloodcat", + L"Humvee", // TODO.Translate }; STR16 pUpdateMercsInfoText[] = @@ -3451,6 +3452,7 @@ STR16 gpStrategicString[] = L"War room isn't staffed - militia move aborted!", L"Tank", //STR_AR_TANK_NAME, + L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 3d1d5eb1..a2a11007 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -1548,6 +1548,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"Adt M Monster", //25 L"Queen Monster", L"Dziki kot", + L"Humvee", // TODO.Translate }; STR16 pUpdateMercsInfoText[] = @@ -3462,6 +3463,7 @@ STR16 gpStrategicString[] = L"War room isn't staffed - militia move aborted!", L"Tank", //STR_AR_TANK_NAME, + L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 6a808f00..2d6b6574 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -1544,6 +1544,7 @@ STR16 pDisplayBodyTypeInfoText[] = L"Adt M Monster", //25 L"Queen Monster", L"Bloodcat", + L"Humvee", // TODO.Translate }; STR16 pUpdateMercsInfoText[] = @@ -3456,6 +3457,7 @@ STR16 gpStrategicString[] = L"War room isn't staffed - militia move aborted!", L"Танк", //STR_AR_TANK_NAME, + L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate L"\nВосстановление дыхания в час: %d", // STR_BREATH_REGEN_SLEEP }; diff --git a/lua/lua_strategic.cpp b/lua/lua_strategic.cpp index 719a7a8b..e9621762 100644 --- a/lua/lua_strategic.cpp +++ b/lua/lua_strategic.cpp @@ -158,8 +158,9 @@ static int LuaGroupCreate( lua_State *L ) UINT8 NumTroops = (UINT8) luaL_checkinteger( L, 3); UINT8 NumElites = (UINT8) luaL_checkinteger( L, 4); UINT8 NumTanks = (UINT8) luaL_checkinteger( L, 5); + UINT8 NumJeeps = (UINT8)luaL_checkinteger( L, 6 ); - GROUP *pGroup = CreateNewEnemyGroupDepartingFromSector( Sector, NumAdmins, NumTroops, NumElites, NumTanks ); + GROUP *pGroup = CreateNewEnemyGroupDepartingFromSector( Sector, NumAdmins, NumTroops, NumElites, NumTanks, NumJeeps ); if (pGroup) { diff --git a/ub_config.cpp b/ub_config.cpp index 17b91d64..47174d59 100644 --- a/ub_config.cpp +++ b/ub_config.cpp @@ -101,55 +101,56 @@ void RandomStats (); void RandomAddEnemy( UINT8 SectorX, UINT8 SectorY, UINT8 Level ) { -UNDERGROUND_SECTORINFO *pSector; -UINT8 ubNumAdmins = 0; -UINT8 ubNumTroops = 0; -UINT8 ubNumElites = 0; -UINT8 ubNumTanks = 0; + UNDERGROUND_SECTORINFO *pSector; + UINT8 ubNumAdmins = 0; + UINT8 ubNumTroops = 0; + UINT8 ubNumElites = 0; + UINT8 ubNumTanks = 0; + UINT8 ubNumJeeps = 0; if ( Level != 0 ) { - pSector = FindUnderGroundSector( SectorX, SectorY, Level ); - if ( pSector ) - { - if ( pSector->fVisited != TRUE ) + pSector = FindUnderGroundSector( SectorX, SectorY, Level ); + if ( pSector ) { - switch( gGameOptions.ubDifficultyLevel ) + if ( pSector->fVisited != TRUE ) { - case DIF_LEVEL_EASY: - ubNumAdmins = Random( 0 ); - ubNumTroops = 10 + Random( 5 ); - ubNumElites = Random( 4 ); - 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, ubNumTanks ); - break; - case DIF_LEVEL_HARD: - ubNumAdmins = Random( 0 ); - ubNumTroops = 20 + Random( 7 ); - ubNumElites = 2 + Random( 2 ); - 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, ubNumTanks ); - break; - default: - ubNumAdmins = Random( 0 ); - ubNumTroops = 10 + Random( 5 ); - ubNumElites = Random( 4 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); - break; + switch( gGameOptions.ubDifficultyLevel ) + { + case DIF_LEVEL_EASY: + ubNumAdmins = Random( 0 ); + ubNumTroops = 10 + Random( 5 ); + ubNumElites = Random( 4 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + break; + case DIF_LEVEL_MEDIUM: + ubNumAdmins = Random( 0 ); + ubNumTroops = 15 + Random( 8 ); + ubNumElites = 1 + Random( 2 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + break; + case DIF_LEVEL_HARD: + ubNumAdmins = Random( 0 ); + ubNumTroops = 20 + Random( 7 ); + ubNumElites = 2 + Random( 2 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + break; + case DIF_LEVEL_INSANE: + ubNumAdmins = Random( 0 ); + ubNumTroops = 20 + Random( 3 ); + ubNumElites = 6 + Random( 3 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + break; + default: + ubNumAdmins = Random( 0 ); + ubNumTroops = 10 + Random( 5 ); + ubNumElites = Random( 4 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + break; + } } } } - } else { if ( !GetSectorFlagStatus( SectorX, SectorY, Level, SF_ALREADY_VISITED ) ) @@ -160,32 +161,31 @@ UINT8 ubNumTanks = 0; ubNumAdmins = Random( 0 ); ubNumTroops = 10 + Random( 5 ); ubNumElites = Random( 4 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); break; case DIF_LEVEL_MEDIUM: ubNumAdmins = Random( 0 ); ubNumTroops = 15 + Random( 8 ); ubNumElites = 1 + Random( 2 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); break; case DIF_LEVEL_HARD: ubNumAdmins = Random( 0 ); ubNumTroops = 23 + Random( 7); ubNumElites = 2 + Random( 2 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); break; case DIF_LEVEL_INSANE: ubNumAdmins = Random( 0 ); ubNumTroops = 20 + Random( 3 ); ubNumElites = 6 + Random( 3 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); break; default: ubNumAdmins = Random( 0 ); ubNumTroops = 10 + Random( 5 ); ubNumElites = Random( 4 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks ); - break; + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); break; } }