diff --git a/GameSettings.cpp b/GameSettings.cpp index 310da8cf..11c865ba 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1508,6 +1508,11 @@ void LoadGameExternalOptions() // Drassen counterattack gGameExternalOptions.ubSendTroopsToDrassen = iniReader.ReadBoolean("Strategic Event Settings","TRIGGER_MASSIVE_ENEMY_COUNTERATTACK_AT_DRASSEN",TRUE); + // Flugente: new strategic AI + gGameExternalOptions.ubAgressiveStrategicAI = iniReader.ReadInteger("Strategic Event Settings","AGGRESSIVE_STRATEGIC_AI", 1, 0, 4); + gGameExternalOptions.ubGameProgressOffensiveStage1 = iniReader.ReadInteger("Strategic Event Settings","GAME_PROGRESS_OFFENSIVE_STAGE_1", 65, 0, 100); + gGameExternalOptions.ubGameProgressOffensiveStage2 = iniReader.ReadInteger("Strategic Event Settings","GAME_PROGRESS_OFFENSIVE_STAGE_2", 80, 0, 100); + // Enable/Disable crepitus completely in SCI-FI mode. gGameExternalOptions.fEnableCrepitus = iniReader.ReadBoolean("Strategic Event Settings", "ENABLE_CREPITUS", TRUE); diff --git a/GameSettings.h b/GameSettings.h index 62192c7c..459efaf4 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -521,6 +521,9 @@ typedef struct UINT32 ubGameProgressMikeAvailable; UINT32 ubGameProgressIggyAvaliable; BOOLEAN ubSendTroopsToDrassen; + UINT8 ubAgressiveStrategicAI; + UINT32 ubGameProgressOffensiveStage1; + UINT32 ubGameProgressOffensiveStage2; // WDS - make number of mercenaries, etc. be configurable // group sizes diff --git a/Strategic/Meanwhile.cpp b/Strategic/Meanwhile.cpp index acfe067f..896303f4 100644 --- a/Strategic/Meanwhile.cpp +++ b/Strategic/Meanwhile.cpp @@ -700,24 +700,38 @@ void ProcessImplicationsOfMeanwhile( void ) break; case CAMBRIA_LIBERATED: - ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 8, 7 ); //lalien: The queen should try to get the city back + //ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 8, 7 ); //lalien: The queen should try to get the city back + + ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_WAKE_QUEEN, 0, 0 ); + ExecuteStrategicAIAction( NPC_ACTION_SEND_SOLDIERS_TO_CAMBRIA, 8, 8 ); break; case ALMA_LIBERATED: - ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 14, 9 );//lalien: The queen should try to get the city back + //ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 14, 9 );//lalien: The queen should try to get the city back + + ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_WAKE_QUEEN, 0, 0 ); + ExecuteStrategicAIAction( NPC_ACTION_SEND_SOLDIERS_TO_ALMA, 14, 9 ); break; case GRUMM_LIBERATED: - ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 3, 8 );//lalien: The queen should try to get the city back + //ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 3, 8 );//lalien: The queen should try to get the city back + + ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_WAKE_QUEEN, 0, 0 ); + ExecuteStrategicAIAction( NPC_ACTION_SEND_SOLDIERS_TO_GRUMM, 3, 8 ); break; case CHITZENA_LIBERATED: - ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 2, 2 );//lalien: The queen should try to get the city back + //ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 2, 2 );//lalien: The queen should try to get the city back + + ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_WAKE_QUEEN, 0, 0 ); + ExecuteStrategicAIAction( NPC_ACTION_SEND_SOLDIERS_TO_CHITZENA, 2, 2 ); break; case BALIME_LIBERATED: ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_WAKE_QUEEN, 0, 0 ); - ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 11, 12 );//lalien: The queen should try to get the city back + //ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, 11, 12 );//lalien: The queen should try to get the city back + + ExecuteStrategicAIAction( NPC_ACTION_SEND_SOLDIERS_TO_BALIME, 12, 12 ); break; case DRASSEN_LIBERATED: diff --git a/Strategic/Strategic AI.cpp b/Strategic/Strategic AI.cpp index aee4c857..08729a09 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -4381,6 +4381,367 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto break; + case NPC_ACTION_SEND_SOLDIERS_TO_CHITZENA: + case NPC_ACTION_SEND_SOLDIERS_TO_GRUMM: + case NPC_ACTION_SEND_SOLDIERS_TO_CAMBRIA: + case NPC_ACTION_SEND_SOLDIERS_TO_ALMA: + case NPC_ACTION_SEND_SOLDIERS_TO_BALIME: + { + if ( gGameExternalOptions.ubAgressiveStrategicAI < 1) + { + ExecuteStrategicAIAction( NPC_ACTION_SEND_TROOPS_TO_SAM, sSectorX, sSectorY ); + break; + } + + ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3); + + UINT32 grouptroops = ubNumSoldiers; + UINT32 groupelites = 0; + if ( gGameOptions.ubDifficultyLevel > 0 ) + groupelites = ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel; + + UINT32 totalusedsoldiers = 4 * min(grouptroops + groupelites, gGameExternalOptions.iMaxEnemyGroupSize); + + switch( usActionCode ) + { + case NPC_ACTION_SEND_SOLDIERS_TO_CHITZENA: + ubSourceSectorID = SEC_H3; + ubTargetSectorID = SEC_B2; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + + break; + case NPC_ACTION_SEND_SOLDIERS_TO_GRUMM: + ubSourceSectorID = SEC_M3; + ubTargetSectorID = SEC_H3; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( SEC_M2, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( SEC_M3, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( SEC_M3, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( SEC_M6, 0, grouptroops, groupelites ); + + break; + case NPC_ACTION_SEND_SOLDIERS_TO_CAMBRIA: + ubSourceSectorID = SEC_M6; + ubTargetSectorID = SEC_H8; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( SEC_M6, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( SEC_M6, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( SEC_M6, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( SEC_L11, 0, grouptroops, groupelites ); + + break; + case NPC_ACTION_SEND_SOLDIERS_TO_ALMA: + ubSourceSectorID = SEC_G9; + ubTargetSectorID = SEC_H13; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + { + ubSourceSectorID = SEC_J9; + ubTargetSectorID = SEC_I13; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + } + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + + break; + case NPC_ACTION_SEND_SOLDIERS_TO_BALIME: + ubSourceSectorID = SEC_N5; + ubTargetSectorID = SEC_L11; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + + break; + } + + + if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) + { + pGroup0->pEnemyGroup->ubIntention = STAGE; + pGroup1->pEnemyGroup->ubIntention = STAGE; + pGroup2->pEnemyGroup->ubIntention = STAGE; + pGroup3->pEnemyGroup->ubIntention = REINFORCEMENTS; + + gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID = pGroup3->ubGroupID; + + } + else + { + //this should never happen (but if it did, then this is the best way to deal with it). + pGroup0->pEnemyGroup->ubIntention = PURSUIT; + pGroup1->pEnemyGroup->ubIntention = PURSUIT; + pGroup2->pEnemyGroup->ubIntention = PURSUIT; + pGroup3->pEnemyGroup->ubIntention = PURSUIT; + } + + switch( usActionCode ) + { + case NPC_ACTION_SEND_SOLDIERS_TO_CHITZENA: + MoveSAIGroupToSector( &pGroup0, SEC_B1, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_C2, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_B3, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_B1, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + break; + + case NPC_ACTION_SEND_SOLDIERS_TO_GRUMM: + MoveSAIGroupToSector( &pGroup0, SEC_H4, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_I3, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_I3, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_G3, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + break; + + case NPC_ACTION_SEND_SOLDIERS_TO_CAMBRIA: + MoveSAIGroupToSector( &pGroup0, SEC_I8, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_I8, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_H7, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_H9, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + break; + + case NPC_ACTION_SEND_SOLDIERS_TO_ALMA: + if ( ubSourceSectorID == SEC_G9 ) + { + MoveSAIGroupToSector( &pGroup0, SEC_H12, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_H12, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_G13, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_G13, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + } + else + { + MoveSAIGroupToSector( &pGroup0, SEC_J13, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_J13, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_I12, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_I12, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + } + break; + + case NPC_ACTION_SEND_SOLDIERS_TO_BALIME: + MoveSAIGroupToSector( &pGroup0, SEC_K11, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_L10, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_L10, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_K11, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + break; + } + + //Madd: unlimited reinforcements? + if ( !gfUnlimitedTroops ) + giReinforcementPool -= totalusedsoldiers; + + giReinforcementPool = max( giReinforcementPool, 0 ); + } + break; + + case NPC_ACTION_GLOBAL_OFFENSIVE_1: + case NPC_ACTION_GLOBAL_OFFENSIVE_2: // for now, just a copy... + { + if ( gGameExternalOptions.ubAgressiveStrategicAI < 2 ) + { + break; + } + + // depending on which cities the player currently holds, we send out attack on multiple cities. We try to make these attacks occur simultaneously, so the palyer will have to fend off + // multiple gigantic attacks on different cities. Ideally, the attacks will be timed so well that the player cannot use a sqaud in both battles, even with use of the helicopter + // we first have to check which cities we have to attack. For that, we simply check wether there are troops in the target sector. If not, we will attack here + BOOLEAN fAttack_Grumm = !(SectorInfo[ SEC_H3 ].ubNumTroops > 0); + BOOLEAN fAttack_Cambria = !(SectorInfo[ SEC_H8 ].ubNumTroops > 0); + BOOLEAN fAttack_Alma = !(SectorInfo[ SEC_I13 ].ubNumTroops > 0); + BOOLEAN fAttack_Balime = !(SectorInfo[ SEC_L11 ].ubNumTroops > 0); + + ubNumSoldiers = (UINT8)( gubMinEnemyGroupSize + gGameOptions.ubDifficultyLevel * 3); + + UINT32 grouptroops = ubNumSoldiers; + UINT32 groupelites = 0; + if ( gGameOptions.ubDifficultyLevel > 0 ) + groupelites = ubNumSoldiers - ubNumSoldiers / gGameOptions.ubDifficultyLevel; + + UINT32 totalusedsoldiers = 0; + + if ( fAttack_Grumm ) + { + ubSourceSectorID = SEC_M6; + ubTargetSectorID = SEC_H3; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( SEC_P3, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( SEC_P3, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( SEC_P3, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + + totalusedsoldiers += min(grouptroops + groupelites, gGameExternalOptions.iMaxEnemyGroupSize); + + if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) + { + pGroup0->pEnemyGroup->ubIntention = STAGE; + pGroup1->pEnemyGroup->ubIntention = STAGE; + pGroup2->pEnemyGroup->ubIntention = STAGE; + pGroup3->pEnemyGroup->ubIntention = REINFORCEMENTS; + + gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID = pGroup3->ubGroupID; + + } + else + { + //this should never happen (but if it did, then this is the best way to deal with it). + pGroup0->pEnemyGroup->ubIntention = PURSUIT; + pGroup1->pEnemyGroup->ubIntention = PURSUIT; + pGroup2->pEnemyGroup->ubIntention = PURSUIT; + pGroup3->pEnemyGroup->ubIntention = PURSUIT; + } + + MoveSAIGroupToSector( &pGroup0, SEC_H4, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_I3, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_I3, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_G3, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + } + + if ( fAttack_Cambria ) + { + ubSourceSectorID = SEC_P3; + ubTargetSectorID = SEC_H8; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + + totalusedsoldiers += min(grouptroops + groupelites, gGameExternalOptions.iMaxEnemyGroupSize); + + if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) + { + pGroup0->pEnemyGroup->ubIntention = STAGE; + pGroup1->pEnemyGroup->ubIntention = STAGE; + pGroup2->pEnemyGroup->ubIntention = STAGE; + pGroup3->pEnemyGroup->ubIntention = REINFORCEMENTS; + + gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID = pGroup3->ubGroupID; + + } + else + { + //this should never happen (but if it did, then this is the best way to deal with it). + pGroup0->pEnemyGroup->ubIntention = PURSUIT; + pGroup1->pEnemyGroup->ubIntention = PURSUIT; + pGroup2->pEnemyGroup->ubIntention = PURSUIT; + pGroup3->pEnemyGroup->ubIntention = PURSUIT; + } + + MoveSAIGroupToSector( &pGroup0, SEC_I8, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_I8, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_H7, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_H9, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + } + + if ( fAttack_Alma ) + { + ubSourceSectorID = SEC_M6; + ubTargetSectorID = SEC_I13; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + + totalusedsoldiers += min(grouptroops + groupelites, gGameExternalOptions.iMaxEnemyGroupSize); + + if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) + { + pGroup0->pEnemyGroup->ubIntention = STAGE; + pGroup1->pEnemyGroup->ubIntention = STAGE; + pGroup2->pEnemyGroup->ubIntention = STAGE; + pGroup3->pEnemyGroup->ubIntention = REINFORCEMENTS; + + gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID = pGroup3->ubGroupID; + + } + else + { + //this should never happen (but if it did, then this is the best way to deal with it). + pGroup0->pEnemyGroup->ubIntention = PURSUIT; + pGroup1->pEnemyGroup->ubIntention = PURSUIT; + pGroup2->pEnemyGroup->ubIntention = PURSUIT; + pGroup3->pEnemyGroup->ubIntention = PURSUIT; + } + + MoveSAIGroupToSector( &pGroup0, SEC_J13, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_J13, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_I12, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_I12, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + } + + if ( fAttack_Balime ) + { + ubSourceSectorID = SEC_M2; + ubTargetSectorID = SEC_L11; + + if ( !(SectorInfo[ ubSourceSectorID ].ubNumTroops > 0) ) + ubSourceSectorID = SEC_P3; + + pGroup0 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup1 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup2 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + pGroup3 = CreateNewEnemyGroupDepartingFromSector( ubSourceSectorID, 0, grouptroops, groupelites ); + + totalusedsoldiers += min(grouptroops + groupelites, gGameExternalOptions.iMaxEnemyGroupSize); + + if( !gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID ) + { + pGroup0->pEnemyGroup->ubIntention = STAGE; + pGroup1->pEnemyGroup->ubIntention = STAGE; + pGroup2->pEnemyGroup->ubIntention = STAGE; + pGroup3->pEnemyGroup->ubIntention = REINFORCEMENTS; + + gGarrisonGroup[ SectorInfo[ ubTargetSectorID ].ubGarrisonID ].ubPendingGroupID = pGroup3->ubGroupID; + + } + else + { + //this should never happen (but if it did, then this is the best way to deal with it). + pGroup0->pEnemyGroup->ubIntention = PURSUIT; + pGroup1->pEnemyGroup->ubIntention = PURSUIT; + pGroup2->pEnemyGroup->ubIntention = PURSUIT; + pGroup3->pEnemyGroup->ubIntention = PURSUIT; + } + + MoveSAIGroupToSector( &pGroup0, SEC_K11, EVASIVE, pGroup0->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup1, SEC_L10, EVASIVE, pGroup1->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup2, SEC_L10, EVASIVE, pGroup2->pEnemyGroup->ubIntention ); + MoveSAIGroupToSector( &pGroup3, SEC_K11, EVASIVE, pGroup3->pEnemyGroup->ubIntention ); + } + + //Madd: unlimited reinforcements? + if ( !gfUnlimitedTroops ) + giReinforcementPool -= totalusedsoldiers; + + giReinforcementPool = max( giReinforcementPool, 0 ); + } + break; case NPC_ACTION_SEND_SOLDIERS_TO_BATTLE_LOCATION: //Send 4, 8, or 12 troops (based on difficulty) to the location of the first battle. If nobody is there when they arrive, diff --git a/Tactical/Campaign.cpp b/Tactical/Campaign.cpp index fe7bb133..b5eab54f 100644 --- a/Tactical/Campaign.cpp +++ b/Tactical/Campaign.cpp @@ -35,6 +35,8 @@ #include "Town Militia.h" #include "Campaign Types.h" #include "Tactical Save.h" + #include "Strategic AI.h" + #include "interface Dialogue.h" #endif #ifdef JA2UB @@ -1727,6 +1729,17 @@ void HourlyProgressUpdate(void) gMercProfiles[ IGGY ].sSectorY = MAP_ROW_C; } + // Flugente: on certain progress levels, the queen decides to initiate major attacks + if ( ubCurrentProgress >= gGameExternalOptions.ubGameProgressOffensiveStage1 && gStrategicStatus.ubHighestProgress <= gGameExternalOptions.ubGameProgressOffensiveStage1 ) + { + ExecuteStrategicAIAction( NPC_ACTION_GLOBAL_OFFENSIVE_1, 0, 0 ); + } + + if ( ubCurrentProgress >= gGameExternalOptions.ubGameProgressOffensiveStage2 && gStrategicStatus.ubHighestProgress <= gGameExternalOptions.ubGameProgressOffensiveStage2 ) + { + ExecuteStrategicAIAction( NPC_ACTION_GLOBAL_OFFENSIVE_2, 0, 0 ); + } + gStrategicStatus.ubHighestProgress = ubCurrentProgress; // debug message diff --git a/Tactical/Food.cpp b/Tactical/Food.cpp index c0217946..2c1e597b 100644 --- a/Tactical/Food.cpp +++ b/Tactical/Food.cpp @@ -762,7 +762,7 @@ void SectorFillCanteens( void ) // search for a water drum BOOLEAN waterdrumfound = FALSE; OBJECTTYPE* pWaterDrum = GetUsableWaterDrumInSector(); - if ( !pWaterDrum || !(pWaterDrum->exists()) ) + if ( pWaterDrum && (pWaterDrum->exists()) ) waterdrumfound = TRUE; // drink from sector if water is ok, or it is poisonous but we haven't found a useable water drum diff --git a/Tactical/Interface Dialogue.cpp b/Tactical/Interface Dialogue.cpp index da08d121..906b66c4 100644 --- a/Tactical/Interface Dialogue.cpp +++ b/Tactical/Interface Dialogue.cpp @@ -3551,6 +3551,13 @@ void HandleNPCDoAction( UINT8 ubTargetNPC, UINT16 usActionCode, UINT8 ubQuoteNum case NPC_ACTION_SEND_SOLDIERS_TO_OMERTA: case NPC_ACTION_ADD_MORE_ELITES: case NPC_ACTION_GIVE_KNOWLEDGE_OF_ALL_MERCS: + case NPC_ACTION_SEND_SOLDIERS_TO_CHITZENA: + case NPC_ACTION_SEND_SOLDIERS_TO_GRUMM: + case NPC_ACTION_SEND_SOLDIERS_TO_CAMBRIA: + case NPC_ACTION_SEND_SOLDIERS_TO_ALMA: + case NPC_ACTION_SEND_SOLDIERS_TO_BALIME: + case NPC_ACTION_GLOBAL_OFFENSIVE_1: + case NPC_ACTION_GLOBAL_OFFENSIVE_2: break; case NPC_ACTION_TRIGGER_QUEEN_BY_SAM_SITES_CONTROLLED: diff --git a/Tactical/interface Dialogue.h b/Tactical/interface Dialogue.h index 36275068..7e49861e 100644 --- a/Tactical/interface Dialogue.h +++ b/Tactical/interface Dialogue.h @@ -372,7 +372,17 @@ enum NPC_ACTION_TURN_TO_FACE_NEAREST_MERC = 500, NPC_ACTION_TURN_TO_FACE_PROFILE_ID_0, - NPC_ACTION_LAST_TURN_TO_FACE_PROFILE = 650 + NPC_ACTION_LAST_TURN_TO_FACE_PROFILE = 650, + + // Flugente: counterattacks for all cities + NPC_ACTION_SEND_SOLDIERS_TO_CHITZENA, + NPC_ACTION_SEND_SOLDIERS_TO_GRUMM, + NPC_ACTION_SEND_SOLDIERS_TO_CAMBRIA, + NPC_ACTION_SEND_SOLDIERS_TO_ALMA, + NPC_ACTION_SEND_SOLDIERS_TO_BALIME, + + NPC_ACTION_GLOBAL_OFFENSIVE_1, + NPC_ACTION_GLOBAL_OFFENSIVE_2, }; #define HOSPITAL_PATIENT_DISTANCE 9