diff --git a/GameSettings.cpp b/GameSettings.cpp index 62baf629..50d904e9 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1853,6 +1853,10 @@ void LoadGameExternalOptions() 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 ); + gGameExternalOptions.fArmyUsesRobotsInAttacks = iniReader.ReadBoolean( "Strategic Gameplay Settings", "ARMY_USES_ROBOTS_IN_ATTACKS", FALSE ); + gGameExternalOptions.fArmyUsesRobotsInPatrols = iniReader.ReadBoolean( "Strategic Gameplay Settings", "ARMY_USES_ROBOTS_IN_PATROLS", FALSE ); + gGameExternalOptions.usRobotMinimumProgress = iniReader.ReadInteger( "Strategic Gameplay Settings", "ROBOT_MINIMUM_PROGRESS", 45, 0, 100 ); + // Kaiden: Vehicle Inventory change - Added INI file Option VEHICLE_INVENTORY gGameExternalOptions.fVehicleInventory = iniReader.ReadBoolean("Strategic Gameplay Settings", "VEHICLE_INVENTORY", TRUE); @@ -2035,18 +2039,22 @@ void LoadGameExternalOptions() 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_Cost[ASD_ROBOT] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_COST_ROBOT", 25000, 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] = 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.gASDResource_BuyTime[ASD_ROBOT] = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_TIME_ROBOT", 60 * 12, 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.fASDAssignsRobots = iniReader.ReadBoolean( "Strategic Additional Enemy AI Settings", "ASD_ASSIGNS_ROBOTS", 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 ); + gGameExternalOptions.gASDResource_Fuel_Robot = iniReader.ReadInteger( "Strategic Additional Enemy AI Settings", "ASD_FUEL_REQUIRED_ROBOT", 0, 0, 10000 ); // Flugente: enemy heli //################# Enemy Helicopter Settings ################## diff --git a/GameSettings.h b/GameSettings.h index b98929e2..5f357d05 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -223,6 +223,7 @@ enum ASD_HELI, ASD_JEEP, ASD_TANK, + ASD_ROBOT, ASD_RESOURCE_MAX }; @@ -686,9 +687,11 @@ typedef struct BOOLEAN fASDAssignsTanks; BOOLEAN fASDAssignsJeeps; + BOOLEAN fASDAssignsRobots; INT32 gASDResource_Fuel_Tank; INT32 gASDResource_Fuel_Jeep; + INT32 gASDResource_Fuel_Robot; // Flugente: enemy heli BOOLEAN fEnemyHeliActive; @@ -947,6 +950,10 @@ typedef struct BOOLEAN fArmyUsesJeepsInPatrols; UINT8 usJeepMinimumProgress; + BOOLEAN fArmyUsesRobotsInAttacks; + BOOLEAN fArmyUsesRobotsInPatrols; + UINT8 usRobotMinimumProgress; + // WANNE: Always use "prof.dat". BOOLEAN fUseDifficultyBasedProfDat; diff --git a/GameVersion.h b/GameVersion.h index 4fa11cd9..e20e7887 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -22,6 +22,7 @@ extern CHAR16 zRevisionNumber[16]; // Keeps track of the saved game version. Increment the saved game version whenever // you will invalidate the saved game file +#define ENEMY_ROBOTS 183 // rftr: enemy robots #define DRAGSTRUCTURE 182 // Flugente: we can drag structures behind us #define DISABILITYFLAGMASK 181 // Flugente: disabilities get a flagmask #define PROFILETYPE_STORED 180 // Flugente: the type of each profile is stored in the savegame @@ -102,7 +103,7 @@ extern CHAR16 zRevisionNumber[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 DRAGSTRUCTURE +#define SAVE_GAME_VERSION ENEMY_ROBOTS //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Laptop/CampaignStats.cpp b/Laptop/CampaignStats.cpp index a278c66f..5d70d11e 100644 --- a/Laptop/CampaignStats.cpp +++ b/Laptop/CampaignStats.cpp @@ -156,7 +156,7 @@ Incident_Stats::AddStat( SOLDIERTYPE* pSoldier, UINT8 aType ) case ENEMY_TEAM: { - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) group = CAMPAIGNHISTORY_SD_ENEMY_TANK; else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR ) group = CAMPAIGNHISTORY_SD_ENEMY_ADMIN; diff --git a/Strategic/AI Viewer.cpp b/Strategic/AI Viewer.cpp index 3287fe0d..03ca0d07 100644 --- a/Strategic/AI Viewer.cpp +++ b/Strategic/AI Viewer.cpp @@ -1278,7 +1278,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) gfRenderViewer = TRUE; if( gsSelSectorY > 1 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-16, 0, 11, 5, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-16, 0, 11, 5, 0, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 10; @@ -1290,7 +1290,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) } if( gsSelSectorY < 16 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+16, 0, 8, 8, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+16, 0, 8, 8, 0, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 12; @@ -1302,7 +1302,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) } if( gsSelSectorX > 1 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-1, 0, 11, 5, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector-1, 0, 11, 5, 0, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 11; @@ -1314,7 +1314,7 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason ) } if( gsSelSectorX < 16 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, 0, 14, 0, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, 0, 14, 0, 0, 0, 0 ); pGroup->ubNextX = (UINT8)gsSelSectorX; pGroup->ubNextY = (UINT8)gsSelSectorY; pGroup->uiTraverseTime = 13; diff --git a/Strategic/ASD.cpp b/Strategic/ASD.cpp index 8a8b3878..92c3256e 100644 --- a/Strategic/ASD.cpp +++ b/Strategic/ASD.cpp @@ -99,12 +99,14 @@ void InitASD( ) gASDResource[ASD_HELI] = 0; gASDResource[ASD_JEEP] = 2; gASDResource[ASD_TANK] = 2; + gASDResource[ASD_ROBOT] = 8; gASDResource_Ordered[ASD_MONEY] = 0; gASDResource_Ordered[ASD_FUEL] = 0; gASDResource_Ordered[ASD_HELI] = 0; gASDResource_Ordered[ASD_JEEP] = 0; gASDResource_Ordered[ASD_TANK] = 0; + gASDResource_Ordered[ASD_ROBOT] = 0; gASD_Flags = 0; @@ -196,6 +198,8 @@ void UpdateASD( ) if ( !(gASD_Flags & ASDFACT_TANK_UNLOCKED) && HighestPlayerProgressPercentage( ) >= gGameExternalOptions.usTankMinimumProgress ) SetASDFlag( ASDFACT_TANK_UNLOCKED ); + if ( !(gASD_Flags & ASDFACT_ROBOT_UNLOCKED) && HighestPlayerProgressPercentage( ) >= gGameExternalOptions.usRobotMinimumProgress ) + SetASDFlag( ASDFACT_ROBOT_UNLOCKED ); // determine whether we need to buy new toys ASDDecideOnPurchases(); @@ -210,6 +214,7 @@ void ASDDecideOnPurchases() INT32 needed_heli = 0; INT32 needed_tank = 0; INT32 needed_jeep = 0; + INT32 needed_robot = 0; UINT16 highestplayerprogress = HighestPlayerProgressPercentage( ); @@ -275,24 +280,39 @@ void ASDDecideOnPurchases() needed_fuel += needed_tank * ASDResourceCostFuel( ASD_TANK ); } + // do we need new robots? + if ( gASD_Flags & ASDFACT_ROBOT_UNLOCKED ) + { + // 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_robot = min( 10, 2 + highestplayerprogress / 10 ); + + // how many are needed? + needed_robot = max( 0, needed_robot - gASDResource[ASD_ROBOT] ); + + needed_fuel += needed_robot * ASDResourceCostFuel( ASD_ROBOT ); + } + // how much new fuel do we need? needed_fuel = max( 0, needed_fuel - gASDResource[ASD_FUEL] ); - // reduce order by what we'e alreay ordered + // reduce order by what we'e already ordered needed_fuel = max( 0, needed_fuel - gASDResource_Ordered[ASD_FUEL] ); needed_jeep = max( 0, needed_jeep - gASDResource_Ordered[ASD_JEEP] ); needed_tank = max( 0, needed_tank - gASDResource_Ordered[ASD_TANK] ); needed_heli = max( 0, needed_heli - gASDResource_Ordered[ASD_HELI] ); + needed_robot = max( 0, needed_robot - gASDResource_Ordered[ASD_ROBOT] ); // check whether we can afford all new purchases. If we can't, lower your expectations while ( needed_fuel * ASDResourceCostMoney( ASD_FUEL ) + needed_jeep * ASDResourceCostMoney( ASD_JEEP ) + needed_tank * ASDResourceCostMoney( ASD_TANK ) + - needed_heli * ASDResourceCostMoney( ASD_HELI ) > gASDResource[ASD_MONEY] ) + needed_heli * ASDResourceCostMoney( ASD_HELI ) + + needed_robot * ASDResourceCostMoney( ASD_ROBOT ) > gASDResource[ASD_MONEY] ) { if ( needed_tank ) --needed_tank; else if ( needed_heli ) --needed_heli; else if ( needed_jeep ) --needed_jeep; + else if ( needed_robot ) --needed_robot; else needed_fuel = max( 0, needed_fuel - 10 ); } @@ -334,6 +354,15 @@ void ASDDecideOnPurchases() AddStrategicEvent( EVENT_ASD_PURCHASE_HELI, GetWorldTotalMin( ) + ASDResourceDeliveryTime( ASD_HELI ), needed_heli ); } + + if ( needed_robot ) + { + AddStrategicAIResources( ASD_MONEY, -needed_robot * ASDResourceCostMoney( ASD_ROBOT ) ); + + gASDResource_Ordered[ASD_ROBOT] += needed_robot; + + AddStrategicEvent( EVENT_ASD_PURCHASE_ROBOT, GetWorldTotalMin( ) + ASDResourceDeliveryTime( ASD_ROBOT ), needed_robot ); + } } void ASDDecideHeliOperations() @@ -1470,6 +1499,10 @@ UINT32 ASDResourceCostFuel( UINT8 aType ) case ASD_JEEP: return gGameExternalOptions.gASDResource_Fuel_Jeep; break; + + case ASD_ROBOT: + return gGameExternalOptions.gASDResource_Fuel_Robot; + break; } return 0; @@ -1509,3 +1542,20 @@ BOOLEAN ASDSoldierUpgradeToJeep( ) return FALSE; } + +BOOLEAN ASDSoldierUpgradeToRobot( ) +{ + if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsRobots ) + { + if ( gASD_Flags & ASDFACT_ROBOT_UNLOCKED ) + { + if ( gASDResource[ASD_ROBOT] ) + { + gASDResource[ASD_ROBOT] = max( 0, gASDResource[ASD_ROBOT] - 1 ); + return TRUE; + } + } + } + + return FALSE; +} diff --git a/Strategic/ASD.h b/Strategic/ASD.h index 8f321679..934c0e32 100644 --- a/Strategic/ASD.h +++ b/Strategic/ASD.h @@ -49,6 +49,7 @@ void ASDDecideHeliOperations(); #define ASDFACT_HELI_UNLOCKED 0x00000001 // AI is allowed to purchase helicopters #define ASDFACT_JEEP_UNLOCKED 0x00000002 // AI is allowed to purchase jeeps #define ASDFACT_TANK_UNLOCKED 0x00000004 // AI is allowed to purchase tanks +#define ASDFACT_ROBOT_UNLOCKED 0x00000008 // AI is allowed to purchase robots void SetASDFlag( UINT32 aFlag ); @@ -121,5 +122,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( ); +BOOLEAN ASDSoldierUpgradeToRobot( ); #endif //__ASD_H diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index a3ddb959..c4b7f7ef 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -74,6 +74,8 @@ #include "MilitiaIndividual.h" // added by Flugente #endif +#pragma optimize("",off) + #include "Reinforcement.h" //#define INVULNERABILITY @@ -141,7 +143,7 @@ typedef struct AUTORESOLVE_STRUCT INT32 iButtonImage[ NUM_AR_BUTTONS ]; INT32 iFaces; //for generic civs and enemies // WDS - make number of mercenaries, etc. be configurable - INT32 iMercFaces[CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS]; //for each merc face + //INT32 iMercFaces[CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS]; //for each merc face INT32 iIndent; INT32 iInterfaceBuffer; INT32 iNumMercFaces; @@ -168,7 +170,7 @@ typedef struct AUTORESOLVE_STRUCT UINT8 ubEnemyLeadership; UINT8 ubPlayerLeadership; UINT8 ubMercs, ubCivs, ubEnemies; - UINT8 ubAdmins, ubTroops, ubElites, ubTanks, ubJeeps; + UINT8 ubAdmins, ubTroops, ubElites, ubTanks, ubJeeps, ubRobots; UINT8 ubYMCreatures, ubYFCreatures, ubAMCreatures, ubAFCreatures; UINT8 ubBloodcats; UINT8 ubZombies; @@ -236,10 +238,11 @@ typedef struct AUTORESOLVE_STRUCT #define CELL_BLOODCAT 0x01000000 #define CELL_ZOMBIE 0x02000000 #define CELL_BANDIT 0x04000000 +#define CELL_ENEMYROBOT 0x08000000 //Combined flags #define CELL_PLAYER ( CELL_MERC | CELL_MILITIA ) -#define CELL_ENEMY ( CELL_ELITE | CELL_TROOP | CELL_ADMIN | CELL_TANK | CELL_JEEP | CELL_BANDIT ) +#define CELL_ENEMY ( CELL_ELITE | CELL_TROOP | CELL_ADMIN | CELL_TANK | CELL_JEEP | CELL_BANDIT | CELL_ENEMYROBOT ) #define CELL_FEMALECREATURE ( CELL_AF_CREATURE | CELL_YF_CREATURE ) #define CELL_MALECREATURE ( CELL_AM_CREATURE | CELL_YM_CREATURE ) #define CELL_BUG ( CELL_FEMALECREATURE | CELL_MALECREATURE ) @@ -415,6 +418,7 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY ) UINT8 ubNumEnemies[ NUM_ENEMY_RANKS ]; UINT8 ubNumTanks = 0; UINT8 ubNumJeeps = 0; + UINT8 ubNumRobots = 0; UINT8 ubRankIndex; //Clear any possible battle locator @@ -427,7 +431,7 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY ) // we must process the enemies killed right here & give out loyalty bonuses as if the battle had been fought & won if( !gpAR ) { - GetNumberOfEnemiesInSector( ubSectorX, ubSectorY, &ubNumEnemies[0], &ubNumEnemies[1], &ubNumEnemies[2], &ubNumTanks, &ubNumJeeps ); + GetNumberOfEnemiesInSector( ubSectorX, ubSectorY, &ubNumEnemies[0], &ubNumEnemies[1], &ubNumEnemies[2], &ubNumRobots, &ubNumTanks, &ubNumJeeps ); for ( ubRankIndex = 0; ubRankIndex < NUM_ENEMY_RANKS; ++ubRankIndex ) { @@ -459,6 +463,7 @@ void EliminateAllEnemies( UINT8 ubSectorX, UINT8 ubSectorY ) pSector->ubNumAdmins = 0; pSector->ubNumTanks = 0; pSector->ubNumJeeps = 0; + pSector->ubNumRobots = 0; pSector->ubNumCreatures = 0; pSector->bLastKnownEnemies = 0; //Remove the mobile forces here, but only if battle is over. @@ -747,9 +752,9 @@ void AssociateEnemiesWithStrategicGroups() { SECTORINFO *pSector; GROUP *pGroup; - 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; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots; //how many soldiers of the type do we still have to assign to a group? + UINT8 ubISNumAdmins, ubISNumTroops, ubISNumElites, ubISNumTanks, ubISNumJeeps, ubISNumRobots; + UINT8 ubNumElitesInGroup, ubNumTroopsInGroup, ubNumAdminsInGroup, ubNumTanksInGroup, ubNumJeepsInGroup, ubNumRobotsInGroup; INT32 i; UINT8 pSectors[4]; UINT8 ubDirAmount; @@ -769,6 +774,7 @@ void AssociateEnemiesWithStrategicGroups() ubNumElites = pSector->ubNumElites; ubNumTanks = pSector->ubNumTanks; ubNumJeeps = pSector->ubNumJeeps; + ubNumRobots = pSector->ubNumRobots; //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 @@ -786,6 +792,12 @@ void AssociateEnemiesWithStrategicGroups() gpEnemies[i].uiFlags |= CELL_ASSIGNED; ubNumJeeps--; } + else if ( gpEnemies[i].uiFlags & CELL_ENEMYROBOT && ubNumRobots ) + { + gpEnemies[i].pSoldier->ubGroupID = 0; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + ubNumRobots--; + } else if ( gpEnemies[i].uiFlags & CELL_ELITE && ubNumElites ) { gpEnemies[ i ].pSoldier->ubGroupID = 0; @@ -804,15 +816,16 @@ void AssociateEnemiesWithStrategicGroups() gpEnemies[ i ].uiFlags |= CELL_ASSIGNED; ubNumAdmins--; } - } + } ubNumAdmins = gpAR->ubAdmins - pSector->ubNumAdmins; ubNumTroops = gpAR->ubTroops - pSector->ubNumTroops; ubNumElites = gpAR->ubElites - pSector->ubNumElites; ubNumTanks = gpAR->ubTanks - pSector->ubNumTanks; ubNumJeeps = gpAR->ubJeeps - pSector->ubNumJeeps; + ubNumRobots = gpAR->ubRobots - pSector->ubNumRobots; - if ( !ubNumElites && !ubNumTroops && !ubNumAdmins && !ubNumTanks && !ubNumJeeps ) + if ( !ubNumElites && !ubNumTroops && !ubNumAdmins && !ubNumTanks && !ubNumJeeps && !ubNumRobots ) { //All troops accounted for. return; } @@ -828,6 +841,7 @@ void AssociateEnemiesWithStrategicGroups() ubNumAdminsInGroup = pGroup->pEnemyGroup->ubNumAdmins; ubNumTanksInGroup = pGroup->pEnemyGroup->ubNumTanks; ubNumJeepsInGroup = pGroup->pEnemyGroup->ubNumJeeps; + ubNumRobotsInGroup = pGroup->pEnemyGroup->ubNumRobots; 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) ? @@ -846,6 +860,13 @@ void AssociateEnemiesWithStrategicGroups() ubNumJeeps--; ubNumJeepsInGroup--; } + else if ( ubNumRobots && ubNumRobotsInGroup && gpEnemies[i].uiFlags & CELL_ENEMYROBOT ) + { + gpEnemies[i].pSoldier->ubGroupID = pGroup->ubGroupID; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + ubNumRobots--; + ubNumRobotsInGroup--; + } else if (ubNumElites && ubNumElitesInGroup && gpEnemies[i].uiFlags & CELL_ELITE) { gpEnemies[ i ].pSoldier->ubGroupID = pGroup->ubGroupID; @@ -886,6 +907,7 @@ void AssociateEnemiesWithStrategicGroups() ubNumAdminsInGroup = pGroup->pEnemyGroup->ubNumAdmins; ubNumTanksInGroup = pGroup->pEnemyGroup->ubNumTanks; ubNumJeepsInGroup = pGroup->pEnemyGroup->ubNumJeeps; + ubNumRobotsInGroup = pGroup->pEnemyGroup->ubNumRobots; for( i = 0; i < gpAR->ubEnemies; i++ ) { if( !(gpEnemies[ i ].uiFlags & CELL_ASSIGNED) ) @@ -904,6 +926,13 @@ void AssociateEnemiesWithStrategicGroups() ubNumJeeps--; ubNumJeepsInGroup--; } + else if ( ubNumRobots && ubNumRobotsInGroup && gpEnemies[i].uiFlags & CELL_ENEMYROBOT ) + { + gpEnemies[i].pSoldier->ubGroupID = pGroup->ubGroupID; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + ubNumRobots--; + ubNumRobotsInGroup--; + } else if (ubNumElites && ubNumElitesInGroup && gpEnemies[i].uiFlags & CELL_ELITE) { gpEnemies[ i ].pSoldier->ubGroupID = pGroup->ubGroupID; @@ -943,10 +972,11 @@ void AssociateEnemiesWithStrategicGroups() ubISNumElites = pSector->ubNumElites; ubISNumTanks = pSector->ubNumTanks; ubISNumJeeps = pSector->ubNumJeeps; + ubISNumRobots = pSector->ubNumRobots; for( i = 0; i < gpAR->ubEnemies; ++i ) { - 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 ( ubISNumAdmins + ubISNumTroops + ubISNumElites + ubISNumTanks + ubISNumJeeps + ubISNumRobots <= 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) ) { @@ -968,6 +998,15 @@ void AssociateEnemiesWithStrategicGroups() ubISNumJeeps--; ubNumJeeps--; } + else if ( gpEnemies[i].uiFlags & CELL_ENEMYROBOT && ubISNumRobots && ubNumRobots ) + { + gpEnemies[i].pSoldier->ubGroupID = 0; + gpEnemies[i].uiFlags |= CELL_ASSIGNED; + gpEnemies[i].pSoldier->sSectorX = SECTORX( pSectors[ubCurrSI] ); + gpEnemies[i].pSoldier->sSectorY = SECTORY( pSectors[ubCurrSI] ); + ubISNumRobots--; + ubNumRobots--; + } else if ( gpEnemies[i].uiFlags & CELL_ELITE && ubISNumElites && ubNumElites ) { gpEnemies[ i ].pSoldier->ubGroupID = 0; @@ -1000,7 +1039,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 & ubISNumJeeps), "Mapping between actual enemies and autoresolve cells is wrong." ); + AssertMsg( !(ubISNumAdmins & ubISNumTroops & ubISNumElites & ubISNumTanks & ubISNumJeeps & ubISNumRobots), "Mapping between actual enemies and autoresolve cells is wrong." ); } @@ -1142,8 +1181,10 @@ void CalculateSoldierCells( BOOLEAN fReset ) gpEnemies[index].uiFlags = CELL_ADMIN; else if ( index < gpAR->ubElites + gpAR->ubTroops + gpAR->ubAdmins + gpAR->ubTanks ) gpEnemies[index].uiFlags = CELL_TANK; - else + else if ( index < gpAR->ubElites + gpAR->ubTroops + gpAR->ubAdmins + gpAR->ubTanks + gpAR->ubJeeps ) gpEnemies[index].uiFlags = CELL_JEEP; + else + gpEnemies[index].uiFlags = CELL_ENEMYROBOT; } } } @@ -2270,6 +2311,19 @@ void CreateAutoResolveInterface() } else { + for (i = 0; i < gpAR->ubRobots; ++i, ++index) + { + gpEnemies[index].pSoldier = TacticalCreateEnemyRobot(); + gpEnemies[index].pSoldier->sSectorX = gpAR->ubSectorX; + gpEnemies[index].pSoldier->sSectorY = gpAR->ubSectorY; + swprintf( gpEnemies[index].pSoldier->name, gpStrategicString[STR_AR_ROBOT_NAME] ); + + // reuse madlab's robot's face + VOBJECT_DESC VObjectDesc; + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + sprintf( VObjectDesc.ImageFile, "Faces\\65Face\\%02d.sti", gMercProfiles[ ROBOT ].ubFaceIndex ); + AddVideoObject(&VObjectDesc, &gpEnemies[index].uiVObjectID); + } for ( i = 0; i < gpAR->ubElites; ++i, ++index ) { gpEnemies[index].pSoldier = TacticalCreateEliteEnemy(); @@ -3052,9 +3106,9 @@ void CalculateAutoResolveInfo() else { GetNumberOfEnemiesInFiveSectors( gpAR->ubSectorX, gpAR->ubSectorY, - &gpAR->ubAdmins, &gpAR->ubTroops, &gpAR->ubElites, &gpAR->ubTanks, &gpAR->ubJeeps ); + &gpAR->ubAdmins, &gpAR->ubTroops, &gpAR->ubElites, &gpAR->ubRobots, &gpAR->ubTanks, &gpAR->ubJeeps ); - gpAR->ubEnemies = (UINT8)min( gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubElites + gpAR->ubTanks + gpAR->ubJeeps, MAX_AR_TEAM_SIZE ); + gpAR->ubEnemies = (UINT8)min( gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubElites + gpAR->ubTanks + gpAR->ubJeeps + gpAR->ubRobots, MAX_AR_TEAM_SIZE ); } gfTransferTacticalOppositionToAutoResolve = FALSE; @@ -3114,22 +3168,23 @@ 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->ubJeeps > gpAR->ubEnemies ) + while ( gpAR->ubElites + gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubTanks + gpAR->ubJeeps + gpAR->ubRobots > gpAR->ubEnemies ) { - switch( PreRandom( 5 ) ) + switch( PreRandom( 6 ) ) { - case 0: if( gpAR->ubElites ) { gpAR->ubElites--; 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; } + case 5: if ( gpAR->ubRobots ) { gpAR->ubRobots--; break; } } } - while ( gpAR->ubElites + gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubTanks + gpAR->ubJeeps< gpAR->ubEnemies ) + while ( gpAR->ubElites + gpAR->ubAdmins + gpAR->ubTroops + gpAR->ubTanks + gpAR->ubJeeps + gpAR->ubRobots < 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; } @@ -4433,7 +4488,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 ( ARMED_VEHICLE( pTarget->pSoldier ) && FireAntiTankWeapon( pAttacker ) ) + else if ( (ARMED_VEHICLE( pTarget->pSoldier ) || ENEMYROBOT( pTarget->pSoldier )) && FireAntiTankWeapon( pAttacker ) ) { fAntiTank = TRUE; @@ -4801,6 +4856,9 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget ) // SANDRO - experimental - more specific statistics of mercs switch(pTarget->pSoldier->ubSoldierClass) { + case SOLDIER_CLASS_ROBOT : + gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsOthers++; + break; case SOLDIER_CLASS_ELITE : gMercProfiles[ pAttacker->pSoldier->ubProfile ].records.usKillsElites++; break; @@ -4970,10 +5028,10 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index ) } //bullet hit -- play an impact sound and a merc hit sound - if ( ARMED_VEHICLE( pTarget->pSoldier ) ) + if ( ARMED_VEHICLE( pTarget->pSoldier ) || ENEMYROBOT( 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 ); + PlayAutoResolveSample( (UINT8)(BULLET_IMPACT_1+PreRandom(3)), RATE_11025, 50, 1, MIDDLEPAN ); if( pTarget->pSoldier->stats.bLife >= CONSCIOUSNESS ) { @@ -5043,6 +5101,9 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index ) // SANDRO - new mercs' records switch(pTarget->pSoldier->ubSoldierClass) { + case SOLDIER_CLASS_ROBOT : + gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsOthers++; + break; case SOLDIER_CLASS_ELITE : gMercProfiles[ pKiller->pSoldier->ubProfile ].records.usKillsElites++; break; @@ -5154,10 +5215,10 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index ) { //Normal death if( gpAR->fSound ) { - if ( ARMED_VEHICLE( pTarget->pSoldier ) ) + if ( ARMED_VEHICLE( pTarget->pSoldier ) || ENEMYROBOT( pTarget->pSoldier ) ) PlayAutoResolveSample( (UINT8)(S_RAID_TB_BOMB), RATE_11025, 50, 1, MIDDLEPAN ); else - pTarget->pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 ); + pTarget->pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 ); } } #ifdef INVULNERABILITY diff --git a/Strategic/Campaign Init.cpp b/Strategic/Campaign Init.cpp index 645b2994..0fe4681e 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_C7, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_D9, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_B9, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_A14, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N6, 0, ubNumTroops, 0, 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N10, 0, ubNumTroops, 0, 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 8f67fad4..bebb9ef7 100644 --- a/Strategic/Campaign Types.h +++ b/Strategic/Campaign Types.h @@ -490,8 +490,9 @@ typedef struct SECTORINFO UINT8 ubNumTroops; //the actual number of troops here. UINT8 ubNumElites; //the actual number of elites here. UINT8 ubNumAdmins; //the actual number of admins here. + UINT8 ubNumRobots; //the actual number of robots here. UINT8 ubNumCreatures; //only set when immediately before ground attack made! - UINT8 ubTroopsInBattle, ubElitesInBattle, ubAdminsInBattle, ubCreaturesInBattle; + UINT8 ubTroopsInBattle, ubElitesInBattle, ubAdminsInBattle, ubRobotsInBattle, ubCreaturesInBattle; INT8 bLastKnownEnemies; // -1 means never been there, no idea, otherwise it's what we'd observed most recently // while this is being maintained (partially, surely buggy), nothing uses it anymore. ARM @@ -591,7 +592,7 @@ typedef struct UNDERGROUND_SECTORINFO { UINT32 uiFlags; UINT8 ubSectorX, ubSectorY, ubSectorZ; - UINT8 ubNumElites, ubNumTroops, ubNumAdmins, ubNumCreatures; + UINT8 ubNumRobots, ubNumElites, ubNumTroops, ubNumAdmins, ubNumCreatures; UINT8 fVisited; INT8 ubTravelRating; //Represents how travelled a sector is. Typically, the higher the travel rating, //the more people go near it. A travel rating of 0 means there are never people @@ -602,7 +603,7 @@ typedef struct UNDERGROUND_SECTORINFO UINT8 ubNumBloodcats; // Bloodcat population UINT8 ubCreatureHabitat; //determines how creatures live in this sector (see creature spreading.c) - UINT8 ubElitesInBattle, ubTroopsInBattle, ubAdminsInBattle, ubCreaturesInBattle; + UINT8 ubRobotsInBattle, ubElitesInBattle, ubTroopsInBattle, ubAdminsInBattle, ubCreaturesInBattle; // adding these (should not change struct layout due to padding) UINT8 ubMusicMode, ubUnsed; diff --git a/Strategic/Game Event Hook.cpp b/Strategic/Game Event Hook.cpp index e88d7522..4a92be05 100644 --- a/Strategic/Game Event Hook.cpp +++ b/Strategic/Game Event Hook.cpp @@ -592,6 +592,13 @@ BOOLEAN ExecuteStrategicEvent( STRATEGICEVENT *pEvent ) AddStrategicAIResources( ASD_HELI, pEvent->uiParam ); break; + case EVENT_ASD_PURCHASE_ROBOT: + ASDReduceOrderedStrategicResources( ASD_ROBOT, pEvent->uiParam ); + + if ( IsSectorEnemyControlled( gModSettings.usASDSupplyArrivalSectorX, gModSettings.usASDSupplyArrivalSectorY, 0 ) ) + AddStrategicAIResources( ASD_ROBOT, pEvent->uiParam ); + break; + case EVENT_ENEMY_HELI_UPDATE: UpdateEnemyHeli( pEvent->uiParam ); break; diff --git a/Strategic/Game Event Hook.h b/Strategic/Game Event Hook.h index b07a86dc..e290b329 100644 --- a/Strategic/Game Event Hook.h +++ b/Strategic/Game Event Hook.h @@ -125,6 +125,7 @@ enum EVENT_ASD_PURCHASE_JEEP, EVENT_ASD_PURCHASE_TANK, EVENT_ASD_PURCHASE_HELI, + EVENT_ASD_PURCHASE_ROBOT, EVENT_ENEMY_HELI_UPDATE, // Flugente: move enemy helicopter to another sector EVENT_ENEMY_HELI_REPAIR, diff --git a/Strategic/Ja25 Strategic Ai.cpp b/Strategic/Ja25 Strategic Ai.cpp index 3319de20..581b54d6 100644 --- a/Strategic/Ja25 Strategic Ai.cpp +++ b/Strategic/Ja25 Strategic Ai.cpp @@ -123,15 +123,15 @@ JA25_SECTOR_AI_MANAGER gJa25StrategicAi; BOOLEAN AddEnemiesToInitialSectorH7(); -UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); -void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps ); +UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps, UINT8 *pubNumRobots ); +void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, UINT8 ubNumRobots ); 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, UINT8 ubNumJeeps ); +void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, UINT8 ubNumRobots ); void ResetJa25SectorProbabilities(); BOOLEAN InitJa25StrategicSectorAI( BOOLEAN fReset ); @@ -151,8 +151,8 @@ void FixEnemyCounterInSectorBug(); void AddEnemiesToFirstTunnelSector(); void AddEnemiesToSecondTunnelSector(); -UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps ); -UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps ); +UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps, UINT8 *pRobots ); +UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps, UINT8 *pRobots ); void RemoveAllEnemySoldierInitListLinks(); INT16 GetGridNoEnemyWillSeekWhenAttacking( INT8 bSaiSector ); void SetH11NumEnemiesInSector(); @@ -174,7 +174,7 @@ BOOLEAN Ja25BetaDateToInvalidateExe(); - UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites, UINT8 *pNumTanks, UINT8 *pubNumJeeps ) + UINT32 GetNumberOfJA25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 *pNumAdmins, UINT8 *pNumTroops, UINT8 *pNumElites, UINT8 *pNumTanks, UINT8 *pubNumJeeps, UINT8 *pubNumRobots ) { SECTORINFO *pSector; @@ -188,6 +188,7 @@ BOOLEAN Ja25BetaDateToInvalidateExe(); *pNumElites = pSector->ubNumElites; *pNumTanks = pSector->ubNumTanks; *pubNumJeeps = pSector->ubNumJeeps; + *pubNumRobots = pSector->ubNumRobots; } else { @@ -201,6 +202,7 @@ BOOLEAN Ja25BetaDateToInvalidateExe(); *pNumElites = pSector->ubNumElites; *pNumTanks = pSector->ubNumTanks; *pubNumJeeps = pSector->ubNumJeeps; + *pubNumRobots = pSector->ubNumRobots; } } @@ -283,17 +285,19 @@ BOOLEAN AddEnemiesToInitialSectorH7() UINT8 ubNumElites; UINT8 ubNumTanks; UINT8 ubNumJeeps; + UINT8 ubNumRobots; UINT8 ubNumRemovedAdmins=0; UINT8 ubNumRemovedTroops=0; UINT8 ubNumRemovedElites=0; UINT8 ubNumRemovedTanks=0; UINT8 ubNumRemovedJeeps=0; + UINT8 ubNumRemovedRobots=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, &ubNumJeeps ); + GetNumberOfJA25EnemiesInSector( 8, MAP_ROW_H, 0, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps, &ubNumRobots ); //determine the #of enemies to travel to the initial heli sector if( ubNumAdmins > 1 ) @@ -311,14 +315,17 @@ BOOLEAN AddEnemiesToInitialSectorH7() if( ubNumJeeps > 1 ) ubNumRemovedJeeps = ubNumJeeps / 3 + + Random( 3 ); + if( ubNumRobots > 1 ) + ubNumRemovedRobots = ubNumRobots / 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), (UINT8)(ubNumJeeps-ubNumRemovedJeeps) ); + (UINT8)(ubNumTanks-ubNumRemovedTanks), (UINT8)(ubNumJeeps-ubNumRemovedJeeps), (UINT8)(ubNumRobots-ubNumRemovedRobots) ); uiWorldMin = GetWorldTotalMin(); - pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, ubNumRemovedAdmins, ubNumRemovedTroops, ubNumRemovedElites, ubNumRemovedTanks, ubNumRemovedJeeps ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSector+1, ubNumRemovedAdmins, ubNumRemovedTroops, ubNumRemovedElites, ubNumRemovedTanks, ubNumRemovedJeeps, ubNumRemovedRobots ); if( pGroup == NULL ) { @@ -409,24 +416,24 @@ void InitJa25UnderGroundSectors() */ } -void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps ) +void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, UINT8 ubNumRobots ) { //if its a ground level if( bSectorZ == 0 ) { - SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //its an underground level else { - SetNumberJa25EnemiesInUnderGroundSector( sSectorX, sSectorY, bSectorZ, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInUnderGroundSector( sSectorX, sSectorY, bSectorZ, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } } -void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps ) +void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, UINT8 ubNumRobots ) { SECTORINFO* pSector = &SectorInfo[iSectorID]; pSector->ubNumAdmins = ubNumAdmins; @@ -434,6 +441,7 @@ void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UI pSector->ubNumElites = ubNumElites; pSector->ubNumTanks = ubNumTanks; pSector->ubNumJeeps = ubNumJeeps; + pSector->ubNumRobots = ubNumRobots; } void SetNumberOfJa25BloodCatsInSector( INT32 iSectorID, INT8 bNumBloodCats, INT8 bBloodCatPlacements ) @@ -446,7 +454,7 @@ void SetNumberOfJa25BloodCatsInSector( INT32 iSectorID, INT8 bNumBloodCats, INT8 pSector->bBloodCatPlacements = bBloodCatPlacements; } -void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps ) +void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, UINT8 ubNumRobots ) { UNDERGROUND_SECTORINFO *pSector=NULL; @@ -459,6 +467,7 @@ void SetNumberJa25EnemiesInUnderGroundSector( INT16 sSectorX, INT16 sSectorY, IN pSector->ubNumElites = ubNumElites; pSector->ubNumTanks = ubNumTanks; pSector->ubNumJeeps = ubNumJeeps; + pSector->ubNumRobots = ubNumRobots; } void InitNumberOfEnemiesInAboveGroundSectors( ) @@ -468,6 +477,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps=0; + UINT8 ubNumRobots=0; //H7 { @@ -494,7 +504,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_H7, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_H7, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } @@ -525,7 +535,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_H8, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_H8, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //Guard Post @@ -555,7 +565,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_H9, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_H9, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } // SEC_H10: @@ -584,7 +594,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_H10, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_H10, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //SEC_H11 @@ -617,7 +627,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_I9, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_I9, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //First part of town @@ -647,7 +657,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_I10, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_I10, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //Second part of town @@ -677,7 +687,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_I11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_I11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //SEC_I12: @@ -706,7 +716,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_I12, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_I12, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //Abandoned mine @@ -736,7 +746,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_I13, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_I13, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } // SEC_J11: @@ -765,7 +775,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_J11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_J11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } // SEC_J12: @@ -794,7 +804,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_J12, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_J12, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //Power Generator, Ground Level @@ -824,7 +834,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_J13, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_J13, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } //Complex, Ground Level @@ -854,7 +864,7 @@ void InitNumberOfEnemiesInAboveGroundSectors( ) break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_K15, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_K15, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } } @@ -865,6 +875,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps=0; + UINT8 ubNumRobots=0; //Mine Sector Level 1 switch( gGameOptions.ubDifficultyLevel ) @@ -885,7 +896,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 13, 9, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 13, 9, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); //Power Generator Level 1 @@ -907,7 +918,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 13, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 13, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); //Tunnel First Part, Level 1 @@ -929,7 +940,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); //Tunnel Second Part, Level 1 @@ -951,7 +962,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 0 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); @@ -974,7 +985,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 6 + Random( 4 ); break; } - SetNumberJa25EnemiesInSector( 15, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 15, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); //Complex, Level 2, K15 @@ -996,7 +1007,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 10 + Random( 2 ); break; } - SetNumberJa25EnemiesInSector( 15, 11, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 15, 11, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); //Complex, Level 2, L15 @@ -1018,7 +1029,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 14 + Random( 2 ); break; } - SetNumberJa25EnemiesInSector( 15, 12, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 15, 12, 2, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); //Complex, Level 3, L15 @@ -1040,7 +1051,7 @@ void InitNumberOfEnemiesInUnderGroundSectors( ) ubNumElites = 15 + Random( 0 ); break; } - SetNumberJa25EnemiesInSector( 15, 12, 3, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 15, 12, 3, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } void InitJa25SaveStruct() @@ -1289,7 +1300,7 @@ void HandleAddingEnemiesToTunnelMaps() else if( AreAnyPlayerMercsStillInSector( 14, 10, 1 ) && !AreAnyPlayerMercsStillInSector( 14, 11, 1 ) ) { - ubNumEnemies = NumEnemiesToAttackFirstTunnelSector( NULL, NULL, NULL, NULL, NULL ); + ubNumEnemies = NumEnemiesToAttackFirstTunnelSector( NULL, NULL, NULL, NULL, NULL, NULL ); //Add enemies to the first sector HandleAddEnemiesToSectorPlayerIsntIn( JA25_J14_1, ubNumEnemies ); @@ -1303,7 +1314,7 @@ void HandleAddingEnemiesToTunnelMaps() //else if the player is in the second sector else if( AreAnyPlayerMercsStillInSector( 14, 11, 1 ) ) { - ubNumEnemies = NumEnemiesToAttackSecondTunnelSector( NULL, NULL, NULL, NULL, NULL ); + ubNumEnemies = NumEnemiesToAttackSecondTunnelSector( NULL, NULL, NULL, NULL, NULL, NULL ); //Add enemies to the first sector HandleAddEnemiesToSectorPlayerIsntIn( JA25_K14_1, ubNumEnemies ); @@ -1334,10 +1345,11 @@ void AddEnemiesToFirstTunnelSector() UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps=0; + UINT8 ubNumRobots=0; - NumEnemiesToAttackFirstTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); + NumEnemiesToAttackFirstTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps, &ubNumRobots ); - SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( 14, 10, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } void AddEnemiesToSecondTunnelSector() @@ -1347,18 +1359,20 @@ void AddEnemiesToSecondTunnelSector() UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps=0; + UINT8 ubNumRobots=0; - NumEnemiesToAttackSecondTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); - SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + NumEnemiesToAttackSecondTunnelSector( &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps, &ubNumRobots ); + SetNumberJa25EnemiesInSector( 14, 11, 1, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } -UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps ) +UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps, UINT8 *pRobots ) { UINT8 ubNumAdmins=0; UINT8 ubNumTroops=0; UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps=0; + UINT8 ubNumRobots=0; //if the player blew up the fan, add a ton of enemies to the sector //1st Tunnel Sector @@ -1396,16 +1410,20 @@ UINT8 NumEnemiesToAttackFirstTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 if( pJeeps ) *pJeeps = ubNumJeeps; - return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps ); + if( pRobots ) + *pRobots = ubNumRobots; + + return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps + ubNumRobots ); } -UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps ) +UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT8 *pElites, UINT8 *pTanks, UINT8 *pJeeps, UINT8 *pRobots ) { UINT8 ubNumAdmins=0; UINT8 ubNumTroops=0; UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps=0; + UINT8 ubNumRobots=0; //if the player blew up the fan, add a ton of enemies to the sector //1st Tunnel Sector @@ -1439,8 +1457,10 @@ UINT8 NumEnemiesToAttackSecondTunnelSector( UINT8 *pAdmins, UINT8 *pTroops, UINT *pTanks = ubNumTanks; if( pJeeps ) *pJeeps = ubNumJeeps; + if( pRobots ) + *pRobots = ubNumRobots; - return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps ); + return( ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps + ubNumRobots ); } @@ -2202,7 +2222,7 @@ BOOLEAN HandleAddEnemiesToSectorPlayerIsntIn( INT16 sSaiSector, UINT8 ubNumEnemi SetEnemyEncounterCode( ENEMY_INVASION_CODE ); } - SetNumberJa25EnemiesInSector( sSectorX, sSectorY, bSectorZ, 0, ubNumEnemies, 0, 0, 0 ); + SetNumberJa25EnemiesInSector( sSectorX, sSectorY, bSectorZ, 0, ubNumEnemies, 0, 0, 0, 0 ); SetThisSectorAsEnemyControlled( sSectorX, sSectorY, bSectorZ, FALSE ); @@ -2248,7 +2268,7 @@ if ( gGameUBOptions.pJA2UB == TRUE ) if( gJa25AiSectorStruct[ sSaiSector ].bSectorZ == 0 ) { - pGroup = CreateNewEnemyGroupDepartingFromSector( sSector, 0, ubNumEnemies, 0, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( sSector, 0, ubNumEnemies, 0, 0, 0, 0 ); if( sGridNo != -1 ) { @@ -2841,6 +2861,7 @@ void SetH11NumEnemiesInSector() UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps = 0; + UINT8 ubNumRobots = 0; // SEC_H11: { @@ -2868,7 +2889,7 @@ void SetH11NumEnemiesInSector() break; } - SetNumberJa25EnemiesInSurfaceSector( SEC_H11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SEC_H11, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); } } diff --git a/Strategic/Ja25 Strategic Ai.h b/Strategic/Ja25 Strategic Ai.h index 705959cf..4de27d9a 100644 --- a/Strategic/Ja25 Strategic Ai.h +++ b/Strategic/Ja25 Strategic Ai.h @@ -188,12 +188,12 @@ BOOLEAN ShouldEnemiesBeAddedToInitialSector(); void InitJa25StrategicAi(); -void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps ); +void SetNumberJa25EnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubJeeps, UINT8 ubRobots ); void InitJa25SaveStruct(); void InitJa25StrategicAiBloodcats( ); -void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps ); +void SetNumberJa25EnemiesInSurfaceSector( INT32 iSectorID, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, UINT8 ubNumRobots ); BOOLEAN SaveJa25SaveInfoToSaveGame( HWFILE hFile ); BOOLEAN LoadJa25SaveInfoFromSavedGame( HWFILE hFile ); diff --git a/Strategic/LuaInitNPCs.cpp b/Strategic/LuaInitNPCs.cpp index 92b1bd3b..b7dc3d42 100644 --- a/Strategic/LuaInitNPCs.cpp +++ b/Strategic/LuaInitNPCs.cpp @@ -2266,6 +2266,7 @@ int i; UINT8 ubNumElites=0; UINT8 ubNumTanks=0; UINT8 ubNumJeeps=0; + UINT8 ubNumRobots=0; INT16 sSectorX; INT16 sSectorY; @@ -2279,7 +2280,7 @@ INT16 sSectorY; if (i == 5 ) ubNumElites = lua_tointeger(L,i); if (i == 6 ) ubNumTanks = lua_tointeger(L,i); } - SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSurfaceSector( SECTOR( sSectorX, sSectorY ), ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); return 0; } diff --git a/Strategic/PreBattle Interface.cpp b/Strategic/PreBattle Interface.cpp index 17dbfceb..638d0aac 100644 --- a/Strategic/PreBattle Interface.cpp +++ b/Strategic/PreBattle Interface.cpp @@ -233,7 +233,7 @@ 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 || pGroup->pEnemyGroup->ubJeepsInBattle ) + if ( pGroup->pEnemyGroup->ubAdminsInBattle || pGroup->pEnemyGroup->ubTroopsInBattle || pGroup->pEnemyGroup->ubElitesInBattle || pGroup->pEnemyGroup->ubTanksInBattle || pGroup->pEnemyGroup->ubJeepsInBattle || pGroup->pEnemyGroup->ubRobotsInBattle ) { ++ubInvalidGroups; pGroup->pEnemyGroup->ubAdminsInBattle = 0; @@ -241,6 +241,7 @@ void ValidateAndCorrectInBattleCounters( GROUP *pLocGroup ) pGroup->pEnemyGroup->ubElitesInBattle = 0; pGroup->pEnemyGroup->ubTanksInBattle = 0; pGroup->pEnemyGroup->ubJeepsInBattle = 0; + pGroup->pEnemyGroup->ubRobotsInBattle = 0; } } } @@ -258,14 +259,15 @@ 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) J(%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) R(%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->ubNumJeeps, pSector->ubJeepsInBattle ); + pSector->ubNumJeeps, pSector->ubJeepsInBattle, + pSector->ubNumRobots, pSector->ubRobotsInBattle ); DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL ); pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; @@ -273,6 +275,7 @@ void ValidateAndCorrectInBattleCounters( GROUP *pLocGroup ) pSector->ubCreaturesInBattle = 0; pSector->ubTanksInBattle = 0; pSector->ubJeepsInBattle = 0; + pSector->ubRobotsInBattle = 0; } } #endif @@ -2007,7 +2010,7 @@ void CalculateNonPersistantPBIInfo() { SetExplicitEnemyEncounterCode( FIGHTING_CREATURES_CODE ); } - else if( pSector->ubAdminsInBattle || pSector->ubTroopsInBattle || pSector->ubElitesInBattle || pSector->ubTanksInBattle || pSector->ubJeepsInBattle ) + else if( pSector->ubAdminsInBattle || pSector->ubTroopsInBattle || pSector->ubElitesInBattle || pSector->ubTanksInBattle || pSector->ubJeepsInBattle || pSector->ubRobotsInBattle ) { SetExplicitEnemyEncounterCode( ENTERING_ENEMY_SECTOR_CODE ); SetEnemyEncounterCode( ENTERING_ENEMY_SECTOR_CODE ); @@ -2022,7 +2025,7 @@ void CalculateNonPersistantPBIInfo() { SetExplicitEnemyEncounterCode( FIGHTING_CREATURES_CODE ); } - else if( pSector->ubAdminsInBattle || pSector->ubTroopsInBattle || pSector->ubElitesInBattle || pSector->ubTanksInBattle || pSector->ubJeepsInBattle ) + else if( pSector->ubAdminsInBattle || pSector->ubTroopsInBattle || pSector->ubElitesInBattle || pSector->ubTanksInBattle || pSector->ubJeepsInBattle || pSector->ubRobotsInBattle ) { SetExplicitEnemyEncounterCode( ENTERING_ENEMY_SECTOR_CODE ); SetEnemyEncounterCode( ENTERING_ENEMY_SECTOR_CODE ); diff --git a/Strategic/Queen Command.cpp b/Strategic/Queen Command.cpp index 331bcc10..609993f1 100644 --- a/Strategic/Queen Command.cpp +++ b/Strategic/Queen Command.cpp @@ -162,7 +162,7 @@ UINT8 NumHostilesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) pSector = FindUnderGroundSector( sSectorX, sSectorY, (UINT8)sSectorZ ); if( pSector ) { - ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures + pSector->ubNumJeeps + pSector->ubNumTanks); + ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures + pSector->ubNumRobots + pSector->ubNumJeeps + pSector->ubNumTanks); } } else @@ -172,7 +172,7 @@ UINT8 NumHostilesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) //Count stationary hostiles pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; - ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures + pSector->ubNumJeeps + pSector->ubNumTanks); + ubNumHostiles = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumCreatures + pSector->ubNumRobots + pSector->ubNumJeeps + pSector->ubNumTanks); //Count mobile enemies pGroup = gpGroupList; @@ -206,7 +206,7 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) pSector = FindUnderGroundSector( sSectorX, sSectorY, (UINT8)sSectorZ ); if( pSector ) { - ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumJeeps + pSector->ubNumTanks); + ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumJeeps + pSector->ubNumTanks); } } else @@ -216,7 +216,7 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) //Count stationary enemies pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; - ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumJeeps + pSector->ubNumTanks); + ubNumEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumJeeps + pSector->ubNumTanks); //Count mobile enemies pGroup = gpGroupList; @@ -259,7 +259,7 @@ UINT8 NumNonPlayerTeamMembersInSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubT if ( ubTeam == ENEMY_TEAM ) { - ubNumTroops = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumJeeps + pSector->ubNumTanks); + ubNumTroops = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumJeeps + pSector->ubNumTanks); if ( is_networked ) ubNumTroops += numenemyLAN((UINT8)sSectorX,(UINT8)sSectorY ); //hayden @@ -372,7 +372,7 @@ UINT8 NumStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) return( 0 ); } - return (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks); + return (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps + pSector->ubNumRobots); } UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) @@ -400,13 +400,13 @@ UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) if( pSector->ubGarrisonID == ROADBLOCK ) { //consider these troops as mobile troops even though they are in a garrison - ubNumTroops += (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumJeeps + pSector->ubNumTanks); + ubNumTroops += (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumJeeps + pSector->ubNumTanks); } return ubNumTroops; } -void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) +void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { GROUP *pGroup; SECTORINFO *pSector; @@ -416,7 +416,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 = *pubNumJeeps =0; + *pubNumTroops = *pubNumElites = *pubNumAdmins = *pubNumRobots = *pubNumTanks = *pubNumJeeps = 0; pGroup = gpGroupList; while( pGroup ) { @@ -425,6 +425,7 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu *pubNumTroops += pGroup->pEnemyGroup->ubNumTroops; *pubNumElites += pGroup->pEnemyGroup->ubNumElites; *pubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins; + *pubNumRobots += pGroup->pEnemyGroup->ubNumRobots; *pubNumTanks += pGroup->pEnemyGroup->ubNumTanks; *pubNumJeeps += pGroup->pEnemyGroup->ubNumJeeps; } @@ -438,12 +439,13 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu *pubNumAdmins += pSector->ubNumAdmins; *pubNumTroops += pSector->ubNumTroops; *pubNumElites += pSector->ubNumElites; + *pubNumRobots += pSector->ubNumRobots; *pubNumTanks += pSector->ubNumTanks; *pubNumJeeps += pSector->ubNumJeeps; } } -void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, 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 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { GROUP *pGroup; AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE); @@ -452,7 +454,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 = *pubNumJeeps = 0; + *pubNumTroops = *pubNumElites = *pubNumAdmins = *pubNumRobots = *pubNumTanks = *pubNumJeeps = 0; pGroup = gpGroupList; while( pGroup ) { @@ -461,6 +463,7 @@ void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSe *pubNumTroops += pGroup->pEnemyGroup->ubNumTroops; *pubNumElites += pGroup->pEnemyGroup->ubNumElites; *pubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins; + *pubNumRobots += pGroup->pEnemyGroup->ubNumRobots; *pubNumTanks += pGroup->pEnemyGroup->ubNumTanks; *pubNumJeeps += pGroup->pEnemyGroup->ubNumJeeps; } @@ -469,7 +472,7 @@ void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSe } -void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) +void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { SECTORINFO *pSector; AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE); @@ -482,21 +485,23 @@ void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins = pSector->ubNumAdmins; *pubNumTroops = pSector->ubNumTroops; *pubNumElites = pSector->ubNumElites; + *pubNumRobots = pSector->ubNumRobots; *pubNumTanks = pSector->ubNumTanks; *pubNumJeeps = pSector->ubNumJeeps; } -void GetNumberOfEnemiesInSector( 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 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { - UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumRobots, ubNumTanks, ubNumJeeps; - GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks, pubNumJeeps ); + GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumRobots, pubNumTanks, pubNumJeeps ); - GetNumberOfMobileEnemiesInSector( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); + GetNumberOfMobileEnemiesInSector( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumRobots, &ubNumTanks, &ubNumJeeps ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; *pubNumElites += ubNumElites; + *pubNumRobots += ubNumRobots; *pubNumTanks += ubNumTanks; *pubNumJeeps += ubNumJeeps; } @@ -514,6 +519,7 @@ void EndTacticalBattleForEnemy() pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; + pSector->ubRobotsInBattle = 0; pSector->ubTanksInBattle = 0; pSector->ubJeepsInBattle = 0; } @@ -525,6 +531,7 @@ void EndTacticalBattleForEnemy() pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; + pSector->ubRobotsInBattle = 0; pSector->ubTanksInBattle = 0; pSector->ubJeepsInBattle = 0; pSector->ubNumCreatures = 0; @@ -544,6 +551,7 @@ void EndTacticalBattleForEnemy() { pGroup->pEnemyGroup->ubTroopsInBattle = 0; pGroup->pEnemyGroup->ubElitesInBattle = 0; + pGroup->pEnemyGroup->ubRobotsInBattle = 0; pGroup->pEnemyGroup->ubAdminsInBattle = 0; pGroup->pEnemyGroup->ubTanksInBattle = 0; pGroup->pEnemyGroup->ubJeepsInBattle = 0; @@ -601,8 +609,8 @@ BOOLEAN PrepareEnemyForSectorBattle() SECTORINFO *pSector; GROUP *pGroup; SOLDIERTYPE *pSoldier; - unsigned ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; - unsigned ubTotalAdmins, ubTotalElites, ubTotalTroops, ubTotalTanks, ubTotalJeeps = 0; + unsigned ubNumAdmins, ubNumTroops, ubNumElites, ubNumRobots, ubNumTanks, ubNumJeeps; + unsigned ubTotalAdmins, ubTotalElites, ubTotalRobots, ubTotalTroops, ubTotalTanks, ubTotalJeeps = 0; unsigned totalCountOfStationaryEnemies = 0; unsigned totalCountOfMobileEnemies = 0; int sNumSlots; @@ -658,6 +666,7 @@ BOOLEAN PrepareEnemyForSectorBattle() !pGroup->pEnemyGroup->ubAdminsInBattle && !pGroup->pEnemyGroup->ubTroopsInBattle && !pGroup->pEnemyGroup->ubElitesInBattle && + !pGroup->pEnemyGroup->ubRobotsInBattle && !pGroup->pEnemyGroup->ubTanksInBattle && !pGroup->pEnemyGroup->ubJeepsInBattle ) { @@ -698,13 +707,14 @@ 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 + pSector->ubNumJeeps); + float totalEnemies = (float)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + 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); + ubTotalRobots = (unsigned int)(((float)pSector->ubNumRobots / totalEnemies) * mapMaximumNumberOfEnemies); ubTotalTanks = (unsigned int)(((float)pSector->ubNumTanks / totalEnemies) * mapMaximumNumberOfEnemies); ubTotalJeeps = (unsigned int)(((float)pSector->ubNumJeeps / totalEnemies) * mapMaximumNumberOfEnemies); - totalEnemies = (float)(ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks + ubTotalJeeps); + totalEnemies = (float)(ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalRobots + ubTotalTanks + ubTotalJeeps); // take care of any rounding losses while (totalEnemies < mapMaximumNumberOfEnemies) @@ -717,11 +727,13 @@ BOOLEAN PrepareEnemyForSectorBattle() pSector->ubNumAdmins = ubTotalAdmins; pSector->ubNumTroops = ubTotalTroops; pSector->ubNumElites = ubTotalElites; + pSector->ubNumRobots = ubTotalRobots; pSector->ubNumTanks = ubTotalTanks; pSector->ubNumJeeps = ubTotalJeeps; pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; + pSector->ubRobotsInBattle = 0; pSector->ubTanksInBattle = 0; pSector->ubJeepsInBattle = 0; } @@ -742,6 +754,7 @@ BOOLEAN PrepareEnemyForSectorBattle() case SOLDIER_CLASS_BANDIT: ubTotalAdmins++; break; case SOLDIER_CLASS_ARMY: ubTotalTroops++; break; case SOLDIER_CLASS_ELITE: ubTotalElites++; break; + case SOLDIER_CLASS_ROBOT: ubTotalRobots++; break; case SOLDIER_CLASS_TANK: ubTotalTanks++; break; case SOLDIER_CLASS_JEEP: ubTotalJeeps++; break; } @@ -751,11 +764,13 @@ BOOLEAN PrepareEnemyForSectorBattle() pSector->ubNumAdmins = ubTotalAdmins; pSector->ubNumTroops = ubTotalTroops; pSector->ubNumElites = ubTotalElites; + pSector->ubNumRobots = ubTotalRobots; pSector->ubNumTanks = ubTotalTanks; pSector->ubNumJeeps = ubTotalJeeps; pSector->ubAdminsInBattle = 0; pSector->ubTroopsInBattle = 0; pSector->ubElitesInBattle = 0; + pSector->ubRobotsInBattle = 0; pSector->ubTanksInBattle = 0; pSector->ubJeepsInBattle = 0; } @@ -764,12 +779,13 @@ BOOLEAN PrepareEnemyForSectorBattle() ubTotalAdmins = pSector->ubNumAdmins - pSector->ubAdminsInBattle; ubTotalTroops = pSector->ubNumTroops - pSector->ubTroopsInBattle; ubTotalElites = pSector->ubNumElites - pSector->ubElitesInBattle; + ubTotalRobots = pSector->ubNumRobots - pSector->ubRobotsInBattle; ubTotalTanks = pSector->ubNumTanks - pSector->ubTanksInBattle; ubTotalJeeps = pSector->ubNumJeeps - pSector->ubJeepsInBattle; } } - totalCountOfStationaryEnemies = ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalTanks + ubTotalJeeps; + totalCountOfStationaryEnemies = ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalRobots + ubTotalTanks + ubTotalJeeps; if( totalCountOfStationaryEnemies > mapMaximumNumberOfEnemies ) { @@ -783,13 +799,15 @@ BOOLEAN PrepareEnemyForSectorBattle() ubTotalAdmins = min( mapMaximumNumberOfEnemies, ubTotalAdmins ); 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 ); + ubTotalRobots = min( mapMaximumNumberOfEnemies-ubTotalAdmins-ubTotalTroops-ubTotalElites, ubTotalRobots ); + ubTotalTanks = min( mapMaximumNumberOfEnemies-ubTotalAdmins-ubTotalTroops-ubTotalElites-ubTotalRobots, ubTotalTanks ); + ubTotalJeeps = min( mapMaximumNumberOfEnemies-ubTotalAdmins-ubTotalTroops-ubTotalElites-ubTotalRobots-ubTotalTanks, ubTotalJeeps ); } pSector->ubAdminsInBattle += ubTotalAdmins; pSector->ubTroopsInBattle += ubTotalTroops; pSector->ubElitesInBattle += ubTotalElites; + pSector->ubRobotsInBattle += ubTotalRobots; pSector->ubTanksInBattle += ubTotalTanks; pSector->ubJeepsInBattle += ubTotalJeeps; @@ -797,9 +815,9 @@ BOOLEAN PrepareEnemyForSectorBattle() if( gfOverrideSector ) { //if there are no troops in the current groups, then we're done. - if ( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks && !ubTotalJeeps ) + if ( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks && !ubTotalJeeps && !ubTotalRobots) return FALSE; - AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks, ubTotalJeeps ); + AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks, ubTotalJeeps, ubTotalRobots ); ValidateEnemiesHaveWeapons(); UnPauseGame(); return TRUE; @@ -827,7 +845,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 + ubTotalJeeps; + sNumSlots -= ubTotalAdmins + ubTotalTroops + ubTotalElites + ubTotalRobots + 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 @@ -881,6 +899,20 @@ BOOLEAN PrepareEnemyForSectorBattle() ubTotalElites += ubNumElites; } if( sNumSlots > 0 ) + { //Add robots + AssertGE(pGroup->pEnemyGroup->ubNumRobots, pGroup->pEnemyGroup->ubRobotsInBattle); + ubNumRobots = pGroup->pEnemyGroup->ubNumRobots - pGroup->pEnemyGroup->ubRobotsInBattle; + sNumSlots -= ubNumRobots; + if( sNumSlots < 0 ) + { //adjust the value to zero + ubNumRobots += sNumSlots; + sNumSlots = 0; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; + } + pGroup->pEnemyGroup->ubRobotsInBattle += ubNumRobots; + ubTotalRobots += ubNumRobots; + } + if( sNumSlots > 0 ) { //Add tanks AssertGE(pGroup->pEnemyGroup->ubNumTanks, pGroup->pEnemyGroup->ubTanksInBattle); ubNumTanks = pGroup->pEnemyGroup->ubNumTanks - pGroup->pEnemyGroup->ubTanksInBattle; @@ -930,12 +962,12 @@ BOOLEAN PrepareEnemyForSectorBattle() } //if there are no troops in the current groups, then we're done. - if ( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalTanks && !ubTotalJeeps ) + if ( !ubTotalAdmins && !ubTotalTroops && !ubTotalElites && !ubTotalRobots && !ubTotalTanks && !ubTotalJeeps ) { return FALSE; } - AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks, ubTotalJeeps ); + AddSoldierInitListEnemyDefenceSoldiers( ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalRobots, 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 @@ -956,9 +988,10 @@ BOOLEAN PrepareEnemyForSectorBattle() ubNumAdmins = pGroup->pEnemyGroup->ubAdminsInBattle; ubNumTroops = pGroup->pEnemyGroup->ubTroopsInBattle; ubNumElites = pGroup->pEnemyGroup->ubElitesInBattle; + ubNumRobots = pGroup->pEnemyGroup->ubRobotsInBattle; ubNumTanks = pGroup->pEnemyGroup->ubTanksInBattle; ubNumJeeps = pGroup->pEnemyGroup->ubJeepsInBattle; - unsigned num = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps; + unsigned num = ubNumAdmins + ubNumTroops + ubNumElites + ubNumRobots + ubNumTanks + ubNumJeeps; AssertGE((int)slotsAvailable, sNumSlots); @@ -1028,6 +1061,16 @@ BOOLEAN PrepareEnemyForSectorBattle() } } break; + case SOLDIER_CLASS_ROBOT: + if( ubNumRobots ) + { + num--; + sNumSlots--; + ubNumRobots--; + pSoldier->ubGroupID = pGroup->ubGroupID; + firstSlot = slot + 1; + } + break; case SOLDIER_CLASS_TANK: if( ubNumTanks ) { @@ -1058,6 +1101,7 @@ BOOLEAN PrepareEnemyForSectorBattle() AssertEQ( ubNumAdmins , 0); AssertEQ( ubNumTanks , 0); AssertEQ( ubNumJeeps , 0); + AssertEQ( ubNumRobots , 0); AssertEQ( num , 0);*/ } pGroup = pGroup->next; @@ -1072,7 +1116,7 @@ BOOLEAN PrepareEnemyForSectorBattle() BOOLEAN PrepareEnemyForUndergroundBattle() { UNDERGROUND_SECTORINFO *pUnderground; - unsigned ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalTanks, ubTotalJeeps; + unsigned ubTotalAdmins, ubTotalTroops, ubTotalElites, ubTotalRobots, ubTotalTanks, ubTotalJeeps; pUnderground = gpUndergroundSectorInfoHead; while( pUnderground ) @@ -1086,18 +1130,20 @@ BOOLEAN PrepareEnemyForUndergroundBattle() ubTotalAdmins = (UINT8)(pUnderground->ubNumAdmins - pUnderground->ubAdminsInBattle); ubTotalTroops = (UINT8)(pUnderground->ubNumTroops - pUnderground->ubTroopsInBattle); ubTotalElites = (UINT8)(pUnderground->ubNumElites - pUnderground->ubElitesInBattle); + ubTotalRobots = (UINT8)(pUnderground->ubNumRobots - pUnderground->ubRobotsInBattle); ubTotalTanks = (UINT8)(pUnderground->ubNumTanks - pUnderground->ubTanksInBattle); ubTotalJeeps = (UINT8)(pUnderground->ubNumJeeps - pUnderground->ubJeepsInBattle); pUnderground->ubAdminsInBattle += ubTotalAdmins; pUnderground->ubTroopsInBattle += ubTotalTroops; pUnderground->ubElitesInBattle += ubTotalElites; + pUnderground->ubRobotsInBattle += ubTotalRobots; pUnderground->ubTanksInBattle += ubTotalTanks; pUnderground->ubJeepsInBattle += ubTotalJeeps; - AddSoldierInitListEnemyDefenceSoldiers( pUnderground->ubNumAdmins, pUnderground->ubNumTroops, pUnderground->ubNumElites, pUnderground->ubNumTanks, pUnderground->ubNumJeeps ); + AddSoldierInitListEnemyDefenceSoldiers( pUnderground->ubNumAdmins, pUnderground->ubNumTroops, pUnderground->ubNumElites, pUnderground->ubNumRobots, pUnderground->ubNumTanks, pUnderground->ubNumJeeps ); ValidateEnemiesHaveWeapons(); UnPauseGame(); } - return ((BOOLEAN)(pUnderground->ubNumAdmins + pUnderground->ubNumTroops + pUnderground->ubNumElites + pUnderground->ubNumTanks + pUnderground->ubNumJeeps > 0)); + return ((BOOLEAN)(pUnderground->ubNumAdmins + pUnderground->ubNumTroops + pUnderground->ubNumElites + pUnderground->ubNumRobots + pUnderground->ubNumTanks + pUnderground->ubNumJeeps > 0)); } pUnderground = pUnderground->next; } @@ -1284,6 +1330,16 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) switch( pSoldier->ubSoldierClass ) { + case SOLDIER_CLASS_ROBOT: + if( pGroup->pEnemyGroup->ubNumRobots ) + { + pGroup->pEnemyGroup->ubNumRobots--; + } + if( pGroup->pEnemyGroup->ubRobotsInBattle ) + { + pGroup->pEnemyGroup->ubRobotsInBattle--; + } + break; case SOLDIER_CLASS_ELITE: #ifdef JA2BETAVERSION if( !pGroup->pEnemyGroup->ubNumElites ) @@ -1464,6 +1520,16 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) pSector->ubElitesInBattle--; } break; + case SOLDIER_CLASS_ROBOT: + if( pSector->ubNumRobots ) + { + pSector->ubNumRobots--; + } + if( pSector->ubRobotsInBattle ) + { + pSector->ubRobotsInBattle--; + } + break; case SOLDIER_CLASS_CREATURE: case SOLDIER_CLASS_BANDIT: case SOLDIER_CLASS_ZOMBIE: @@ -1570,6 +1636,16 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) pSector->ubElitesInBattle--; } break; + case SOLDIER_CLASS_ROBOT: + if( pSector->ubNumRobots ) + { + pSector->ubNumRobots--; + } + if( pSector->ubRobotsInBattle ) + { + pSector->ubRobotsInBattle--; + } + break; case SOLDIER_CLASS_CREATURE: case SOLDIER_CLASS_BANDIT: case SOLDIER_CLASS_ZOMBIE: @@ -1662,7 +1738,7 @@ void AddPossiblePendingEnemiesToBattle() #endif UINT8 ubSlots, ubNumAvailable; - UINT8 ubNumElites, ubNumTroops, ubNumAdmins, ubNumTanks, ubNumJeeps; + UINT8 ubNumRobots, ubNumElites, ubNumTroops, ubNumAdmins, ubNumTanks, ubNumJeeps; UINT8 ubNumGroupsInSector; UINT8 ubGroupIndex; GROUP *pGroup; @@ -1758,18 +1834,25 @@ void AddPossiblePendingEnemiesToBattle() //return; } - if ( pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps ) + if ( pSector->ubNumRobots + pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps ) { - ubNumElites = ubNumTroops = ubNumAdmins = ubNumTanks = ubNumJeeps = 0; + ubNumRobots = ubNumElites = ubNumTroops = ubNumAdmins = ubNumTanks = ubNumJeeps = 0; - ubNumAvailable = pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps - - pSector->ubElitesInBattle - pSector->ubTroopsInBattle - pSector->ubAdminsInBattle - pSector->ubTanksInBattle - pSector->ubJeepsInBattle; + ubNumAvailable = pSector->ubNumRobots + pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps + - pSector->ubRobotsInBattle - pSector->ubElitesInBattle - pSector->ubTroopsInBattle - pSector->ubAdminsInBattle - pSector->ubTanksInBattle - pSector->ubJeepsInBattle; while( ubNumAvailable && ubSlots ) { // So they just magically appear out of nowhere from the edge? //This group has enemies waiting for a chance to enter the battle. - if( pSector->ubElitesInBattle < pSector->ubNumElites ) + if( pSector->ubRobotsInBattle < pSector->ubNumRobots ) + { //Add a robot + pSector->ubRobotsInBattle++; + ubNumAvailable--; + ubSlots--; + ubNumRobots++; + } + else if( pSector->ubElitesInBattle < pSector->ubNumElites ) { //Add an elite troop pSector->ubElitesInBattle++; ubNumAvailable--; @@ -1812,7 +1895,7 @@ void AddPossiblePendingEnemiesToBattle() } - if ( ubNumAdmins || ubNumTroops || ubNumElites || ubNumTanks || ubNumJeeps ) + if ( ubNumAdmins || ubNumTroops || ubNumElites || ubNumRobots || ubNumTanks || ubNumJeeps ) { //This group has contributed forces, then add them now, because different //groups appear on different sides of the map. UINT8 ubStrategicInsertionCode = ubPredefinedInsertionCode; @@ -1853,7 +1936,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, ubNumJeeps, FALSE ); + AddEnemiesToBattle( 0, ubStrategicInsertionCode, ubNumAdmins, ubNumTroops, ubNumElites, ubNumRobots, ubNumTanks, ubNumJeeps, FALSE ); gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; } } @@ -1884,7 +1967,7 @@ void AddPossiblePendingEnemiesToBattle() // Flugente fix: check for underflow... UINT8 currentgroupsize = pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle - + pGroup->pEnemyGroup->ubTanksInBattle + pGroup->pEnemyGroup->ubJeepsInBattle; + + pGroup->pEnemyGroup->ubRobotsInBattle + pGroup->pEnemyGroup->ubTanksInBattle + pGroup->pEnemyGroup->ubJeepsInBattle; if ( currentgroupsize > pGroup->ubGroupSize ) ubNumAvailable = 0; else @@ -1949,32 +2032,37 @@ void AddPossiblePendingEnemiesToBattle() { //Add an elite troop pGroup->pEnemyGroup->ubElitesInBattle++; ubSlots--; - AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 1, 0, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 1, 0, 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, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 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, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 1, 0, 0, 0, 0, 0, FALSE ); + } + else if( pGroup->pEnemyGroup->ubRobotsInBattle < pGroup->pEnemyGroup->ubNumRobots) + { //Add a robot + pGroup->pEnemyGroup->ubRobotsInBattle++; + ubSlots--; + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 0, 1, 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, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 0, 0, 1, 0, FALSE ); } else if ( pGroup->pEnemyGroup->ubJeepsInBattle < pGroup->pEnemyGroup->ubNumJeeps ) - { - //Add a jeep + { //Add a jeep pGroup->pEnemyGroup->ubJeepsInBattle++; ubSlots--; - AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 0, 0, 1, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 0, 0, 0, 0, 1, FALSE ); } else { @@ -1983,7 +2071,7 @@ void AddPossiblePendingEnemiesToBattle() pGroup->pEnemyGroup->ubTroopsInBattle++; ubSlots--; - AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 0, 0, FALSE ); + AddEnemiesToBattle( pGroup, ubInsertionCode, 0, 1, 0, 0, 0, 0, FALSE ); } } @@ -2053,7 +2141,7 @@ void NotifyPlayersOfNewEnemies() } } -void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, UINT8 ubNumJeeps, BOOLEAN fMagicallyAppeared ) +void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumRobots, UINT8 ubNumTanks, UINT8 ubNumJeeps, BOOLEAN fMagicallyAppeared ) { SOLDIERTYPE *pSoldier; MAPEDGEPOINTINFO MapEdgepointInfo; @@ -2078,13 +2166,15 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub if( !gbWorldSectorZ ) { SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; - pSector->ubNumAdmins += ubNumAdmins; + pSector->ubNumAdmins += ubNumAdmins; pSector->ubAdminsInBattle += ubNumAdmins; - pSector->ubNumTroops += ubNumTroops; + pSector->ubNumTroops += ubNumTroops; pSector->ubTroopsInBattle += ubNumTroops; - pSector->ubNumElites += ubNumElites; + pSector->ubNumElites += ubNumElites; pSector->ubElitesInBattle += ubNumElites; - pSector->ubNumTanks += ubNumTanks; + pSector->ubNumRobots += ubNumRobots; + pSector->ubRobotsInBattle += ubNumRobots; + pSector->ubNumTanks += ubNumTanks; pSector->ubTanksInBattle += ubNumTanks; pSector->ubNumJeeps += ubNumJeeps; pSector->ubJeepsInBattle += ubNumJeeps; @@ -2094,13 +2184,15 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub UNDERGROUND_SECTORINFO *pSector = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); if( pSector ) { - pSector->ubNumAdmins += ubNumAdmins; + pSector->ubNumAdmins += ubNumAdmins; pSector->ubAdminsInBattle += ubNumAdmins; - pSector->ubNumTroops += ubNumTroops; + pSector->ubNumTroops += ubNumTroops; pSector->ubTroopsInBattle += ubNumTroops; - pSector->ubNumElites += ubNumElites; + pSector->ubNumElites += ubNumElites; pSector->ubElitesInBattle += ubNumElites; - pSector->ubNumTanks += ubNumTanks; + pSector->ubNumRobots += ubNumRobots; + pSector->ubRobotsInBattle += ubNumRobots; + pSector->ubNumTanks += ubNumTanks; pSector->ubTanksInBattle += ubNumTanks; pSector->ubNumJeeps += ubNumJeeps; pSector->ubJeepsInBattle += ubNumJeeps; @@ -2110,7 +2202,7 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub NotifyPlayersOfNewEnemies(); } - ubTotalSoldiers = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps; + ubTotalSoldiers = ubNumAdmins + ubNumTroops + ubNumElites + ubNumRobots + ubNumTanks + ubNumJeeps; #ifdef JA2UB if( gsGridNoForMapEdgePointInfo != -1 ) @@ -2232,7 +2324,30 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub } UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 ); } - else if( ubNumTanks && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumTroops + ubNumAdmins + ubNumTanks) && ubNumberOfVehicles < 9 ) + else if( ubNumRobots && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumTroops + ubNumAdmins + ubNumRobots) ) + { + ubNumRobots--; + ubTotalSoldiers--; + Assert(pSoldier = TacticalCreateEnemyRobot()); + 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 ); + } + else if( ubNumTanks && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumTroops + ubNumAdmins + ubNumRobots + ubNumTanks) && ubNumberOfVehicles < 9 ) { ubNumTanks--; ubTotalSoldiers--; @@ -2255,7 +2370,7 @@ 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 ) + else if ( ubNumJeeps && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumTroops + ubNumAdmins + ubNumRobots + ubNumTanks + ubNumJeeps) && ubNumberOfVehicles < 9 ) { ubNumJeeps--; ubTotalSoldiers--; @@ -2972,8 +3087,8 @@ BOOLEAN CheckPendingNonPlayerTeam( UINT8 usTeam ) if ( usTeam == ENEMY_TEAM ) { - if ( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps) > - (pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle + pSector->ubTanksInBattle + pSector->ubJeepsInBattle) ) + if ( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps + pSector->ubNumRobots) > + (pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle + pSector->ubTanksInBattle + pSector->ubJeepsInBattle + pSector->ubRobotsInBattle) ) return TRUE; } @@ -2987,7 +3102,7 @@ BOOLEAN CheckPendingNonPlayerTeam( UINT8 usTeam ) if ( usTeam == ENEMY_TEAM ) { if ( pGroup->ubGroupSize > pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle - + pGroup->pEnemyGroup->ubTanksInBattle + pGroup->pEnemyGroup->ubJeepsInBattle ) + + pGroup->pEnemyGroup->ubTanksInBattle + pGroup->pEnemyGroup->ubJeepsInBattle + pGroup->pEnemyGroup->ubRobotsInBattle ) return TRUE; } else if ( usTeam == MILITIA_TEAM ) diff --git a/Strategic/Queen Command.h b/Strategic/Queen Command.h index 9081bf0b..8b5dcea0 100644 --- a/Strategic/Queen Command.h +++ b/Strategic/Queen Command.h @@ -28,10 +28,10 @@ UINT16 NumPlayerTeamMembersInSector( INT16 sSectorX, INT16 sSectorY, INT8 sSecto 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, 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 ); +void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); +void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); +void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ); +void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, 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 @@ -39,7 +39,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, UINT8 abNumJeeps, BOOLEAN fMagicallyAppeared ); +void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumRobots, 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 738e1ec0..e74d8b2a 100644 --- a/Strategic/Reinforcement.cpp +++ b/Strategic/Reinforcement.cpp @@ -33,19 +33,20 @@ 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, UINT8 *pubNumJeeps ) +void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { - UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumRobots, 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, pubNumJeeps ); + GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumRobots, pubNumTanks, pubNumJeeps ); - GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); + GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumRobots, &ubNumTanks, &ubNumJeeps ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; *pubNumElites += ubNumElites; + *pubNumRobots += ubNumRobots; *pubNumTanks += ubNumTanks; *pubNumJeeps += ubNumJeeps; @@ -59,11 +60,16 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub 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, &ubNumJeeps ); + GetNumberOfStationaryEnemiesInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumRobots, &ubNumTanks, &ubNumJeeps ); - while ( ubNumElites + ubNumTroops + ubNumAdmins + ubNumTanks + ubNumJeeps > gubReinforcementMinEnemyStaticGroupSize ) //count how many of static group will reinforce the battle, but leave minimal group size to guard + while ( ubNumRobots + 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 ) + if ( ubNumRobots ) + { + *pubNumRobots += 1; + ubNumRobots--; + } + else if( ubNumElites ) { *pubNumElites += 1; ubNumElites--; @@ -90,11 +96,12 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub } } - GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); + GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumRobots, &ubNumTanks, &ubNumJeeps ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; *pubNumElites += ubNumElites; + *pubNumRobots += ubNumRobots; *pubNumTanks += ubNumTanks; *pubNumJeeps += ubNumJeeps; } @@ -102,11 +109,11 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY ) { - UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps; + UINT8 ubNumAdmins, ubNumTroops, ubNumElites, ubNumRobots, ubNumTanks, ubNumJeeps; - GetNumberOfEnemiesInFiveSectors( sMapX, sMapY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks, &ubNumJeeps ); + GetNumberOfEnemiesInFiveSectors( sMapX, sMapY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumRobots, &ubNumTanks, &ubNumJeeps ); - return ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps; + return ubNumAdmins + ubNumTroops + ubNumElites + ubNumRobots + ubNumTanks + ubNumJeeps; } BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 sSectorY ) @@ -256,40 +263,47 @@ UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam { pSector = &SectorInfo[ pusMoveDir[ ubIndex ][ 0 ] ]; - if( pSector->ubNumElites ) + if( pSector->ubNumRobots ) + { + (pThisSector->ubNumRobots)++; + (pSector->ubNumRobots)--; + (pThisSector->ubRobotsInBattle)++; + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 0, 1, 0, 0, FALSE ); + } + else if( pSector->ubNumElites ) { (pThisSector->ubNumElites)++; (pSector->ubNumElites)--; (pThisSector->ubElitesInBattle)++; - AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 1, 0, 0, FALSE ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 1, 0, 0, 0, FALSE ); } else if( pSector->ubNumTroops ) { (pThisSector->ubNumTroops)++; (pSector->ubNumTroops)--; (pThisSector->ubTroopsInBattle)++; - AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 1, 0, 0, 0, FALSE ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 1, 0, 0, 0, 0, FALSE ); } else if( pSector->ubNumAdmins ) { (pThisSector->ubNumAdmins)++; (pSector->ubNumAdmins)--; (pThisSector->ubAdminsInBattle)++; - AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 1, 0, 0, 0, 0, FALSE ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 1, 0, 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, 0, FALSE ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 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 ); + AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 0, 0, 0, 1, FALSE ); } return (UINT8)pusMoveDir[ ubIndex ][ 2 ]; diff --git a/Strategic/Reinforcement.h b/Strategic/Reinforcement.h index e4a57807..235f1067 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, UINT8 *pubNumJeeps ); +void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumRobots, 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 5ff79593..5ea4a00a 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -554,7 +554,7 @@ INT32 GarrisonReinforcementsRequested( INT32 iGarrisonID, UINT8 *pubExtraReinfor Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; - iExistingForces = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + iExistingForces = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + 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 @@ -607,7 +607,7 @@ INT32 ReinforcementsAvailable( INT32 iGarrisonID ) Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; - iReinforcementsAvailable = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps; + iReinforcementsAvailable = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; iReinforcementsAvailable -= gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation; switch( gGarrisonGroup[ iGarrisonID ].ubComposition ) @@ -686,7 +686,7 @@ BOOLEAN AdjacentSectorIsImportantAndUndefended( UINT8 ubSectorID ) pSector = &SectorInfo[ ubSectorID ]; - if ( pSector->ubNumTroops || pSector->ubNumElites || pSector->ubNumAdmins || pSector->ubNumTanks || pSector->ubNumJeeps ) + if ( pSector->ubNumTroops || pSector->ubNumElites || pSector->ubNumAdmins || pSector->ubNumRobots || pSector->ubNumTanks || pSector->ubNumJeeps ) { return FALSE; } @@ -828,7 +828,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic2"); } } #ifdef JA2BETAVERSION - if ( pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps != pGroup->ubGroupSize || + if ( pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + pGroup->pEnemyGroup->ubNumRobots != pGroup->ubGroupSize || pGroup->ubGroupSize > iMaxEnemyGroupSize ) { SAIReportError( L"Strategic AI: Internal error (bad group populations). Please send PRIOR save file and Strategic Decisions.txt." ); @@ -1133,7 +1133,7 @@ void InitStrategicAI() SECTORINFO *pSector = NULL; GROUP *pGroup; UINT8 ubNumTroops; - UINT8 ubNumTanks, ubNumJeeps; + UINT8 ubNumRobots, ubNumTanks, ubNumJeeps; INT32 iPercentElitesBonus; INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic3"); @@ -1416,7 +1416,7 @@ void InitStrategicAI() } } } - + switch( gGarrisonGroup[ i ].ubComposition ) { case CAMBRIA_DEFENCE: @@ -1433,15 +1433,30 @@ void InitStrategicAI() break; case TIXA_PRISON: pSector->ubNumAdmins = (UINT8)max( 8, pSector->ubNumAdmins ); + if (gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsRobots) + pSector->ubNumRobots = (UINT8)max( Random(gGameOptions.ubDifficultyLevel - 1), pSector->ubNumRobots ); + break; + case QUEEN_DEFENCE: + case MEDUNA_DEFENCE: + case MEDUNA_SAMSITE: + if (gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsRobots) + pSector->ubNumRobots = (UINT8)max( 1 + Random(gGameOptions.ubDifficultyLevel), pSector->ubNumRobots ); + break; + case ORTA_DEFENCE: + case LEVEL1_DEFENCE: + case LEVEL2_DEFENCE: + case LEVEL3_DEFENCE: + if (gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsRobots) + pSector->ubNumRobots = (UINT8)max( Random(gGameOptions.ubDifficultyLevel), pSector->ubNumRobots ); break; } } // fill up deficit with admins if total enemies less than min enemy group size - if ( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps < gubMinEnemyGroupSize ) + if ( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps < gubMinEnemyGroupSize ) { - pSector->ubNumAdmins = gubMinEnemyGroupSize - pSector->ubNumTroops - pSector->ubNumElites - pSector->ubNumTanks - pSector->ubNumJeeps; + pSector->ubNumAdmins = gubMinEnemyGroupSize - pSector->ubNumTroops - pSector->ubNumElites - pSector->ubNumRobots - pSector->ubNumTanks - pSector->ubNumJeeps; } //Calculate weight (range is -20 to +20 before multiplier). @@ -1494,49 +1509,15 @@ void InitStrategicAI() //based on the difficulty settings in the above patrol table. //if( gPatrolGroup[ i ].ubUNUSEDStartIfDifficulty <= gGameOptions.ubDifficultyLevel ) { - //Add this patrol group now. - ubNumTroops = (UINT8)(gPatrolGroup[ i ].bSize + Random( 3 ) - 1); - ubNumTroops = (UINT8)max( gubMinEnemyGroupSize, min( iMaxEnemyGroupSize, ubNumTroops ) ); - ubNumTanks = 0; - ubNumJeeps = 0; + UINT8 troopCount = (UINT8)(gPatrolGroup[ i ].bSize + Random( 3 ) - 1); + troopCount = (UINT8)max( gubMinEnemyGroupSize, min( iMaxEnemyGroupSize, troopCount) ); + UINT8 ubNumElites; + InitializeGroup(GROUP_TYPE_PATROL, troopCount, ubNumTroops, ubNumElites, ubNumRobots, ubNumJeeps, ubNumTanks, Random(10) < gGameOptions.ubDifficultyLevel && i != 3 && i != 4); - if ( ubNumTroops ) - { - UINT32 val2; - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - val2 = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - val2 = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - val2 = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - val2 = 4; - else - { - val2 = Random( 4 ); - if (val2 == 0) val2 = 1; - } - - if ( Random( 10 ) < val2 && i != 3 && i != 4 ) - { - if ( gGameExternalOptions.fArmyUsesJeepsInPatrols && ASDSoldierUpgradeToJeep( ) ) - { - ubNumTroops--; - ubNumJeeps++; - } - else if ( gGameExternalOptions.fArmyUsesTanksInPatrols && ASDSoldierUpgradeToTank( ) ) - { - ubNumTroops--; - ubNumTanks++; - } - } - } - - //ubNumTroops = (UINT8)max( gubMinEnemyGroupSize, min( MAX_STRATEGIC_TEAM_SIZE, gPatrolGroup[ i ].bSize + Random( 3 ) - 1 ) ); //Note on adding patrol groups... //The patrol group can't actually start on the first waypoint, so we set it to the second way //point for initialization, and then add the waypoints from 0 up - pGroup = CreateNewEnemyGroupDepartingFromSector( gPatrolGroup[ i ].ubSectorID[ 1 ], 0, ubNumTroops, 0, ubNumTanks, ubNumJeeps ); + pGroup = CreateNewEnemyGroupDepartingFromSector( gPatrolGroup[ i ].ubSectorID[ 1 ], 0, ubNumTroops, ubNumElites, ubNumRobots, ubNumTanks, ubNumJeeps ); Assert( pGroup ); if( i == 3 || i == 4 ) @@ -1871,6 +1852,7 @@ BOOLEAN HandlePlayerGroupNoticedByPatrolGroup( GROUP *pPlayerGroup, GROUP *pEnem usOffensePoints = pEnemyGroup->pEnemyGroup->ubNumAdmins * 2 + pEnemyGroup->pEnemyGroup->ubNumTroops * 4 + pEnemyGroup->pEnemyGroup->ubNumElites * 6 + + pEnemyGroup->pEnemyGroup->ubNumRobots * 15 + pEnemyGroup->pEnemyGroup->ubNumTanks * 20 + pEnemyGroup->pEnemyGroup->ubNumJeeps * 12; if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) ) @@ -1925,6 +1907,7 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID ) usOffensePoints = pSector->ubNumAdmins * 2 + pSector->ubNumTroops * 4 + pSector->ubNumElites * 6 + + pSector->ubNumElites * 15 + pSector->ubNumTanks * 20 + pSector->ubNumJeeps * 12; if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) ) @@ -1938,7 +1921,7 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID ) if( pSector->ubGarrisonID != NO_GARRISON ) { //Decide whether or not they will attack them with some of the troops. - ubEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps); + ubEnemies = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps); if ( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) iReinforcementsApproved = (ubEnemies - gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation ); else @@ -1946,7 +1929,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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ); @@ -1955,12 +1938,12 @@ void HandlePlayerGroupNoticedByGarrison( GROUP *pPlayerGroup, UINT8 ubSectorID ) if ( pGroup ) RemoveSoldiersFromGarrisonBasedOnComposition( pSector->ubGarrisonID, pGroup->ubGroupSize ); - if ( pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps > iMaxEnemyGroupSize ) + if ( pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumRobots + 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 + pSector->ubNumJeeps, iMaxEnemyGroupSize ); + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps + pSector->ubNumRobots, iMaxEnemyGroupSize ); #endif } @@ -1983,6 +1966,7 @@ BOOLEAN HandleMilitiaNoticedByPatrolGroup( UINT8 ubSectorID, GROUP *pEnemyGroup usOffensePoints = pEnemyGroup->pEnemyGroup->ubNumAdmins * 2 + pEnemyGroup->pEnemyGroup->ubNumTroops * 4 + pEnemyGroup->pEnemyGroup->ubNumElites * 6 + + pEnemyGroup->pEnemyGroup->ubNumRobots * 15 + pEnemyGroup->pEnemyGroup->ubNumTanks * 20 + pEnemyGroup->pEnemyGroup->ubNumJeeps * 12; if( PlayerForceTooStrong( ubSectorID, usOffensePoints, &usDefencePoints ) ) @@ -2133,11 +2117,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 + pSector->ubNumJeeps; + ubAvailableTroops = pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumRobots + 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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( ubGarrisonSectorID, 0, (UINT8)(ubAvailableTroops / 2), 0, 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ ubDstGarrisonID ].ubComposition ); RemoveSoldiersFromGarrisonBasedOnComposition( ubSrcGarrisonID, pGroup->ubGroupSize ); gGarrisonGroup[ ubDstGarrisonID ].ubPendingGroupID = pGroup->ubGroupID; @@ -2242,13 +2226,14 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); pSector->ubNumAdmins = (UINT8)(pSector->ubNumAdmins + pGroup->pEnemyGroup->ubNumAdmins); pSector->ubNumTroops = (UINT8)(pSector->ubNumTroops + pGroup->pEnemyGroup->ubNumTroops); pSector->ubNumElites = (UINT8)(pSector->ubNumElites + pGroup->pEnemyGroup->ubNumElites); + pSector->ubNumRobots = (UINT8)(pSector->ubNumRobots + pGroup->pEnemyGroup->ubNumRobots); 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->pEnemyGroup->ubNumJeeps, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX ); + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + pGroup->pEnemyGroup->ubNumRobots, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX ); #endif if( IsThisSectorASAMSector( pGroup->ubSectorX, pGroup->ubSectorY, 0 ) ) @@ -2322,13 +2307,14 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); pPatrolGroup->pEnemyGroup->ubNumTroops += pGroup->pEnemyGroup->ubNumTroops; pPatrolGroup->pEnemyGroup->ubNumElites += pGroup->pEnemyGroup->ubNumElites; pPatrolGroup->pEnemyGroup->ubNumAdmins += pGroup->pEnemyGroup->ubNumAdmins; + pPatrolGroup->pEnemyGroup->ubNumRobots += pGroup->pEnemyGroup->ubNumRobots; pPatrolGroup->pEnemyGroup->ubNumTanks += 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); + + pGroup->pEnemyGroup->ubNumRobots + 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->ubNumJeeps, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + pGroup->pEnemyGroup->ubNumRobots, pPatrolGroup->ubSectorY + 'A' - 1, pPatrolGroup->ubSectorX, pPatrolGroup->ubGroupSize ); #endif if( pPatrolGroup->ubGroupSize > iMaxEnemyGroupSize ) @@ -2362,6 +2348,11 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); pGroup->pEnemyGroup->ubNumElites--; pPatrolGroup->pEnemyGroup->ubNumElites--; } + else if( pGroup->pEnemyGroup->ubNumRobots ) + { + pGroup->pEnemyGroup->ubNumRobots--; + pPatrolGroup->pEnemyGroup->ubNumRobots--; + } else if( pGroup->pEnemyGroup->ubNumTanks ) { pGroup->pEnemyGroup->ubNumTanks--; @@ -2377,6 +2368,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); Assert( pPatrolGroup->pEnemyGroup->ubNumAdmins + pPatrolGroup->pEnemyGroup->ubNumTroops + pPatrolGroup->pEnemyGroup->ubNumElites + + pPatrolGroup->pEnemyGroup->ubNumRobots + pPatrolGroup->pEnemyGroup->ubNumTanks + pPatrolGroup->pEnemyGroup->ubNumJeeps == iMaxEnemyGroupSize ); } @@ -2404,7 +2396,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->ubNumJeeps, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + pGroup->pEnemyGroup->ubNumRobots, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX ); #endif RecalculatePatrolWeight( i ); @@ -2579,7 +2571,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup ) return FALSE; } pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY-1 ) ]; - ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY-1 ) ); @@ -2595,7 +2587,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup ) return FALSE; } pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX+1, pPlayerGroup->ubSectorY ) ]; - ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX+1, pPlayerGroup->ubSectorY ) ); @@ -2611,7 +2603,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup ) return FALSE; } pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY+1 ) ]; - ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX, pPlayerGroup->ubSectorY+1 ) ); @@ -2627,7 +2619,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup ) return FALSE; } pSector = &SectorInfo[ SECTOR( pPlayerGroup->ubSectorX-1, pPlayerGroup->ubSectorY ) ]; - ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + ubNumEnemies = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; if( ubNumEnemies && pSector->ubGarrisonID != NO_GARRISON && AttemptToNoticeAdjacentGroupSucceeds() ) { HandlePlayerGroupNoticedByGarrison( pPlayerGroup, (UINT8)SECTOR( pPlayerGroup->ubSectorX-1, pPlayerGroup->ubSectorY ) ); @@ -2692,7 +2684,7 @@ void CheckEnemyControlledSector( UINT8 ubSectorID ) } } - if ( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps ) + if ( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps ) { //The sector is still controlled, so look around to see if there are any players nearby. @@ -2847,7 +2839,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 + pSector->ubNumJeeps; + iCurrentPop = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; iPriority = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bPriority; //First, remove the previous weight from the applicable field. @@ -3085,7 +3077,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->ubNumJeeps, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + pGroup->pEnemyGroup->ubNumRobots, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX, ubDstSectorY + 'A' - 1, ubDstSectorX ); #endif @@ -3145,7 +3137,7 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi } } - pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ iDstGarrisonID ].ubComposition ); pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY ); //Madd: unlimited reinforcements? @@ -3155,7 +3147,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 + pGroup->pEnemyGroup->ubNumJeeps); + ubGroupSize = (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumRobots + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps); if( ubNumExtraReinforcements ) { @@ -3235,13 +3227,13 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi } } - pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 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 + pGroup->pEnemyGroup->ubNumJeeps); + ubGroupSize = (UINT8)(pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumRobots + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps); if( ubNumExtraReinforcements ) { @@ -3307,7 +3299,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->ubNumJeeps, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + pGroup->pEnemyGroup->ubNumRobots, pGroup->ubSectorY + 'A' - 1, pGroup->ubSectorX, ubDstSectorY + 'A' - 1, ubDstSectorX ); #endif @@ -3325,7 +3317,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, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, (UINT8)iReinforcementsApproved, 0, 0, 0, 0 ); pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY ); //Madd: unlimited reinforcements? @@ -3376,7 +3368,7 @@ BOOLEAN SendReinforcementsForPatrol( INT32 iPatrolID, GROUP **pOptionalGroup ) if ( !iReinforcementsApproved ) continue; - pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0 ); + pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0, 0 ); pGroup->ubOriginalSector = (UINT8)SECTOR( ubDstSectorX, ubDstSectorY ); gPatrolGroup[ iPatrolID ].ubPendingGroupID = pGroup->ubGroupID; @@ -3384,7 +3376,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->ubNumJeeps, + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + pGroup->pEnemyGroup->ubNumRobots, ubSrcSectorY + 'A' - 1, ubSrcSectorX, ubDstSectorY + 'A' - 1, ubDstSectorX ); #endif @@ -4486,13 +4478,25 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto UINT8 stagesector0, stagesector1, stagesector2, stagesector3; UINT8 assaultsector0, assaultsector1, assaultsector2, assaultsector3; unsigned ubNumSoldiers; + UINT8 ubNumRobots = 0; 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}; + UINT8 grouptroops[4] = {0,0,0,0}; + UINT8 groupelites[4] = {0,0,0,0}; + UINT8 grouprobots[4] = {0,0,0,0}; + UINT8 grouptanks[4] = {0,0,0,0}; + UINT8 groupjeeps[4] = {0, 0, 0, 0}; + + UINT32 difficultyMod; + switch (gGameOptions.ubDifficultyLevel) + { + case DIF_LEVEL_EASY: difficultyMod = 1; break; + case DIF_LEVEL_MEDIUM: difficultyMod = 2; break; + case DIF_LEVEL_HARD: difficultyMod = 3; break; + case DIF_LEVEL_INSANE: difficultyMod = 4; break; + default: difficultyMod = 1; break; + } switch( usActionCode ) { @@ -4579,40 +4583,15 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto { for( UINT8 ubCounter = 0; ubCounter < 4; ++ubCounter ) { - grouptroops[ubCounter] = ubNumSoldiers; - groupelites[ubCounter] = 0; - grouptanks[ubCounter] = 0; - groupjeeps[ubCounter] = 0; - - if ( Random( 10 ) < gGameOptions.ubDifficultyLevel ) - { - if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) - { - grouptroops[ubCounter]--; - groupjeeps[ubCounter]++; - } - else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) - { - grouptroops[ubCounter]--; - grouptanks[ubCounter]++; - } - } - - // replace some soldiers with elites - if ( gGameOptions.ubDifficultyLevel > 0 ) - { - groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / gGameOptions.ubDifficultyLevel; - //grouptroops[ubCounter] -= groupelites[ubCounter]; - } - - totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[ubCounter], groupelites[ubCounter], grouprobots[ubCounter], groupjeeps[ubCounter], grouptanks[ubCounter], Random(10) < gGameOptions.ubDifficultyLevel); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouprobots[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } } - 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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouprobots[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouprobots[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouprobots[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -4665,35 +4644,8 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto // 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 ( Random( 10 ) < gGameOptions.ubDifficultyLevel ) - { - if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) - { - grouptroops[ubCounter]--; - groupjeeps[ubCounter]++; - } - else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) - { - grouptroops[ubCounter]--; - grouptanks[ubCounter]++; - } - } - } - - if ( gGameOptions.ubDifficultyLevel > 0 ) - { - groupelites[ubCounter] = grouptroops[ubCounter] - grouptroops[ubCounter] / gGameOptions.ubDifficultyLevel; - grouptroops[ubCounter] -= groupelites[ubCounter]; - } - - totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[ubCounter], groupelites[ubCounter], grouprobots[ubCounter], groupjeeps[ubCounter], grouptanks[ubCounter], ubNumSoldiers > 0); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouprobots[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } switch( usActionCode ) @@ -4820,10 +4772,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto break; } - 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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( stagesector0, 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( stagesector1, 0, grouptroops[1], groupelites[1], grouprobots[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( stagesector2, 0, grouptroops[2], groupelites[2], grouprobots[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( stagesector3, 0, grouptroops[3], groupelites[3], grouprobots[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -4876,51 +4828,15 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto BOOLEAN fAttack_Balime = !(SectorInfo[ SEC_L11 ].ubNumTroops > 0); BOOLEAN fAttack_Chitzena = !(SectorInfo[ SEC_L11 ].ubNumTroops > 0); - 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 - { - value2 = Random (4); - if (value2 == 0) value2 = 1; - } - - ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + value2 * 3); + ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + difficultyMod * 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]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[ubCounter], groupelites[ubCounter], grouprobots[ubCounter], groupjeeps[ubCounter], grouptanks[ubCounter], ubNumSoldiers > 0); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouprobots[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } ubSourceSectorID = SEC_M6; @@ -4929,10 +4845,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); - pGroup0 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[1], groupelites[1], grouprobots[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[2], groupelites[2], grouprobots[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouprobots[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -4964,29 +4880,8 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto // 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]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[ubCounter], groupelites[ubCounter], grouprobots[ubCounter], groupjeeps[ubCounter], grouptanks[ubCounter], ubNumSoldiers > 0); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouprobots[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); @@ -5012,10 +4907,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto assaultsector3 = SEC_H9; } - 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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouprobots[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouprobots[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouprobots[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -5047,29 +4942,8 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto // 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]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[ubCounter], groupelites[ubCounter], grouprobots[ubCounter], groupjeeps[ubCounter], grouptanks[ubCounter], ubNumSoldiers > 0); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouprobots[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } ubSourceSectorID = SEC_M6; @@ -5078,10 +4952,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); - pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouprobots[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouprobots[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouprobots[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -5112,29 +4986,8 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto // 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]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[ubCounter], groupelites[ubCounter], grouprobots[ubCounter], groupjeeps[ubCounter], grouptanks[ubCounter], ubNumSoldiers > 0); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouprobots[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } ubSourceSectorID = SEC_M2; @@ -5143,10 +4996,10 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) ubSourceSectorID = SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ); - pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouprobots[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouprobots[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouprobots[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -5178,29 +5031,8 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto // 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]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[ubCounter], groupelites[ubCounter], grouprobots[ubCounter], groupjeeps[ubCounter], grouptanks[ubCounter], ubNumSoldiers > 0); + totalusedsoldiers += grouptroops[ubCounter] + groupelites[ubCounter] + grouprobots[ubCounter] + grouptanks[ubCounter] + groupjeeps[ubCounter]; } ubSourceSectorID = SEC_H2; @@ -5210,10 +5042,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[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] ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[1], groupelites[1], grouprobots[1], grouptanks[1], groupjeeps[1] ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[2], groupelites[2], grouprobots[2], grouptanks[2], groupjeeps[2] ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops[3], groupelites[3], grouprobots[3], grouptanks[3], groupjeeps[3] ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { @@ -5262,54 +5094,16 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto ubSectorID = (UINT8)STRATEGIC_INDEX_TO_SECTOR_INFO( sWorldSectorLocationOfFirstBattle ); pSector = &SectorInfo[ ubSectorID ]; - 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 - { - value2 = Random( 4 ); - - if ( value2 == 0 ) - value2 = 1; - } - - ubNumSoldiers = (UINT8)(gubMinEnemyGroupSize + value2 * 4); + ubNumSoldiers = (UINT8)(gubMinEnemyGroupSize + difficultyMod * 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]; + InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[0], groupelites[0], grouprobots[0], groupjeeps[0], grouptanks[0], Random(10) < difficultyMod); + totalusedsoldiers += grouptroops[0] + groupelites[0] + grouprobots[0], grouptanks[0] + groupjeeps[0]; } - pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[0], groupelites[0], grouptanks[0], groupjeeps[0] ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] ); //Madd: unlimited reinforcements? if ( !gfUnlimitedTroops ) @@ -5358,33 +5152,11 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto unsigned intention = (unsigned) option2; Assert(intention < NUM_ENEMY_INTENTIONS); - UINT8 value5; - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - value5 = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - value5 = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - value5 = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - value5 = 4; - else - { - value5 = Random (4); - if (value5 == 0) value5 = 1; - } - ubNumSoldiers = ( gubMinEnemyGroupSize + - value5 * 3 + + difficultyMod * 3 + Random(HighestPlayerProgressPercentage() / 5) + Random(option1 / 5) ); - /* - ubNumSoldiers = ( gubMinEnemyGroupSize + - gGameOptions.ubDifficultyLevel * 3 + - Random(HighestPlayerProgressPercentage() / 5) + - Random(option1 / 5) - ); - */ if ( !gfUnlimitedTroops ) giReinforcementPool -= ubNumSoldiers; @@ -5407,11 +5179,14 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto soldiersThisSquad = (unsigned)gGameExternalOptions.iMaxEnemyGroupSize; } ubNumSoldiers -= soldiersThisSquad; - unsigned adminsThisSquad = 0; - unsigned troopsThisSquad = 0; - unsigned elitesThisSquad = 0; - unsigned tanksThisSquad = 0; - unsigned jeepsThisSquad = 0; + UINT8 adminsThisSquad = 0; + UINT8 troopsThisSquad = 0; + UINT8 elitesThisSquad = 0; + UINT8 robotsThisSquad = 0; + UINT8 tanksThisSquad = 0; + UINT8 jeepsThisSquad = 0; + // this is an attack group, but set it to patrol since we'll set the admin/regular/elite composition by hand here + InitializeGroup(GROUP_TYPE_PATROL, soldiersThisSquad, troopsThisSquad, elitesThisSquad, robotsThisSquad, jeepsThisSquad, tanksThisSquad, Random(10 * 100) < difficultyMod * direness); if (direness < 25) { adminsThisSquad = soldiersThisSquad * (40 + Random(20)) / 100; // 40-60% of total troopsThisSquad = soldiersThisSquad - adminsThisSquad; // The rest @@ -5429,24 +5204,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto elitesThisSquad = soldiersThisSquad - troopsThisSquad - adminsThisSquad; // The rest } Assert(adminsThisSquad + troopsThisSquad + elitesThisSquad == soldiersThisSquad); - // anv: replace one of soldiers with tank - if( ubNumSoldiers ) - { - if ( Random( 10 * 100 ) < value5 * direness ) - { - if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) - { - elitesThisSquad--; - jeepsThisSquad++; - } - else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) - { - elitesThisSquad--; - tanksThisSquad++; - } - } - } - pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, tanksThisSquad, jeepsThisSquad ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, robotsThisSquad, tanksThisSquad, jeepsThisSquad ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { pGroup0->pEnemyGroup->ubIntention = STAGE; if (groupCnt > 2) { @@ -5515,7 +5273,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, 0 ); + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, adminsThisSquad, soldiersThisSquad, elitesThisSquad, 0, 0, 0 ); if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) { pGroup0->pEnemyGroup->ubIntention = STAGE; if (groupCnt > 2) { @@ -5531,24 +5289,8 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto break; case NPC_ACTION_SEND_SOLDIERS_TO_OMERTA: - - UINT8 value6; - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - value6 = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - value6 = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - value6 = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - value6 = 4; - else - { - value6 = Random (4); - if (value6 == 0) value6 = 1; - } - 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, 0 ); //add 1 elite to normal, and 2 for hard + ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + difficultyMod * 6); //6, 12, or 18 based on difficulty. + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, ubNumSoldiers, (UINT8)(ubNumSoldiers/7), 0, 0, 0 ); //add 1 elite to normal, and 2 for hard ubNumSoldiers = (UINT8)(ubNumSoldiers + ubNumSoldiers / 7); //Madd: unlimited reinforcements @@ -5572,46 +5314,17 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto case NPC_ACTION_SEND_TROOPS_TO_SAM: ubSectorID = (UINT8)SECTOR( sSectorX, sSectorY ); - UINT8 value7; - if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_EASY ) - value7 = 1; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_MEDIUM ) - value7 = 2; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_HARD ) - value7 = 3; - else if( gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) - value7 = 4; - else - { - value7 = Random (4); - if (value7 == 0) value7 = 1; - } - ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + value7 + HighestPlayerProgressPercentage() / 15 ); - // ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel + HighestPlayerProgressPercentage() / 15 ); + ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + difficultyMod + HighestPlayerProgressPercentage() / 15 ); //Madd: unlimited reinforcements? if ( !gfUnlimitedTroops ) giReinforcementPool -= ubNumSoldiers; - // anv: replace one of soldiers with tank - if( ubNumSoldiers ) - { - if ( Random( 10 * 100 ) < value7 * HighestPlayerProgressPercentage( ) ) - { - if ( gGameExternalOptions.fArmyUsesJeepsInAttacks && ASDSoldierUpgradeToJeep( ) ) - { - --ubNumSoldiers; - ++ubNumJeeps; - } - else if ( gGameExternalOptions.fArmyUsesTanksInAttacks && ASDSoldierUpgradeToTank( ) ) - { - --ubNumSoldiers; - ++ubNumTanks; - } - } - } + UINT8 ubNumTroops, ubNumElites; + // set the type to patrol as we're manually tuning the group composition here (100% elites + ASD upgrades) + InitializeGroup(GROUP_TYPE_PATROL, ubNumSoldiers, ubNumTroops, ubNumElites, ubNumRobots, ubNumJeeps, ubNumTanks, Random(10*100) < difficultyMod * HighestPlayerProgressPercentage()); giReinforcementPool = max( giReinforcementPool, 0 ); - pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, 0, ubNumSoldiers, ubNumTanks, ubNumJeeps ); + pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, 0, ubNumSoldiers, ubNumRobots, ubNumTanks, ubNumJeeps ); MoveSAIGroupToSector( &pGroup, ubSectorID, STAGE, REINFORCEMENTS ); // WANNE: This should fix the assertion in UC in the cutscene! @@ -5886,16 +5599,16 @@ void InvestigateSector( UINT8 ubSectorID ) switch( i ) { case 0: //NORTH - AddEnemiesToBattle( NULL, INSERTION_CODE_NORTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_NORTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, 0, TRUE ); break; case 1: //EAST - AddEnemiesToBattle( NULL, INSERTION_CODE_EAST, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_EAST, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, 0, TRUE ); break; case 2: //SOUTH - AddEnemiesToBattle( NULL, INSERTION_CODE_SOUTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_SOUTH, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, 0, TRUE ); break; case 3: //WEST - AddEnemiesToBattle( NULL, INSERTION_CODE_WEST, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, TRUE ); + AddEnemiesToBattle( NULL, INSERTION_CODE_WEST, ubAdmins[i], ubTroops[i], ubElites[i], 0, 0, 0, TRUE ); break; } } @@ -6192,7 +5905,7 @@ void RequestHighPriorityGarrisonReinforcements( INT32 iGarrisonID, UINT8 ubSoldi if ( giReinforcementPool > 0 ) { pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), - 0, min( ubSoldiersRequested, giReinforcementPool ), 0, 0, 0 ); + 0, min( ubSoldiersRequested, giReinforcementPool ), 0, 0, 0, 0 ); pGroup->ubMoveType = ONE_WAY; pGroup->pEnemyGroup->ubIntention = REINFORCEMENTS; gGarrisonGroup[ iGarrisonID ].ubPendingGroupID = pGroup->ubGroupID; @@ -6230,7 +5943,7 @@ void MassFortifyTowns() for( i = 0; i < giGarrisonArraySize; i++ ) { pSector = &SectorInfo[ gGarrisonGroup[ i ].ubSectorID ]; - ubNumTroops = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + ubNumTroops = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; ubDesiredTroops = (UINT8)gArmyComp[ gGarrisonGroup[ i ].ubComposition ].bDesiredPopulation; if( ubNumTroops < ubDesiredTroops ) @@ -6269,7 +5982,7 @@ void RenderAIViewerGarrisonInfo( INT32 x, INT32 y, SECTORINFO *pSector ) { INT32 iDesired, iSurplus; iDesired = gArmyComp[ gGarrisonGroup[ pSector->ubGarrisonID ].ubComposition ].bDesiredPopulation; - iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps - iDesired; + iSurplus = pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps - iDesired; SetFontForeground( FONT_WHITE ); if( iSurplus >= 0 ) { @@ -6322,11 +6035,11 @@ BOOLEAN GarrisonCanProvideMinimumReinforcements( INT32 iGarrisonID ) SECTORINFO *pSector; UINT8 ubSectorX, ubSectorY; - 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 ]; - iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; iDesired = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation; if( iAvailable - iDesired >= gubMinEnemyGroupSize ) @@ -6350,7 +6063,7 @@ BOOLEAN GarrisonRequestingMinimumReinforcements( INT32 iGarrisonID ) INT32 iDesired; 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( gGarrisonGroup[ iGarrisonID ].ubPendingGroupID ) { @@ -6358,7 +6071,7 @@ BOOLEAN GarrisonRequestingMinimumReinforcements( INT32 iGarrisonID ) } pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; - iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks + pSector->ubNumJeeps; + iAvailable = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; iDesired = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation; if( iDesired - iAvailable >= gubMinEnemyGroupSize ) @@ -6409,8 +6122,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 + pGroup->pEnemyGroup->ubNumJeeps + - pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks + pSector->ubNumJeeps; + iTotal = pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumRobots + pGroup->pEnemyGroup->ubNumTanks + pGroup->pEnemyGroup->ubNumJeeps + + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumRobots + pSector->ubNumTanks + pSector->ubNumJeeps; if( iTotal <= iMaxEnemyGroupSize ) { return; @@ -6522,6 +6235,32 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic8"); iTotal = 0; } } + else if ( pGroup->pEnemyGroup->ubNumRobots ) + { + if ( pGroup->pEnemyGroup->ubNumRobots < iTotal ) + { + iTotal -= pGroup->pEnemyGroup->ubNumRobots; + pGroup->pEnemyGroup->ubNumRobots = 0; + } + else + { + pGroup->pEnemyGroup->ubNumRobots -= (UINT8)iTotal; + iTotal = 0; + } + } + else if ( pSector->ubNumRobots ) + { + if ( pSector->ubNumRobots < iTotal ) + { + iTotal -= pSector->ubNumRobots; + pSector->ubNumRobots = 0; + } + else + { + pSector->ubNumRobots -= (UINT8)iTotal; + iTotal = 0; + } + } else if ( pGroup->pEnemyGroup->ubNumJeeps ) { if ( pGroup->pEnemyGroup->ubNumJeeps < iTotal ) @@ -7295,4 +7034,58 @@ GROUP* FindPendingGroupForGarrisonSector( UINT8 ubSectorID ) } } return NULL; -} \ No newline at end of file +} + +void InitializeGroup( const GROUP_TYPE groupType, const UINT8 groupSize, UINT8 &troopCount, UINT8 &eliteCount, UINT8 &robotCount, UINT8 &jeepCount, UINT8 &tankCount, const BOOLEAN asdUpgrade ) +{ + troopCount = groupSize; + eliteCount = 0; + robotCount = 0; + jeepCount = 0; + tankCount = 0; + + UINT32 difficultyMod = 0; + switch (gGameOptions.ubDifficultyLevel) + { + case DIF_LEVEL_EASY: difficultyMod = 1; break; + case DIF_LEVEL_MEDIUM: difficultyMod = 2; break; + case DIF_LEVEL_HARD: difficultyMod = 3; break; + case DIF_LEVEL_INSANE: difficultyMod = 4; break; + default: difficultyMod = 1; break; + } + + if ( asdUpgrade && groupSize > 0 ) + { + const BOOLEAN canUpgradeToJeep = (groupType == GROUP_TYPE_ATTACK && gGameExternalOptions.fArmyUsesJeepsInAttacks) + || (groupType == GROUP_TYPE_PATROL && gGameExternalOptions.fArmyUsesJeepsInPatrols); + const BOOLEAN canUpgradeToTank = (groupType == GROUP_TYPE_ATTACK && gGameExternalOptions.fArmyUsesTanksInAttacks) + || (groupType == GROUP_TYPE_PATROL && gGameExternalOptions.fArmyUsesTanksInPatrols); + const BOOLEAN canUpgradeToRobot = (groupType == GROUP_TYPE_ATTACK && gGameExternalOptions.fArmyUsesRobotsInAttacks) + || (groupType == GROUP_TYPE_PATROL && gGameExternalOptions.fArmyUsesRobotsInPatrols); + if ( canUpgradeToJeep && ASDSoldierUpgradeToJeep( ) ) + { + troopCount--; + jeepCount++; + } + else if ( canUpgradeToTank && ASDSoldierUpgradeToTank( ) ) + { + troopCount--; + tankCount++; + } + + if ( canUpgradeToRobot && ASDSoldierUpgradeToRobot() ) + { + const int numRobots = Random(difficultyMod); + troopCount -= numRobots; + robotCount += numRobots; + } + } + + // replace some soldiers with elites for attack groups + if ( groupType == GROUP_TYPE_ATTACK && difficultyMod > 0 ) + { + eliteCount += troopCount - troopCount / difficultyMod; + troopCount -= eliteCount; + } + +} diff --git a/Strategic/Strategic AI.h b/Strategic/Strategic AI.h index 7176e0dc..7c5541dd 100644 --- a/Strategic/Strategic AI.h +++ b/Strategic/Strategic AI.h @@ -75,7 +75,13 @@ void TagSAIGroupWithGracePeriod( GROUP *pGroup ); BOOLEAN PermittedToFillPatrolGroup( INT32 iPatrolID ); +enum GROUP_TYPE +{ + GROUP_TYPE_ATTACK, + GROUP_TYPE_PATROL +}; +void InitializeGroup(const GROUP_TYPE groupType, const UINT8 groupSize, UINT8 &troopCount, UINT8 &eliteCount, UINT8 &robotCount, UINT8 &jeepCount, UINT8 &tankCount, const BOOLEAN asdUpgrade); extern BOOLEAN gfDisplayStrategicAILogs; extern BOOLEAN gfFirstBattleMeanwhileScenePending; diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index fe5a5302..1ea80d75 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -706,7 +706,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, UINT8 ubNumJeeps ) +GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumRobots, UINT8 ubNumTanks, UINT8 ubNumJeeps ) { GROUP *pNew; AssertMsg( uiSector >= 0 && uiSector <= 255, String( "CreateNewEnemyGroup with out of range value of %d", uiSector ) ); @@ -717,7 +717,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 + ubNumJeeps > gGameExternalOptions.iMaxEnemyGroupSize ) + while ( ubNumAdmins + ubNumTroops + ubNumElites + ubNumRobots + ubNumTanks + ubNumJeeps > gGameExternalOptions.iMaxEnemyGroupSize ) { if (ubNumTroops) { @@ -731,6 +731,10 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin { ubNumElites--; } + else if (ubNumRobots) + { + ubNumRobots--; + } else if (ubNumTanks) { ubNumTanks--; @@ -752,9 +756,10 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin pNew->pEnemyGroup->ubNumAdmins = ubNumAdmins; pNew->pEnemyGroup->ubNumTroops = ubNumTroops; pNew->pEnemyGroup->ubNumElites = ubNumElites; + pNew->pEnemyGroup->ubNumRobots = ubNumRobots; pNew->pEnemyGroup->ubNumTanks = ubNumTanks; pNew->pEnemyGroup->ubNumJeeps = ubNumJeeps; - pNew->ubGroupSize = (UINT8)(ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks + ubNumJeeps); + pNew->ubGroupSize = (UINT8)(ubNumAdmins + ubNumTroops + ubNumElites + ubNumRobots + 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 76f99764..e5fef61a 100644 --- a/Strategic/Strategic Movement.h +++ b/Strategic/Strategic Movement.h @@ -64,12 +64,14 @@ typedef struct ENEMYGROUP UINT8 ubNumTroops; //number of regular troops in the group UINT8 ubNumElites; //number of elite troops in the group UINT8 ubNumAdmins; //number of administrators in the group + UINT8 ubNumRobots; //number of enemy robots in the group UINT8 ubLeaderProfileID; //could be Mike, maybe the warden... someone new, but likely nobody. UINT8 ubPendingReinforcements;//This group is waiting for reinforcements before attacking or attempting to fortify newly aquired sector. UINT8 ubAdminsInBattle; //number of administrators in currently in battle. UINT8 ubIntention; //the type of group this is: patrol, assault, spies, etc. UINT8 ubTroopsInBattle; //number of soldiers currently in battle. UINT8 ubElitesInBattle; //number of elite soldiers currently in battle. + UINT8 ubRobotsInBattle; //number of enemy robots currently in battle. // WDS - New AI UINT8 ubNumTanks; UINT8 ubTanksInBattle; @@ -196,7 +198,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 ubNumTanksm, UINT8 ubNumJeeps ); +GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumRobots, UINT8 ubNumTanks, UINT8 ubNumJeeps ); GROUP* CreateNewMilitiaGroupDepartingFromSector( UINT32 uiSector, UINT8& arusNumAdmins, UINT8& arusNumTroops, UINT8& arusNumElites ); diff --git a/Strategic/Strategic Status.cpp b/Strategic/Strategic Status.cpp index f60186ec..e84f9d4a 100644 --- a/Strategic/Strategic Status.cpp +++ b/Strategic/Strategic Status.cpp @@ -428,6 +428,7 @@ INT8 SoldierClassToRankIndex( UINT8 ubSoldierClass ) case SOLDIER_CLASS_BANDIT: bRankIndex = 0; break; case SOLDIER_CLASS_ELITE: bRankIndex = 2; break; case SOLDIER_CLASS_ARMY: bRankIndex = 1; break; + case SOLDIER_CLASS_ROBOT: bRankIndex = 2; break; default: // this happens when an NPC joins the enemy team (e.g. Conrad, Iggy, Mike) diff --git a/Strategic/UndergroundInit.cpp b/Strategic/UndergroundInit.cpp index df4735f5..a5ea0904 100644 --- a/Strategic/UndergroundInit.cpp +++ b/Strategic/UndergroundInit.cpp @@ -90,6 +90,7 @@ BOOLEAN LuaUnderground::InitializeSectorList() sectorData.getValue("numElites", s->ubNumElites); sectorData.getValue("numTanks", s->ubNumTanks); sectorData.getValue("numJeeps", s->ubNumJeeps ); + sectorData.getValue("numRobots", s->ubNumRobots); sectorData.getValue("numBloodcats", s->ubNumBloodcats); sectorData.getValue("numCreatures", s->ubNumCreatures); @@ -108,6 +109,7 @@ BOOLEAN LuaUnderground::InitializeSectorList() 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\tRobots: " << static_cast(s->ubNumRobots) << 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/Tactical/End Game.cpp b/Tactical/End Game.cpp index af9c9894..93e5da86 100644 --- a/Tactical/End Game.cpp +++ b/Tactical/End Game.cpp @@ -318,6 +318,7 @@ void DoneFadeOutKilledQueen( void ) SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubAdminsInBattle = 0; SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTroopsInBattle = 0; SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubElitesInBattle = 0; + SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubRobotsInBattle = 0; SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTanksInBattle = 0; SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubJeepsInBattle = 0; diff --git a/Tactical/Enemy Soldier Save.cpp b/Tactical/Enemy Soldier Save.cpp index ea39d24a..b5de4fce 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, UINT8 *pubNumJeeps ); +BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumRobots, 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, ubNumJeeps = 0; - UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks, ubStrategicJeeps; + UINT8 ubNumRobots = 0, ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0, ubNumJeeps = 0; + UINT8 ubStrategicRobots, ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks, ubStrategicJeeps; gfRestoringEnemySoldiersFromTempFile = TRUE; @@ -256,6 +256,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile() ubStrategicAdmins = pSector->ubNumAdmins; ubStrategicTanks = pSector->ubNumTanks; ubStrategicJeeps = pSector->ubNumJeeps; + ubStrategicRobots = pSector->ubNumRobots; ubStrategicCreatures = pSector->ubNumCreatures; } else @@ -263,7 +264,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile() SECTORINFO *pSector; pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; ubStrategicCreatures = pSector->ubNumCreatures; - GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks, &ubStrategicJeeps ); + GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicRobots, &ubStrategicTanks, &ubStrategicJeeps ); } for( i = 0; i < slots; i++ ) @@ -370,6 +371,16 @@ BOOLEAN LoadEnemySoldiersFromTempFile() } } break; + case SOLDIER_CLASS_ROBOT: + if (ENEMYROBOT(curr->pBasicPlacement)) + { + ubNumRobots++; + if (ubNumRobots < ubStrategicRobots) + { + AddPlacementToWorld(curr); + } + } + break; } break; } @@ -397,14 +408,15 @@ 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 || ubStrategicJeeps > ubNumJeeps ) + if ( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicRobots > ubNumRobots || ubStrategicTanks > ubNumTanks || ubStrategicJeeps > ubNumJeeps ) { ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0; ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0; + ubStrategicRobots = ( ubStrategicRobots > ubNumRobots ) ? ubStrategicRobots - ubNumRobots : 0; ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0; ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0; ubStrategicJeeps = (ubStrategicJeeps > ubNumJeeps) ? ubStrategicJeeps - ubNumJeeps : 0; - AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks, ubStrategicJeeps ); + AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicRobots, ubStrategicTanks, ubStrategicJeeps ); } if( ubStrategicCreatures > ubNumCreatures ) @@ -688,8 +700,8 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() #endif INT8 bSectorZ; UINT8 ubSectorID; - UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0, ubNumJeeps = 0; - UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks, ubStrategicJeeps; + UINT8 ubNumRobots = 0, ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0, ubNumJeeps = 0; + UINT8 ubStrategicRobots = 0, ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks, ubStrategicJeeps; gfRestoringEnemySoldiersFromTempFile = TRUE; @@ -730,16 +742,17 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() ubNumAdmins = pSector->ubNumAdmins; ubNumTanks = pSector->ubNumTanks; ubNumJeeps = pSector->ubNumJeeps; + ubNumRobots = pSector->ubNumRobots; ubNumCreatures = pSector->ubNumCreatures; } if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) { // Get the number of enemies form the temp file - CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicElites, &ubStrategicTroops, &ubStrategicAdmins, &ubStrategicCreatures, &ubStrategicTanks, &ubStrategicJeeps ); + CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicRobots, &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 || ubStrategicJeeps != ubNumJeeps ) + if ( ubStrategicRobots != ubNumRobots || ubStrategicElites != ubNumElites || ubStrategicTroops != ubNumTroops || ubStrategicAdmins != ubNumAdmins || ubStrategicCreatures != ubNumCreatures || ubStrategicTanks != ubNumTanks || ubStrategicJeeps != ubNumJeeps ) { //remove the file RemoveEnemySoldierTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); @@ -748,7 +761,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() } //reset - ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = ubNumTanks = ubNumJeeps = 0; + ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = ubNumTanks = ubNumJeeps = ubNumRobots = 0; //Open the file for reading @@ -888,6 +901,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() ubStrategicElites = pSector->ubNumElites; ubStrategicTroops = pSector->ubNumTroops; ubStrategicAdmins = pSector->ubNumAdmins; + ubStrategicRobots = pSector->ubNumRobots; ubStrategicTanks = pSector->ubNumTanks; ubStrategicJeeps = pSector->ubNumJeeps; ubStrategicCreatures = pSector->ubNumCreatures; @@ -897,7 +911,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() SECTORINFO *pSector; pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; ubStrategicCreatures = pSector->ubNumCreatures; - GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks, &ubStrategicJeeps ); + GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicRobots, &ubStrategicTanks, &ubStrategicJeeps ); } for( i = 0; i < slots; i++ ) @@ -990,7 +1004,17 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() ++ubNumJeeps; if ( ubNumJeeps <= ubStrategicJeeps ) { - //def: AddPlacementToWorld( curr ); +//def: AddPlacementToWorld( curr ); + } + } + break; + case SOLDIER_CLASS_ROBOT: + if ( ENEMYROBOT( curr->pBasicPlacement ) ) + { + ubNumRobots++; + if (ubNumRobots <= ubStrategicRobots) + { +//def: AddPlacementToWorld( curr ); } } break; @@ -1019,14 +1043,15 @@ 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 || ubStrategicJeeps > ubNumJeeps ) + if ( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicRobots > ubNumRobots || ubStrategicTanks > ubNumTanks || ubStrategicJeeps > ubNumJeeps ) { ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0; ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0; + ubStrategicRobots = ( ubStrategicRobots > ubNumRobots ) ? ubStrategicRobots - ubNumRobots : 0; ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0; ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0; ubStrategicJeeps = (ubStrategicJeeps > ubNumJeeps) ? ubStrategicJeeps - ubNumJeeps : 0; - AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks, ubStrategicJeeps ); + AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicRobots, ubStrategicTanks, ubStrategicJeeps ); } if( ubStrategicCreatures > ubNumCreatures ) @@ -1618,7 +1643,7 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY -BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) +BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumRobots, UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks, UINT8 *pubNumJeeps ) { // SOLDIERINITNODE *curr; SOLDIERCREATE_STRUCT tempDetailedPlacement; @@ -1638,6 +1663,7 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( // UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures; //make sure the variables are initialized + *pubNumRobots = 0; *pubNumElites = 0; *pubNumRegulars = 0; *pubNumAdmins = 0; @@ -1817,6 +1843,12 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( (*pubNumJeeps)++; } break; + case SOLDIER_CLASS_ROBOT: + if ( ENEMYROBOT( (&tempDetailedPlacement) ) ) + { + (*pubNumRobots)++; + } + break; } /* while( curr ) diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index c5c33560..58f51ab1 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -1195,17 +1195,16 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent ) return( GAME_SCREEN ); } - usRandom = 12;// (UINT16)Random( 20 ); - if( usRandom < 5 ) - pSoldier = TacticalCreateAdministrator(); - else if( usRandom < 15 ) - pSoldier = TacticalCreateArmyTroop(); - else if ( usRandom < 12 ) - pSoldier = TacticalCreateEnemyTank( ); - else if ( usRandom < 15 ) - pSoldier = TacticalCreateEnemyJeep( ); - else - pSoldier = TacticalCreateEliteEnemy( ); + usRandom = 1;// (UINT16)Random( 6 ); + switch (usRandom) + { + case 0: pSoldier = TacticalCreateAdministrator(); break; + case 1: pSoldier = TacticalCreateArmyTroop(); break; + case 2: pSoldier = TacticalCreateEliteEnemy(); break; + case 3: pSoldier = TacticalCreateEnemyTank(); break; + case 4: pSoldier = TacticalCreateEnemyJeep(); break; + case 5: pSoldier = TacticalCreateEnemyRobot(); break; + } //Add soldier strategic info, so it doesn't break the counters! if( pSoldier ) @@ -1218,6 +1217,7 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent ) 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; + case SOLDIER_CLASS_ROBOT: pSector->ubNumRobots++; pSector->ubRobotsInBattle++; break; case SOLDIER_CLASS_TANK: pSector->ubNumTanks++; pSector->ubTanksInBattle++; break; case SOLDIER_CLASS_JEEP: pSector->ubNumJeeps++; pSector->ubJeepsInBattle++; break; } @@ -1232,6 +1232,7 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent ) 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; + case SOLDIER_CLASS_ROBOT: pSector->ubNumRobots++; pSector->ubRobotsInBattle++; break; case SOLDIER_CLASS_TANK: pSector->ubNumTanks++; pSector->ubTanksInBattle++; break; case SOLDIER_CLASS_JEEP: pSector->ubNumJeeps++; pSector->ubJeepsInBattle++; break; } diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index c6e50596..335da71c 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -88,7 +88,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 EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp, BOOLEAN fTank = TRUE ); +void EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp ); void ChooseKitsForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bKitClass ); void ChooseMiscGearForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bMiscClass ); @@ -248,13 +248,14 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 return; } - if ( ARMED_VEHICLE( pp ) ) + if ( ARMED_VEHICLE( pp ) || ENEMYROBOT( pp ) ) { - EquipArmouredVehicle( pp, TANK( pp ) ); + EquipArmouredVehicle( pp ); return; } - Assert( (bSoldierClass >= SOLDIER_CLASS_NONE) && (bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA) || bSoldierClass == SOLDIER_CLASS_TANK || bSoldierClass == SOLDIER_CLASS_JEEP ); + // rftr: enemy tanks, jeeps, and robots would have early exited above + Assert( (bSoldierClass >= SOLDIER_CLASS_NONE) && (bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA) ); Assert( ( bEquipmentRating >= 0 ) && ( bEquipmentRating <= 4 ) ); // equipment level is modified by 1/10 of the difficulty percentage, -5, so it's between -5 to +5 @@ -3253,12 +3254,12 @@ UINT16 SelectStandardArmyGun( UINT8 uiGunLevel, INT8 bSoldierClass ) -void EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp, BOOLEAN fTank ) +void EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp ) { // tanks get special equipment, and they drop nothing (MGs are hard-mounted & non-removable) // tanks get a main cannon and a MG, other vehicles just get the MG - if ( fTank ) + if ( TANK(pp) ) { CreateItem( TANK_CANNON, ( INT8 )( 80 + Random( 21 ) ), &( pp->Inv[ HANDPOS ]) ); pp->Inv[ HANDPOS ].fFlags |= OBJECT_UNDROPPABLE; @@ -3278,7 +3279,13 @@ void EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp, BOOLEAN fTank ) gTempObject.fFlags |= OBJECT_UNDROPPABLE; PlaceObjectInSoldierCreateStruct( pp, &gTempObject ); } - else + else if ( COMBAT_JEEP(pp) ) + { + // machine gun + CreateItems( MINIMI, (INT8)(80 + Random( 21 )), 1, &(pp->Inv[HANDPOS]) ); + pp->Inv[HANDPOS].fFlags |= OBJECT_UNDROPPABLE; + } + else if ( ENEMYROBOT(pp) ) { // machine gun CreateItems( MINIMI, (INT8)(80 + Random( 21 )), 1, &(pp->Inv[HANDPOS]) ); diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 57474ff5..509e9e7f 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -3243,7 +3243,7 @@ void SwapObjs(SOLDIERTYPE* pSoldier, int leftSlot, int rightSlot, BOOLEAN fPerma { SwapObjs(&pSoldier->inv[ leftSlot ], &pSoldier->inv[ rightSlot ]); - if ( fPermanent && !ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 for current tank don't go further as it lead to invalid animation + if ( fPermanent && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( 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); @@ -9078,7 +9078,7 @@ void CheckEquipmentForDamage( SOLDIERTYPE *pSoldier, INT32 iDamage ) BOOLEAN fBlowsUp; UINT8 ubNumberOfObjects; - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { return; } diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index 617eea44..781a2a82 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -2049,7 +2049,7 @@ BOOLEAN CalculateSoldierZPos( SOLDIERTYPE * pSoldier, UINT8 ubPosType, FLOAT * p ubPosType = TORSO_TARGET_POS; } } - else if ( ARMED_VEHICLE( pSoldier ) ) + else if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { // high up! //ubPosType = HEAD_TARGET_POS; diff --git a/Tactical/LogicalBodyTypes/FilterDB.cpp b/Tactical/LogicalBodyTypes/FilterDB.cpp index 8e848fdc..b0df0128 100644 --- a/Tactical/LogicalBodyTypes/FilterDB.cpp +++ b/Tactical/LogicalBodyTypes/FilterDB.cpp @@ -350,7 +350,8 @@ namespace LogicalBodyTypes { SOLDIER_CLASS_ZOMBIE, SOLDIER_CLASS_TANK, SOLDIER_CLASS_JEEP, - SOLDIER_CLASS_BANDIT + SOLDIER_CLASS_BANDIT, + SOLDIER_CLASS_ROBOT ); /***************************************** diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index f7c08f38..985c225d 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -7265,16 +7265,16 @@ void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { SECTORINFO *pSectorInfo = &(SectorInfo[SECTOR( sMapX, sMapY )]); - pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = pSectorInfo->ubNumJeeps = 0; - pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = pSectorInfo->ubJeepsInBattle = 0; + pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = pSectorInfo->ubNumJeeps = pSectorInfo->ubNumRobots = 0; + pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = pSectorInfo->ubJeepsInBattle = pSectorInfo->ubRobotsInBattle = 0; } else { UNDERGROUND_SECTORINFO *pSectorInfo; pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ ); - pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = pSectorInfo->ubNumJeeps = 0; - pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = pSectorInfo->ubJeepsInBattle = 0; + pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = pSectorInfo->ubNumJeeps = pSectorInfo->ubNumRobots = 0; + pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = pSectorInfo->ubJeepsInBattle = pSectorInfo->ubRobotsInBattle = 0; } } @@ -10941,7 +10941,7 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue ) { enemysidestrength += pSoldier->GetSurrenderStrength(); - if ( pSoldier->ubProfile != NO_PROFILE || ARMED_VEHICLE(pSoldier) ) + if ( pSoldier->ubProfile != NO_PROFILE || ARMED_VEHICLE(pSoldier) || ENEMYROBOT(pSoldier) ) fNoSurrender = TRUE; } } diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index 9d30c051..29de6922 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -2594,7 +2594,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 bAimTime, } } - 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 + if ( AM_A_ROBOT( pSoldier ) || ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) || ubForceRaiseGunCost == 2 )//dnl ch64 300813 robots and tanks cannot do this //dnl ch69 150913 need option to override raise gun cost { fAddingRaiseGunCost = FALSE; } @@ -2968,7 +2968,7 @@ void DeductAmmo( SOLDIERTYPE *pSoldier, OBJECTTYPE* pObj ) { // tanks never run out of MG ammo! // unlimited cannon ammo is handled in AI - if ( ARMED_VEHICLE( pSoldier ) && !Item[pObj->usItem].cannon ) + if ( (ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier )) && !Item[pObj->usItem].cannon ) return; if ( Item[pObj->usItem].cannon ) @@ -4432,7 +4432,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 ( ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier ) || ENEMYROBOT( pSoldier ) ) return 0; ////////////////////////////////////////////////////////////////////////////// // THE BASIC COST FOR HOLDING THE GUN RAISED (per AP) @@ -4573,7 +4573,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 ( ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier ) || ENEMYROBOT( pSoldier ) ) return 0; ////////////////////////////////////////////////////////////////////////////// // THE GUN RECOIL KICK ENERGY COST diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index 9e0494e4..2fae654c 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -4004,6 +4004,9 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse ) // SANDRO - experimental - more specific statistics of mercs switch(pSoldier->ubSoldierClass) { + case SOLDIER_CLASS_ROBOT: + gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsOthers++; + break; case SOLDIER_CLASS_ELITE : gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsElites++; break; diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 4ff92ca7..b44492f2 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -16670,7 +16670,7 @@ UINT32 SOLDIERTYPE::GetSurrenderStrength( ) value = value * (5 + sqrt( (double)max( 1, this->aiData.bMorale ) )) / 15; // adjust for type of soldier - if ( this->ubSoldierClass == SOLDIER_CLASS_ELITE || this->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA ) + if ( this->ubSoldierClass == SOLDIER_CLASS_ELITE || this->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA || this->ubSoldierClass == SOLDIER_CLASS_ROBOT ) value *= 1.5f; else if ( this->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR || this->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA || this->ubSoldierClass == SOLDIER_CLASS_BANDIT ) value *= 0.75f; @@ -16720,8 +16720,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 ) { - // armed vehicles cannot be captured - if ( ARMED_VEHICLE(this) ) + // armed vehicles and robots cannot be captured + if ( ARMED_VEHICLE(this) || ENEMYROBOT(this) ) return FALSE; // enemies can be captured @@ -19346,7 +19346,7 @@ BOOLEAN SOLDIERTYPE::CanMedicAI( ) return FALSE; // this is not for tanks - if ( ARMED_VEHICLE( this ) ) + if ( ARMED_VEHICLE( this ) || ENEMYROBOT( this ) ) return FALSE; if ( HAS_SKILL_TRAIT( this, DOCTOR_NT ) ) @@ -19378,7 +19378,7 @@ BOOLEAN SOLDIERTYPE::AIDoctorFriend( ) return FALSE; // this is not for tanks - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) return FALSE; // if this guy is wounded, heal him (should always be the case, otherwise this function was called needlessly) @@ -21389,6 +21389,10 @@ UINT8 SOLDIERTYPE::GetTurncoatConvinctionChance( UINT16 usID, INT16 sApproach ) || pSoldier->bTeam != ENEMY_TEAM ) return 0; + // enemy robots can't be turncoats + if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ROBOT) + return 0; + if ( this->stats.bLife < OKLIFE ) return 0; @@ -23363,7 +23367,7 @@ BOOLEAN SOLDIERTYPE::IsValidShotFromHip( INT16 bAimTime, INT32 iTrgGridNo ) return(FALSE); } // robots and tanks cannot do this - if ( AM_A_ROBOT( this ) || ARMED_VEHICLE( this ) )//dnl ch64 300813 + if ( AM_A_ROBOT( this ) || ARMED_VEHICLE( this ) || ENEMYROBOT( this ) )//dnl ch64 300813 { return(FALSE); } @@ -23415,7 +23419,7 @@ BOOLEAN SOLDIERTYPE::IsValidPistolFastShot( INT16 bAimTime, INT32 iTrgGridNo ) return(FALSE); } // robots and tanks cannot do this - if ( AM_A_ROBOT( this ) || ARMED_VEHICLE( this ) )//dnl ch64 300813 + if ( AM_A_ROBOT( this ) || ARMED_VEHICLE( this ) || ENEMYROBOT( this ) )//dnl ch64 300813 { return(FALSE); } diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 76f86371..1c19fcff 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -337,6 +337,7 @@ enum SOLDIER_CLASS_TANK, SOLDIER_CLASS_JEEP, SOLDIER_CLASS_BANDIT, + SOLDIER_CLASS_ROBOT, SOLDIER_CLASS_MAX, }; diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index ccff4ced..550b71bb 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -613,9 +613,9 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * pCreateStruct->fPlayerPlan = 0; } - if ( is_networked && ARMED_VEHICLE( pCreateStruct ) ) + if ( is_networked && (ARMED_VEHICLE( pCreateStruct ) || ENEMYROBOT( pCreateStruct )) ) { - ScreenMsg( FONT_YELLOW, MSG_MPSYSTEM, L"skipping tank"); + ScreenMsg( FONT_YELLOW, MSG_MPSYSTEM, L"skipping tank/jeep/robot"); return NULL; } } @@ -730,6 +730,13 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * break; } + + // enemy robot special case + if (pCreateStruct->ubBodyType == ROBOTNOWEAPON && pCreateStruct->ubSoldierClass == SOLDIER_CLASS_ROBOT) + { + Soldier.bTeam = ENEMY_TEAM; + } + } } else @@ -826,7 +833,7 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * // Flugente: disease can affect a soldier's health // not for us, and not for individual militia (their health is affected by their hourly healing instead) - if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic && Soldier.bTeam != OUR_TEAM && Soldier.bTeam != CREATURE_TEAM && !ARMED_VEHICLE((&Soldier)) && + if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic && Soldier.bTeam != OUR_TEAM && Soldier.bTeam != CREATURE_TEAM && !ARMED_VEHICLE((&Soldier)) && !ENEMYROBOT((&Soldier)) && !( Soldier.bTeam == MILITIA_TEAM && gGameExternalOptions.fIndividualMilitia && gGameExternalOptions.fIndividualMilitia_ManageHealth ) ) { UINT8 sector = SECTOR( Soldier.sSectorX, Soldier.sSectorY ); @@ -1756,7 +1763,7 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT // Flugente: soldier profiles // silversurfer: Don't replace tanks! - if ( !ARMED_VEHICLE( pCreateStruct ) ) + if ( !ARMED_VEHICLE( pCreateStruct ) && !ENEMYROBOT( pCreateStruct ) ) { MILITIA militia; if ( GetMilitia( pSoldier->usIndividualMilitiaID, &militia ) ) @@ -2556,6 +2563,7 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B } break; + case SOLDIER_CLASS_ROBOT: case SOLDIER_CLASS_TANK: case SOLDIER_CLASS_JEEP: pp->bExpLevel = bp->bRelativeAttributeLevel; @@ -3241,6 +3249,47 @@ SOLDIERTYPE* TacticalCreateEnemyJeep( ) return(pSoldier); } +// rftr: enemy robots +SOLDIERTYPE* TacticalCreateEnemyRobot() +{ + BASIC_SOLDIERCREATE_STRUCT bp; + SOLDIERCREATE_STRUCT pp; + UINT8 ubID; + SOLDIERTYPE * pSoldier; + + if ( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI ) + { + pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ROBOT ); + + 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 = AGGRESSIVE; + bp.ubBodyType = ROBOTNOWEAPON; + bp.ubSoldierClass = SOLDIER_CLASS_ROBOT; + 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; + + pSoldier->stats.bLifeMax = 80; + pSoldier->stats.bLife = pSoldier->stats.bLifeMax; + } + + return(pSoldier); +} + + //USED BY STRATEGIC AI and AUTORESOLVE SOLDIERTYPE* TacticalCreateZombie() { diff --git a/Tactical/Soldier Create.h b/Tactical/Soldier Create.h index 369e64f4..d98f9c01 100644 --- a/Tactical/Soldier Create.h +++ b/Tactical/Soldier Create.h @@ -471,6 +471,7 @@ SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass, INT16 sX, INT16 sY ); SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType ); SOLDIERTYPE* TacticalCreateEnemyTank(); SOLDIERTYPE* TacticalCreateEnemyJeep( ); +SOLDIERTYPE* TacticalCreateEnemyRobot(); // Flugente: create an armed civilian SOLDIERTYPE* TacticalCreateArmedCivilian( UINT8 usSoldierClass = SOLDIER_CLASS_ARMY ); diff --git a/Tactical/Soldier Init List.cpp b/Tactical/Soldier Init List.cpp index 93b65a14..1b174fd7 100644 --- a/Tactical/Soldier Init List.cpp +++ b/Tactical/Soldier Init List.cpp @@ -1050,12 +1050,13 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum ) return ubNumAdded; } -void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks, UINT8 ubTotalJeeps ) +void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalRobots, UINT8 ubTotalTanks, UINT8 ubTotalJeeps ) { SOLDIERINITNODE *mark; SOLDIERINITNODE *curr; INT32 iRandom; UINT8 ubMaxNum; + UINT8 ubRobotPDSlots = 0, ubRobotDSlots = 0, ubRobotPSlots = 0, ubRobotBSlots = 0; UINT8 ubElitePDSlots = 0, ubEliteDSlots = 0, ubElitePSlots = 0, ubEliteBSlots = 0; UINT8 ubTroopPDSlots = 0, ubTroopDSlots = 0, ubTroopPSlots = 0, ubTroopBSlots = 0; UINT8 ubAdminPDSlots = 0, ubAdminDSlots = 0, ubAdminPSlots = 0, ubAdminBSlots = 0; @@ -1078,7 +1079,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 + ubTotalJeeps; + ubMaxNum = ubTotalAdmin + ubTotalTroops + ubTotalElite + ubTotalRobots + ubTotalTanks + ubTotalJeeps; AssertLE (ubMaxNum, gGameExternalOptions.ubGameMaximumNumberOfEnemies); @@ -1141,6 +1142,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr else ubJeepBSlots++; } + break; case SOLDIER_CLASS_TANK: if ( TANK( curr->pDetailedPlacement ) ) { @@ -1154,6 +1156,16 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr ubTankBSlots++; } break; + case SOLDIER_CLASS_ROBOT: + if ( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement ) + ubRobotPDSlots++; + else if ( curr->pBasicPlacement->fPriorityExistance ) + ubRobotPSlots++; + else if ( curr->pDetailedPlacement ) + ubRobotDSlots++; + else + ubRobotBSlots++; + break; } } curr = curr->next; @@ -1162,7 +1174,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 + 2; ++ubCurrClass ) + for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY + 3; ++ubCurrClass ) { //First, prepare the counters. switch( ubCurrClass ) @@ -1190,6 +1202,11 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr pCurrSlots = &ubJeepPDSlots; pCurrTotal = &ubTotalJeeps; break; + case SOLDIER_CLASS_ROBOT + 3: // SOLDIER_CLASS_ROBOT + ubCurrClass = SOLDIER_CLASS_ROBOT; + pCurrSlots = &ubRobotPDSlots; + pCurrTotal = &ubTotalRobots; + break; } //Now, loop through the priority existance and detailed placement section of the list. curr = gSoldierInitHead; @@ -1370,16 +1387,22 @@ 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 ) + else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks + ubTotalJeeps ) { curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_JEEP; curr->pBasicPlacement->ubBodyType = COMBAT_JEEP; ubTotalJeeps--; } + else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks + ubTotalJeeps + ubTotalRobots ) + { + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ROBOT; + curr->pBasicPlacement->ubBodyType = ROBOTNOWEAPON; + ubTotalRobots--; + } else Assert(0); if( AddPlacementToWorld( curr ) ) @@ -1494,6 +1517,19 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr return; ubFreeSlots--; } + else if ( ubTotalRobots ) + { + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ROBOT; + curr->pBasicPlacement->ubBodyType = ROBOTNOWEAPON; + ubTotalRobots--; + if ( AddPlacementToWorld( curr ) ) + { + ubMaxNum--; + } + else + return; + ubFreeSlots--; + } } curr = curr->next; } @@ -1532,12 +1568,18 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr curr->pBasicPlacement->ubBodyType = TANK_NW; ubTotalTanks--; } - else if ( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks + ubTotalJeeps ) + else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks + ubTotalJeeps ) { curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_JEEP; curr->pBasicPlacement->ubBodyType = COMBAT_JEEP; ubTotalJeeps--; } + else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks + ubTotalJeeps + ubTotalRobots ) + { + curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ROBOT; + curr->pBasicPlacement->ubBodyType = ROBOTNOWEAPON; + ubTotalRobots--; + } else Assert(0); /* DISABLE THE OVERRIDE FOR NOW... diff --git a/Tactical/Soldier Init List.h b/Tactical/Soldier Init List.h index 2b774fec..ac47d25d 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, UINT8 ubTotalJeeps ); +void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalRobots, 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 macros.h b/Tactical/Soldier macros.h index eb19608b..af0a32fe 100644 --- a/Tactical/Soldier macros.h +++ b/Tactical/Soldier macros.h @@ -12,6 +12,7 @@ #define AM_AN_EPC( p ) ( ( p->ubProfile == NO_PROFILE ) ? FALSE : ( gMercProfiles[ p->ubProfile ].ubMiscFlags & PROFILE_MISC_FLAG_EPCACTIVE ) ) +// rftr - this is for madlab's robot, since it has a profile #define AM_A_ROBOT( p ) ( ( p->ubProfile == NO_PROFILE ) ? FALSE : ( gMercProfiles[ p->ubProfile ].ubBodyType == ROBOTNOWEAPON ) ) @@ -34,6 +35,7 @@ #define COMBAT_JEEP( p ) ( p->ubBodyType == COMBAT_JEEP ) #define TANK( p ) (p->ubBodyType == TANK_NE || p->ubBodyType == TANK_NW ) +#define ENEMYROBOT( p ) (p->ubBodyType == ROBOTNOWEAPON && p->bTeam == ENEMY_TEAM) #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 ) diff --git a/Tactical/SoldierTooltips.cpp b/Tactical/SoldierTooltips.cpp index d61b028a..565e727f 100644 --- a/Tactical/SoldierTooltips.cpp +++ b/Tactical/SoldierTooltips.cpp @@ -54,7 +54,7 @@ STR16 gStrAlertStatus[] = { L"Green", L"Yellow", L"Red", L"Black" }; STR16 gStrAttitude[] = { L"DEFENSIVE", L"BRAVESOLO", L"BRAVEAID", L"CUNNINGSOLO", L"CUNNINGAID", L"AGGRESSIVE", L"MAXATTITUDES", L"ATTACKSLAYONLY" }; STR16 gStrOrders[] = { L"STATIONARY", L"ONGUARD", L"CLOSEPATROL", L"FARPATROL", L"POINTPATROL", L"ONCALL", L"SEEKENEMY", L"RNDPTPATROL", L"SNIPER" }; STR16 gStrTeam[] = { L"OUR_TEAM", L"ENEMY_TEAM", L"CREATURE_TEAM", L"MILITIA_TEAM", L"CIV_TEAM", L"LAST_TEAM", L"PLAYER_PLAN", L"LAN_TEAM_ONE", L"LAN_TEAM_TWO", L"LAN_TEAM_THREE", L"LAN_TEAM_FOUR" }; -STR16 gStrClass[] = { L"SOLDIER_CLASS_NONE", L"SOLDIER_CLASS_ADMINISTRATOR", L"SOLDIER_CLASS_ELITE", L"SOLDIER_CLASS_ARMY", L"SOLDIER_CLASS_GREEN_MILITIA", L"SOLDIER_CLASS_REG_MILITIA", L"SOLDIER_CLASS_ELITE_MILITIA", L"SOLDIER_CLASS_CREATURE", L"SOLDIER_CLASS_MINER", L"SOLDIER_CLASS_ZOMBIE", L"SOLDIER_CLASS_TANK", L"SOLDIER_CLASS_JEEP", L"SOLDIER_CLASS_BANDIT"}; +STR16 gStrClass[] = { L"SOLDIER_CLASS_NONE", L"SOLDIER_CLASS_ADMINISTRATOR", L"SOLDIER_CLASS_ELITE", L"SOLDIER_CLASS_ARMY", L"SOLDIER_CLASS_GREEN_MILITIA", L"SOLDIER_CLASS_REG_MILITIA", L"SOLDIER_CLASS_ELITE_MILITIA", L"SOLDIER_CLASS_CREATURE", L"SOLDIER_CLASS_MINER", L"SOLDIER_CLASS_ZOMBIE", L"SOLDIER_CLASS_TANK", L"SOLDIER_CLASS_JEEP", L"SOLDIER_CLASS_BANDIT", L"SOLDIER_CLASS_ROBOT" }; STR16 SeenStr(INT32 value) { @@ -95,7 +95,7 @@ void SoldierTooltip( SOLDIERTYPE* pSoldier ) // WANNE: No tooltips on bloodcats, bugs, tanks, robots // sevenfm: allow tooltip in debug mode if (gGameExternalOptions.ubSoldierTooltipDetailLevel < 4 && - (CREATURE_OR_BLOODCAT( pSoldier ) || ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier))) + (CREATURE_OR_BLOODCAT( pSoldier ) || ARMED_VEHICLE( pSoldier ) || AM_A_ROBOT( pSoldier) || ENEMYROBOT( pSoldier ))) { return; } diff --git a/Tactical/TeamTurns.cpp b/Tactical/TeamTurns.cpp index 3ce16818..5e8645ac 100644 --- a/Tactical/TeamTurns.cpp +++ b/Tactical/TeamTurns.cpp @@ -2015,7 +2015,7 @@ INT8 CalcInterruptDuelPts( SOLDIERTYPE * pSoldier, UINT8 ubOpponentID, BOOLEAN f } } - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { // reduce interrupt possibilities for tanks! iPoints /= 2; diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index ac115648..24cd2200 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -4091,7 +4091,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea { iHitChance = 100; } - 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 + else if ( AM_A_ROBOT( pTargetSoldier ) || ENEMYROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) || CREATURE_OR_BLOODCAT( pTargetSoldier ) || (SOLDIER_CLASS_MILITIA( pTargetSoldier->ubSoldierClass ) && (gGameExternalOptions.ubMilitiaDropEquipment != 2)) ) // added militia here - SANDRO { iHitChance = 0; } @@ -4450,7 +4450,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 ) && !ARMED_VEHICLE( pTargetSoldier ) ) + if ( iHitChance > 0 && pSoldier->bTeam == gbPlayerNum && pTargetSoldier->bTeam != gbPlayerNum && !(pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT( pTargetSoldier ) && !ARMED_VEHICLE( pTargetSoldier ) && !ENEMYROBOT( pTargetSoldier ) ) { if (fFailure == FALSE) { @@ -4582,7 +4582,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea } } - if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) ) + if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) || ENEMYROBOT( pTargetSoldier ) ) { ubExpGain = 0; } @@ -4632,7 +4632,7 @@ BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, BOOLEAN fStea } } - if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) ) + if ( pTargetSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT( pTargetSoldier ) || ARMED_VEHICLE( pTargetSoldier ) || ENEMYROBOT( pTargetSoldier ) ) { ubExpGain = 0; } @@ -6870,7 +6870,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 && !ARMED_VEHICLE( pTarget ) && !(pSoldier->ubBodyType != QUEENMONSTER) ) + if ( pTarget->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY && !ARMED_VEHICLE( pTarget ) && !ENEMYROBOT( pTarget ) && !(pSoldier->ubBodyType != QUEENMONSTER) ) { iPenalty = ( EffectiveAgility( pTarget, FALSE ) / 5 + EffectiveExpLevel( pTarget ) * 2); switch( gAnimControl[ pTarget->usAnimState ].ubHeight ) @@ -6885,7 +6885,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 ( ARMED_VEHICLE( pTarget ) || (pSoldier->ubBodyType != QUEENMONSTER) ) + if ( ARMED_VEHICLE( pTarget ) || ENEMYROBOT( pTarget ) || (pSoldier->ubBodyType != QUEENMONSTER) ) { // reduce ability to track shots iBonus = iBonus / 2; @@ -7455,7 +7455,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 ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { // allow absolute minimums iChance = 0; @@ -7683,7 +7683,7 @@ INT32 ArmourProtection( SOLDIERTYPE * pTarget, UINT16 ubArmourType, INT16 * pbSt iCoverage = Armour [ ubArmourType ].ubCoverage; if ( *plateHit ) iCoverage = 100; - if ( !AM_A_ROBOT( pTarget ) ) + if ( !(AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget )) ) { // check for the bullet missing armor due to coverage iFailure = PreRandom( 100 ) + 1 - iCoverage; @@ -7758,7 +7758,7 @@ INT32 ArmourProtection( SOLDIERTYPE * pTarget, UINT16 ubArmourType, INT16 * pbSt } } - if ( !AM_A_ROBOT( pTarget ) ) + if ( !(AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget )) ) { *pbStatus -= (iAppliedProtection * Armour[ubArmourType].ubDegradePercent) / 100; } @@ -7978,9 +7978,9 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, { damagefactor *= AmmoTypes[ubAmmoType].dDamageModifierZombie; } - else if ( pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE ) + else if ( pTarget->flags.uiStatusFlags & SOLDIER_VEHICLE || pTarget->flags.uiStatusFlags & SOLDIER_ROBOT ) { - if ( COMBAT_JEEP( pTarget ) || AM_A_ROBOT( pTarget ) ) + if ( COMBAT_JEEP( pTarget ) || AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget )) { damagefactor *= AmmoTypes[ubAmmoType].dDamageModifierArmouredVehicle; } @@ -8078,7 +8078,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, ShutupaYoFace( pTarget->iFaceIndex ); } - if ( iImpact > 0 && !ARMED_VEHICLE( pTarget ) ) + if ( iImpact > 0 && !ARMED_VEHICLE( pTarget ) && !ENEMYROBOT( pTarget ) ) { // Flugente: any bullet can have drug effects it set so in the magazine item if ( ammoitem != NOTHING ) @@ -8236,7 +8236,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, } } - if ( AM_A_ROBOT( pTarget ) ) + if ( AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget ) ) { iImpactForCrits = 0; } @@ -8591,7 +8591,7 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO iImpact += EffectiveStrength( pSoldier, FALSE ) / 20; // 0 to 5 for strength, adjusted by damage taken - if ( AM_A_ROBOT( pTarget ) ) + if ( AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget) ) { iImpact /= 4; } @@ -8608,7 +8608,7 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO { iImpact += GetDamage(&pSoldier->inv[HANDPOS]); - if ( AM_A_ROBOT( pTarget ) ) + if ( AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget ) ) { iImpact /= 2; } @@ -8619,7 +8619,7 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO { iImpact += GetDamage(&pSoldier->inv[HANDPOS]); } - if ( AM_A_ROBOT( pTarget ) ) + if ( AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget ) ) { iImpact /= 2; } @@ -8643,7 +8643,7 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO // only the item impact is multiplied, not the level and strength bonus, but here it does iImpact = (INT32)(iImpact * gGameExternalOptions.iMeleeDamageModifier / 100 ); - if ( AM_A_ROBOT( pTarget ) ) + if ( AM_A_ROBOT( pTarget ) || ENEMYROBOT( pTarget ) ) { iImpact = 0; } diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index 41976eb8..6f304032 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -1561,7 +1561,7 @@ INT8 DecideHearing( SOLDIERTYPE * pSoldier ) // calculate the hearing value for the merc... INT8 bHearing; - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { return( -5 ); } @@ -4885,6 +4885,7 @@ void DebugSoldierPage4( ) case SOLDIER_CLASS_MINER: gprintf( 320, LINE_HEIGHT * ubLine, L"(Miner)" ); break; case SOLDIER_CLASS_ZOMBIE: gprintf( 320, LINE_HEIGHT * ubLine, L"(Zombie)" ); break; case SOLDIER_CLASS_BANDIT: gprintf( 320, LINE_HEIGHT * ubLine, L"(Bandit)" ); break; + case SOLDIER_CLASS_ROBOT: gprintf( 320, LINE_HEIGHT * ubLine, L"(Army Robot)" ); break; default: break; //don't care (don't write anything) } diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index b0ca9311..b7d611f8 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -1451,7 +1451,7 @@ void CancelAIAction(SOLDIERTYPE *pSoldier, UINT8 ubForce) DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction")); // re-enable cover checking, something is new or something strange happened - if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 + if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier ) || !ENEMYROBOT( pSoldier ) )//dnl ch64 290813 SkipCoverCheck = FALSE; // turn off new situation flag to stop this from repeating all the time! @@ -1861,7 +1861,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 || !ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 + if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier ) || !ENEMYROBOT( pSoldier ) )//dnl ch64 290813 SkipCoverCheck = FALSE; // reset this field, too @@ -2945,6 +2945,11 @@ void HandleAITacticalTraversal( SOLDIERTYPE * pSoldier ) ++pSectorInfo->ubNumAdmins; break; + case SOLDIER_CLASS_ROBOT: + if (ENEMYROBOT(pSoldier)) + ++pSectorInfo->ubNumRobots; + break; + case SOLDIER_CLASS_TANK: if( TANK(pSoldier) ) ++pSectorInfo->ubNumTanks; diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index df6db2b0..d93d3bd2 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -1237,8 +1237,8 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, BOOLEAN * pfChangeLevel continue; } - // sevenfm: zombies do not attack vehicles - if (pSoldier->IsZombie() && (ARMED_VEHICLE(pOpponent) || (pOpponent->flags.uiStatusFlags & SOLDIER_VEHICLE))) + // sevenfm: zombies do not attack vehicles (rftr: or robots) + if (pSoldier->IsZombie() && (AM_A_ROBOT(pOpponent) || ENEMYROBOT(pOpponent) || ARMED_VEHICLE(pOpponent) || (pOpponent->flags.uiStatusFlags & SOLDIER_VEHICLE))) { continue; } @@ -3031,6 +3031,7 @@ UINT8 SoldierDifficultyLevel( SOLDIERTYPE * pSoldier ) bDifficulty = bDifficultyBase; break; + case SOLDIER_CLASS_ROBOT: case SOLDIER_CLASS_ELITE: bDifficulty = bDifficultyBase + 1; break; @@ -3476,7 +3477,7 @@ UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au continue; // this is not for tanks - if ( ARMED_VEHICLE( pFriend ) ) + if ( ARMED_VEHICLE( pFriend ) || ENEMYROBOT( pFriend )) continue; // skip if this guy is dead @@ -3529,7 +3530,7 @@ UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au continue; // this is not for tanks - if ( ARMED_VEHICLE( pFriend ) ) + if ( ARMED_VEHICLE( pFriend ) || ENEMYROBOT( pFriend ) ) continue; // skip if this guy is dead, or not wounded (enough) @@ -3578,7 +3579,7 @@ UINT8 GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTe continue; // this is not for tanks - if ( ARMED_VEHICLE( pFriend ) ) + if ( ARMED_VEHICLE( pFriend ) || ENEMYROBOT( pFriend ) ) continue; // skip this guy if he is dead or unconscious @@ -4907,7 +4908,8 @@ BOOLEAN SoldierAI(SOLDIERTYPE *pSoldier) pSoldier->flags.uiStatusFlags & SOLDIER_BOXER || ARMED_VEHICLE(pSoldier) || pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE || - AM_A_ROBOT(pSoldier)) + AM_A_ROBOT(pSoldier) || + ENEMYROBOT(pSoldier)) return FALSE; return TRUE; diff --git a/TacticalAI/Attacks.cpp b/TacticalAI/Attacks.cpp index c459ea6a..f70eb02e 100644 --- a/TacticalAI/Attacks.cpp +++ b/TacticalAI/Attacks.cpp @@ -117,7 +117,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 ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { // don't remove ammo gTempObject = pSoldier->inv[bPayloadPocket]; @@ -514,7 +514,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot) } // no crouched/prone if we are tank/using throwing knife/hip firing - if ( pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD || ARMED_VEHICLE( pSoldier ) || (Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE) ) + if ( pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD || ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) || (Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE) ) continue; // --------- Crouched --------- @@ -1159,7 +1159,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow) Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_CREATUREGAS && Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_BURNABLEGAS && Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_SMOKE && - (ARMED_VEHICLE(pOpponent) || pOpponent->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT(pOpponent))) + (ARMED_VEHICLE(pOpponent) || ENEMYROBOT(pOpponent) || pOpponent->flags.uiStatusFlags & SOLDIER_VEHICLE || AM_A_ROBOT(pOpponent))) { continue; } diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index 17c61935..1c6bcb44 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -71,7 +71,7 @@ STR8 gStr8AlertStatus[] = { "Green", "Yellow", "Red", "Black" }; STR8 gStr8Attitude[] = { "DEFENSIVE", "BRAVESOLO", "BRAVEAID", "CUNNINGSOLO", "CUNNINGAID", "AGGRESSIVE", "MAXATTITUDES", "ATTACKSLAYONLY" }; STR8 gStr8Orders[] = { "STATIONARY", "ONGUARD", "CLOSEPATROL", "FARPATROL", "POINTPATROL", "ONCALL", "SEEKENEMY", "RNDPTPATROL", "SNIPER" }; STR8 gStr8Team[] = { "OUR_TEAM", "ENEMY_TEAM", "CREATURE_TEAM", "MILITIA_TEAM", "CIV_TEAM", "LAST_TEAM", "PLAYER_PLAN", "LAN_TEAM_ONE", "LAN_TEAM_TWO", "LAN_TEAM_THREE", "LAN_TEAM_FOUR" }; -STR8 gStr8Class[] = { "SOLDIER_CLASS_NONE", "SOLDIER_CLASS_ADMINISTRATOR", "SOLDIER_CLASS_ELITE", "SOLDIER_CLASS_ARMY", "SOLDIER_CLASS_GREEN_MILITIA", "SOLDIER_CLASS_REG_MILITIA", "SOLDIER_CLASS_ELITE_MILITIA", "SOLDIER_CLASS_CREATURE", "SOLDIER_CLASS_MINER", "SOLDIER_CLASS_ZOMBIE", "SOLDIER_CLASS_TANK", "SOLDIER_CLASS_JEEP", "SOLDIER_CLASS_BANDIT" }; +STR8 gStr8Class[] = { "SOLDIER_CLASS_NONE", "SOLDIER_CLASS_ADMINISTRATOR", "SOLDIER_CLASS_ELITE", "SOLDIER_CLASS_ARMY", "SOLDIER_CLASS_GREEN_MILITIA", "SOLDIER_CLASS_REG_MILITIA", "SOLDIER_CLASS_ELITE_MILITIA", "SOLDIER_CLASS_CREATURE", "SOLDIER_CLASS_MINER", "SOLDIER_CLASS_ZOMBIE", "SOLDIER_CLASS_TANK", "SOLDIER_CLASS_JEEP", "SOLDIER_CLASS_BANDIT", "SOLDIER_CLASS_ROBOT" }; STR8 gStr8Knowledge[] = { "HEARD_3_TURNS_AGO", "HEARD_2_TURNS_AGO", "HEARD_LAST_TURN", "HEARD_THIS_TURN", "NOT_HEARD_OR_SEEN", "SEEN_CURRENTLY", "SEEN_THIS_TURN", "SEEN_LAST_TURN", "SEEN_2_TURNS_AGO", "SEEN_3_TURNS_AGO" }; void DoneScheduleAction( SOLDIERTYPE * pSoldier ) @@ -812,7 +812,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier) bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo ); // Flugente: tanks do not care about gas - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { bInGas = FALSE; } @@ -1135,6 +1135,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier) pSoldier->aiData.bLastAction != AI_ACTION_CLIMB_ROOF && pSoldier->aiData.bOrders != STATIONARY && pSoldier->pathing.bLevel == 0 && + !ENEMYROBOT(pSoldier) && !is_networked) { iChance = 10 + pSoldier->aiData.bBypassToGreen; @@ -2099,7 +2100,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier) AIPopMessage(tempstr); #endif - if ( fClimb )//&& pSoldier->aiData.usActionData == sNoiseGridNo) + if ( !ENEMYROBOT(pSoldier) && fClimb )//&& pSoldier->aiData.usActionData == sNoiseGridNo) { // need to climb AND have enough APs to get there this turn BOOLEAN fUp = TRUE; @@ -2258,7 +2259,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier) AIPopMessage(tempstr); #endif - if ( fClimb )//&& pSoldier->aiData.usActionData == sClosestFriend) + if ( !ENEMYROBOT(pSoldier) && fClimb )//&& pSoldier->aiData.usActionData == sClosestFriend) { // need to climb AND have enough APs to get there this turn BOOLEAN fUp = TRUE; @@ -2593,7 +2594,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo ); // Flugente: tanks do not care about gas - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { bInGas = FALSE; } @@ -3047,6 +3048,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) (fAnyCover || // safe position !fCanBeSeen && NightLight() && CountFriendsFlankSameSpot(pSoldier, sClosestOpponent) && Chance(50) || ARMED_VEHICLE(pSoldier) || // tanks don't need cover + ENEMYROBOT(pSoldier) || // robots don't try to be in cover pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || MercPtrs[BestShot.ubOpponent]->sLastTarget == pSoldier->sGridNo) || // return fire Chance((BestShot.ubChanceToReallyHit + 100) / 2) || // 50% chance to fire without cover //SoldierToSoldierLineOfSightTest(pSoldier, MercPtrs[BestShot.ubOpponent], TRUE, CALC_FROM_ALL_DIRS)) && // can see target after turning @@ -3054,6 +3056,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) // reduce chance to shoot if target is beyond weapon range (AICheckIsMachinegunner(pSoldier) || ARMED_VEHICLE(pSoldier) || + ENEMYROBOT(pSoldier) || AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || MercPtrs[BestShot.ubOpponent]->sLastTarget == pSoldier->sGridNo) || // return fire Chance(100 * (GunRange(&pSoldier->inv[BestShot.bWeaponIn], pSoldier) / CELL_X_SIZE) / PythSpacesAway(pSoldier->sGridNo, BestShot.sTarget))) && @@ -4025,7 +4028,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) AIPopMessage(tempstr); #endif - if (fClimb)//&& pSoldier->aiData.usActionData == sClosestDisturbance) + if (!ENEMYROBOT(pSoldier) && fClimb)//&& pSoldier->aiData.usActionData == sClosestDisturbance) { // need to climb AND have enough APs to get there this turn BOOLEAN fUp = TRUE; @@ -4297,7 +4300,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) AIPopMessage(tempstr); #endif - if ( fClimb )//&& pSoldier->aiData.usActionData == sClosestFriend) + if ( !ENEMYROBOT(pSoldier) && fClimb )//&& pSoldier->aiData.usActionData == sClosestFriend) { // need to climb AND have enough APs to get there this turn BOOLEAN fUp = TRUE; @@ -5039,7 +5042,7 @@ INT16 ubMinAPCost; bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo ); // Flugente: tanks do not care about gas - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { bInGas = FALSE; } @@ -5162,7 +5165,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 && !ARMED_VEHICLE( pSoldier ) ) + if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !(gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) ) { if ( gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 && gTacticalStatus.Team[ CREATURE_TEAM ].bMenInSector == 0 && NumPCsInSector() < 4 && gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector >= NumPCsInSector() * 3 ) { @@ -5553,7 +5556,7 @@ INT16 ubMinAPCost; // if the soldier does have a usable knife somewhere // 0verhaul: And is not a tank! - if ( bWeaponIn != NO_SLOT && !ARMED_VEHICLE( pSoldier ) && !(pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER | SOLDIER_PASSENGER)) ) + if ( bWeaponIn != NO_SLOT && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) && !(pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER | SOLDIER_PASSENGER)) ) { DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"try to stab"); BestStab.bWeaponIn = bWeaponIn; @@ -5641,7 +5644,7 @@ INT16 ubMinAPCost; } ///////////////////////////////////////////////////////////////////////////////////////////////////// // SANDRO - even if we don't have any blade, calculate how much damage we could do unarmed - else if ( !ARMED_VEHICLE( pSoldier ) && !(pSoldier->flags.uiStatusFlags & (SOLDIER_DRIVER | SOLDIER_PASSENGER)) ) + else if ( !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( 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 @@ -5860,7 +5863,7 @@ INT16 ubMinAPCost; } //////////////////////////////////////////////////////////////////////////////////// } - 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 + if ( BestThrow.ubPossible && ((BestThrow.iAttackValue > BestAttack.iAttackValue) || (ubBestAttackAction == AI_ACTION_NONE)) && !((ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( 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; DebugAI(AI_MSG_INFO, pSoldier, String("best action = throw something, iAttackValue = %d", BestThrow.iAttackValue)); @@ -6310,7 +6313,7 @@ INT16 ubMinAPCost; if (pSoldier->bActionPoints >= BestAttack.ubAPCost + sActualAimAP + ubBurstAPs ) { // Base chance of bursting is 25% if best shot was +0 aim, down to 8% at +4 - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { iChance = 100; } @@ -6427,7 +6430,7 @@ L_NEWAIM: if (pSoldier->bActionPoints >= BestAttack.ubAPCost + sActualAimAP + ubBurstAPs ) { // Base chance of bursting is 25% if best shot was +0 aim, down to 8% at +4 - if ( ARMED_VEHICLE( pSoldier ) ) + if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) ) { iChance = 100; } @@ -6765,7 +6768,7 @@ L_NEWAIM: pSoldier->aiData.usActionData = GoAsFarAsPossibleTowards(pSoldier,sClosestOpponent,AI_ACTION_GET_CLOSER); // Flugente: if on the same level and there is a jumpable window here, jump through it - if ( gGameExternalOptions.fCanJumpThroughWindows ) + if ( gGameExternalOptions.fCanJumpThroughWindows && !ENEMYROBOT(pSoldier) ) { // determine if there is a jumpable window in the direction to our target // if yes, and we are not facing it, face it now @@ -6813,14 +6816,14 @@ L_NEWAIM: if (pSoldier->pathing.bLevel > 0 ) fUp = FALSE; - if ( pSoldier->bActionPoints > GetAPsToClimbRoof ( pSoldier, fUp ) ) + if ( !ENEMYROBOT(pSoldier) && (pSoldier->bActionPoints > GetAPsToClimbRoof ( pSoldier, fUp )) ) { pSoldier->aiData.usActionData = targetGridNo;//FindClosestClimbPoint(pSoldier, fUp ); // Necessary test: can we climb up at this position? It might happen that our target is directly above us, then we'll have to move INT8 newdirection; if ( ( fUp && FindHeigherLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &newdirection ) ) || ( !fUp && FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &newdirection ) ) ) - { + { return( AI_ACTION_CLIMB_ROOF ); } else @@ -9586,7 +9589,7 @@ INT8 ArmedVehicleDecideActionBlack( SOLDIERTYPE *pSoldier ) // 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 && !ARMED_VEHICLE( pSoldier ) ) + if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !(gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) ) { if ( gTacticalStatus.Team[MILITIA_TEAM].bMenInSector == 0 && gTacticalStatus.Team[CREATURE_TEAM].bMenInSector == 0 && NumPCsInSector( ) < 4 && gTacticalStatus.Team[ENEMY_TEAM].bMenInSector >= NumPCsInSector( ) * 3 ) { @@ -9859,7 +9862,7 @@ INT8 ArmedVehicleDecideActionBlack( SOLDIERTYPE *pSoldier ) BestAttack.iAttackValue = 0; } - 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 + if ( BestThrow.ubPossible && ((BestThrow.iAttackValue > BestAttack.iAttackValue) || (ubBestAttackAction == AI_ACTION_NONE)) && !((ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( 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" ); diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 8a7c05a4..936763f0 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -1621,7 +1621,7 @@ BOOLEAN DamageSoldierFromBlast( UINT8 ubPerson, UINT8 ubOwner, INT32 sBombGridNo sNewWoundAmt = (INT16)(sNewWoundAmt * (100 + gSkillTraitValues.ubDEDamageOfBombsAndMines) / 100.0f + 0.5f); } // Heavy Weapons trait bonus damage to tanks - if ( HAS_SKILL_TRAIT( MercPtrs[ubOwner], HEAVY_WEAPONS_NT ) && ARMED_VEHICLE( pSoldier ) && + if ( HAS_SKILL_TRAIT( MercPtrs[ubOwner], HEAVY_WEAPONS_NT ) && (ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier )) && Explosive[Item[usItem].ubClassIndex].ubType == EXPLOSV_NORMAL ) { sNewWoundAmt = (INT16)(sNewWoundAmt * (100 + gSkillTraitValues.ubHWDamageTanksBonusPercent * NUM_SKILL_TRAITS( MercPtrs[ ubOwner ], HEAVY_WEAPONS_NT )) / 100.0f + 0.5f); // +30% @@ -1656,7 +1656,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) && !ARMED_VEHICLE( pSoldier ) && + !AM_A_ROBOT( pSoldier ) && !(pSoldier->flags.uiStatusFlags & SOLDIER_MONSTER) && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) && sNewWoundAmt > 2 && sNewWoundAmt < pSoldier->stats.bLife ) { if ( PreRandom( sNewWoundAmt ) > gSkillTraitValues.ubDamageNeededToLoseStats ) @@ -1923,7 +1923,7 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN FLOAT fGasBreathDamageModifier = 1.0; INT8 bPosOfMask = NO_SLOT; - if (!pSoldier->bActive || !pSoldier->bInSector || !pSoldier->stats.bLife || AM_A_ROBOT( pSoldier ) ) + if (!pSoldier->bActive || !pSoldier->bInSector || !pSoldier->stats.bLife || AM_A_ROBOT( pSoldier ) || ENEMYROBOT( pSoldier ) ) { return( fRecompileMovementCosts ); } @@ -4732,7 +4732,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] ) && !ARMED_VEHICLE( MercPtrs[ubID] ) ) + if ( !(MercPtrs[ubID]->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT( MercPtrs[ubID] ) && !ARMED_VEHICLE( MercPtrs[ubID] ) && !ENEMYROBOT( MercPtrs[ubID] ) ) continue; } diff --git a/TileEngine/Tactical Placement GUI.h b/TileEngine/Tactical Placement GUI.h index ab25d9e9..06307750 100644 --- a/TileEngine/Tactical Placement GUI.h +++ b/TileEngine/Tactical Placement GUI.h @@ -4,7 +4,7 @@ //#include "Soldier Control.h" //#include "mousesystem.h" typedef struct _MOUSE_REGION MOUSE_REGION; -extern class SOLDIERTYPE; +class SOLDIERTYPE; void InitTacticalPlacementGUI(); void KillTacticalPlacementGUI(); diff --git a/Utils/Text.h b/Utils/Text.h index c317ad6f..38de6b3a 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -1885,6 +1885,7 @@ enum STR_MILITIAMOVEMENT_NO_LIMITEDROAMING, STR_MILITIAMOVEMENT_NO_STAFF_ABORT, + STR_AR_ROBOT_NAME, STR_AR_TANK_NAME, STR_AR_JEEP_NAME, diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 78f61fad..fc1fc4b0 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -3524,6 +3524,7 @@ STR16 gpStrategicString[] = L"民兵无法移动到这。(RESTRICT_ROAMING = TRUE)", //L"Militia cannot move here (RESTRICT_ROAMING = TRUE).", L"战术中心无人兼职,民兵移动失败!", //L"War room isn't staffed - militia move aborted!", + L"Robot", //STR_AR_ROBOT_NAME, TODO: translate L"坦克", //STR_AR_TANK_NAME, L"吉普", // L"Jeep", STR_AR_JEEP_NAME diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 10769158..4effc535 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -3524,6 +3524,7 @@ STR16 gpStrategicString[] = L"Militia cannot move here (RESTRICT_ROAMING = TRUE).", L"War room isn't staffed - militia move aborted!", + L"Robot", //STR_AR_ROBOT_NAME, TODO: translate L"Tank", //STR_AR_TANK_NAME, L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 003cb6b6..36f34d3a 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -3537,6 +3537,7 @@ STR16 gpStrategicString[] = L"Militia cannot move here (RESTRICT_ROAMING = TRUE).", L"War room isn't staffed - militia move aborted!", + L"Robot", //STR_AR_ROBOT_NAME, L"Tank", //STR_AR_TANK_NAME, L"Jeep", //STR_AR_JEEP_NAME, diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 94d16e4e..207c92bf 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -3532,6 +3532,7 @@ STR16 gpStrategicString[] = L"La milice ne peut pas se déplacer (RESTRICT_ROAMING = TRUE).", L"La salle d'opérations n'est pas ouverte... Le mouvement de la milice a avorté !", + L"Robot", //STR_AR_ROBOT_NAME, // TODO: translate L"Tank", //STR_AR_TANK_NAME, // TODO.Translate L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 6c8a5e92..95e42db4 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -3561,6 +3561,7 @@ STR16 gpStrategicString[] = L"Militia cannot move here (RESTRICT_ROAMING = TRUE).", L"War room isn't staffed - militia move aborted!", + L"Robot", //STR_AR_ROBOT_NAME, // TODO: translate L"Panzer", //STR_AR_TANK_NAME, L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 89f405e1..0bfad05d 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -3519,6 +3519,7 @@ STR16 gpStrategicString[] = L"Militia cannot move here (RESTRICT_ROAMING = TRUE).", L"War room isn't staffed - militia move aborted!", + L"Robot", //STR_AR_ROBOT_NAME, TODO: translate L"Tank", //STR_AR_TANK_NAME, L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 389148cb..3a178d13 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -3530,6 +3530,7 @@ STR16 gpStrategicString[] = L"Militia cannot move here (RESTRICT_ROAMING = TRUE).", L"War room isn't staffed - militia move aborted!", + L"Robot", //STR_AR_ROBOT_NAME, // TODO: translate L"Tank", //STR_AR_TANK_NAME, L"Jeep", //STR_AR_JEEP_NAME // TODO.Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index ab9732ff..968bae8c 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -3524,6 +3524,7 @@ STR16 gpStrategicString[] = L"Ополчение не может быть сюда перемещено (RESTRICT_ROAMING = TRUE).", L"War room isn't staffed - militia move aborted!", // TODO.Translate + L"Робот", //STR_AR_ROBOT_NAME, TODO: translate L"Танк", //STR_AR_TANK_NAME, L"Джип", //STR_AR_JEEP_NAME diff --git a/lua/lua_strategic.cpp b/lua/lua_strategic.cpp index e9621762..a19aa43a 100644 --- a/lua/lua_strategic.cpp +++ b/lua/lua_strategic.cpp @@ -159,8 +159,9 @@ static int LuaGroupCreate( lua_State *L ) UINT8 NumElites = (UINT8) luaL_checkinteger( L, 4); UINT8 NumTanks = (UINT8) luaL_checkinteger( L, 5); UINT8 NumJeeps = (UINT8)luaL_checkinteger( L, 6 ); + UINT8 NumRobots = (UINT8)luaL_checkinteger( L, 7); - GROUP *pGroup = CreateNewEnemyGroupDepartingFromSector( Sector, NumAdmins, NumTroops, NumElites, NumTanks, NumJeeps ); + GROUP *pGroup = CreateNewEnemyGroupDepartingFromSector( Sector, NumAdmins, NumTroops, NumElites, NumRobots, NumTanks, NumJeeps ); if (pGroup) { diff --git a/ub_config.cpp b/ub_config.cpp index 47174d59..6a6b5775 100644 --- a/ub_config.cpp +++ b/ub_config.cpp @@ -107,6 +107,7 @@ void RandomAddEnemy( UINT8 SectorX, UINT8 SectorY, UINT8 Level ) UINT8 ubNumElites = 0; UINT8 ubNumTanks = 0; UINT8 ubNumJeeps = 0; + UINT8 ubNumRobots = 0; if ( Level != 0 ) { @@ -121,31 +122,31 @@ void RandomAddEnemy( UINT8 SectorX, UINT8 SectorY, UINT8 Level ) ubNumAdmins = Random( 0 ); ubNumTroops = 10 + Random( 5 ); ubNumElites = Random( 4 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); 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 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); 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 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); 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 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); break; default: ubNumAdmins = Random( 0 ); ubNumTroops = 10 + Random( 5 ); ubNumElites = Random( 4 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); break; } } @@ -161,31 +162,31 @@ void RandomAddEnemy( UINT8 SectorX, UINT8 SectorY, UINT8 Level ) ubNumAdmins = Random( 0 ); ubNumTroops = 10 + Random( 5 ); ubNumElites = Random( 4 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); 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 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); break; case DIF_LEVEL_HARD: ubNumAdmins = Random( 0 ); ubNumTroops = 23 + Random( 7); ubNumElites = 2 + Random( 2 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); 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 ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); break; default: ubNumAdmins = Random( 0 ); ubNumTroops = 10 + Random( 5 ); ubNumElites = Random( 4 ); - SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps ); + SetNumberJa25EnemiesInSector( SectorX, SectorY, Level, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, ubNumJeeps, ubNumRobots ); break; } }