diff --git a/GameSettings.cpp b/GameSettings.cpp index 233aa2f9..abbcf1ce 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -82,6 +82,8 @@ #define CREATURES_SETTINGS_FILE "Creatures_Settings.ini" +#define REBEL_COMMAND_SETTINGS_FILE "RebelCommand_Settings.ini" + #define CD_ROOT_DIR "DATA\\" GAME_SETTINGS gGameSettings; @@ -94,6 +96,7 @@ HELICOPTER_SETTINGS gHelicopterSettings; MORALE_SETTINGS gMoraleSettings; REPUTATION_SETTINGS gReputationSettings; CREATURES_SETTINGS gCreaturesSettings; +REBELCOMMAND_SETTINGS gRebelCommandSettings; CTH_CONSTANTS gGameCTHConstants; // HEADROCK HAM 4: CTH constants MOD_SETTINGS gModSettings; //DBrot: mod specific settings @@ -113,6 +116,40 @@ BOOLEAN GetCDromDriveLetter( STR8 pString ); BOOLEAN IsDriveLetterACDromDrive( STR pDriveLetter ); void CDromEjectionErrorMessageBoxCallBack( UINT8 bExitValue ); +// helper function for reading numerical arrays +template +void FillArrayValues(CIniReader& iniReader, const STR8 sectionName, const STR8 settingName, T& vec) +{ + using namespace std; + STRING512 textBuffer; + iniReader.ReadString(sectionName, settingName, NULL, textBuffer, _countof(textBuffer)); + + string str, token; + string delim = ","; + size_t offset = 0, prevOffset = 0; + + // sanitise input + vec.clear(); + str = textBuffer; + str.erase(std::remove(str.begin(), str.end(), ' '), str.end()); + + vector tempVec; + do + { + offset = str.find(delim, prevOffset); + token = str.substr(prevOffset, offset-prevOffset); + prevOffset = offset + delim.length(); + + tempVec.push_back(stof(token.c_str())); + } while (offset != string::npos); + + // assign values + for (const auto val : tempVec) + { + vec.push_back(val); + } +} + // these wrappers have the benefit that changing the location of the variable (gameinitoptionscreen/ini/ingame options) doesn't require huge changes throughout the code // additionally, turning off a feature (for UB, for MP...) can be done here without additional checks in the code bool UsingNewInventorySystem() @@ -2319,6 +2356,9 @@ void LoadGameExternalOptions() gGameExternalOptions.fMiniEventsEnabled = iniReader.ReadBoolean("Mini Events Settings", "MINI_EVENTS_ENABLED", FALSE); gGameExternalOptions.fMiniEventsMinHoursBetweenEvents = iniReader.ReadInteger("Mini Events Settings", "MINI_EVENTS_MIN_HOURS_BETWEEN_EVENTS", 120, 24, 24000); gGameExternalOptions.fMiniEventsMaxHoursBetweenEvents = iniReader.ReadInteger("Mini Events Settings", "MINI_EVENTS_MAX_HOURS_BETWEEN_EVENTS", 240, 24, 24000); + + // Rebel Command + gGameExternalOptions.fRebelCommandEnabled = iniReader.ReadBoolean("Rebel Command Settings", "REBEL_COMMAND_ENABLED", FALSE); } @@ -3804,6 +3844,95 @@ void LoadCreaturesSettings() gCreaturesSettings.ubCrepitusFeedingSectorZ = iniReader.ReadInteger("Creatures Settings", "CREPITUS_FEEDING_SECTOR_Z", 2); } +void LoadRebelCommandSettings() +{ + CIniReader iniReader(REBEL_COMMAND_SETTINGS_FILE); + + gRebelCommandSettings.fIncomeModifier = iniReader.ReadFloat("Rebel Command Settings", "INCOME_MODIFIER", 1.5f, 1.0f, 100.0f); + + gRebelCommandSettings.iMaxLoyaltyNovice = iniReader.ReadInteger("Rebel Command Settings", "MAX_LOYALTY_NOVICE", 80, 20, 100); + gRebelCommandSettings.iMaxLoyaltyExperienced = iniReader.ReadInteger("Rebel Command Settings", "MAX_LOYALTY_EXPERIENCED", 70, 20, 100); + gRebelCommandSettings.iMaxLoyaltyExpert = iniReader.ReadInteger("Rebel Command Settings", "MAX_LOYALTY_EXPERT", 60, 20, 100); + gRebelCommandSettings.iMaxLoyaltyInsane = iniReader.ReadInteger("Rebel Command Settings", "MAX_LOYALTY_INSANE", 50, 20, 100); + + gRebelCommandSettings.iAdminActionCostIncreaseRegional = iniReader.ReadInteger("Rebel Command Settings", "ADMIN_ACTION_COST_INCREASE_REGIONAL", 13, 1, 100); + gRebelCommandSettings.iAdminActionCostIncreaseNational = iniReader.ReadInteger("Rebel Command Settings", "ADMIN_ACTION_COST_INCREASE_NATIONAL", 6, 1, 100); + + gRebelCommandSettings.fLoyaltyGainModifier = iniReader.ReadFloat("Rebel Command Settings", "BASE_LOYALTY_GAIN_MODIFIER", 0.5f, 0.1f, 1.0f); + + std::vector vec; + + // militia upgrades + FillArrayValues(iniReader, "Rebel Command Settings", "MILITIA_STATS_UPGRADE_COSTS", gRebelCommandSettings.iMilitiaUpgradeCosts); + gRebelCommandSettings.iMilitiaStatBonusPerLevel = iniReader.ReadInteger("Rebel Command Settings", "MILITIA_STAT_BONUS_PER_LEVEL", 2, 0, 5); + gRebelCommandSettings.iMilitiaMarksmanshipBonusPerLevel = iniReader.ReadInteger("Rebel Command Settings", "MILITIA_MARKSMANSHIP_BONUS_PER_LEVEL", 2, 0, 5); + + // directives + FillArrayValues(iniReader, "Rebel Command Settings", "GATHER_SUPPLIES_COSTS", gRebelCommandSettings.iGatherSuppliesCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "GATHER_SUPPLIES_INCOME", gRebelCommandSettings.iGatherSuppliesIncome); + + gRebelCommandSettings.uSupportMilitiaProgressRequirement = iniReader.ReadUINT8("Rebel Command Settings", "SUPPORT_MILITIA_PROGRESS_REQUIREMENT", 25, 0, 100); + FillArrayValues(iniReader, "Rebel Command Settings", "SUPPORT_MILITIA_COSTS", gRebelCommandSettings.iSupportMilitiaCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "SUPPORT_MILITIA_DISCOUNT", gRebelCommandSettings.fSupportMilitiaDiscounts); + + gRebelCommandSettings.uTrainMilitiaProgressRequirement = iniReader.ReadUINT8("Rebel Command Settings", "TRAIN_MILITIA_PROGRESS_REQUIREMENT", 10, 0, 100); + FillArrayValues(iniReader, "Rebel Command Settings", "TRAIN_MILITIA_COSTS", gRebelCommandSettings.iTrainMilitiaCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "TRAIN_MILITIA_DISCOUNT", gRebelCommandSettings.fTrainMilitiaDiscount); + FillArrayValues(iniReader, "Rebel Command Settings", "TRAIN_MILITIA_SPEED_BONUS", gRebelCommandSettings.iTrainMilitiaSpeedBonus); + + gRebelCommandSettings.uCreatePropagandaProgressRequirement = iniReader.ReadUINT8("Rebel Command Settings", "CREATE_PROPAGANDA_PROGRESS_REQUIREMENT", 33, 0, 100); + FillArrayValues(iniReader, "Rebel Command Settings", "CREATE_PROPAGANDA_COSTS", gRebelCommandSettings.iCreatePropagandaCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "CREATE_PROPAGANDA_MODIFIER", gRebelCommandSettings.fCreatePropagandaModifier); + + gRebelCommandSettings.uEliteMilitiaProgressRequirement = iniReader.ReadUINT8("Rebel Command Settings", "ELITE_MILITIA_PROGRESS_REQUIREMENT", 50, 0, 100); + FillArrayValues(iniReader, "Rebel Command Settings", "ELITE_MILITIA_COSTS", gRebelCommandSettings.iEliteMilitiaCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "ELITE_MILITIA_PER_DAY", gRebelCommandSettings.iEliteMilitiaPerDay); + + gRebelCommandSettings.uHvtStrikesProgressRequirement = iniReader.ReadUINT8("Rebel Command Settings", "HVT_STRIKES_PROGRESS_REQUIREMENT", 33, 0, 100); + FillArrayValues(iniReader, "Rebel Command Settings", "HVT_STRIKES_COSTS", gRebelCommandSettings.iHvtStrikesCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "HVT_STRIKES_CHANCE", gRebelCommandSettings.iHvtStrikesChance); + + gRebelCommandSettings.uSpottersProgressRequirement = iniReader.ReadUINT8("Rebel Command Settings", "SPOTTERS_PROGRESS_REQUIREMENT", 50, 0, 100); + FillArrayValues(iniReader, "Rebel Command Settings", "SPOTTERS_COSTS", gRebelCommandSettings.iSpottersCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "SPOTTERS_MODIFIER", gRebelCommandSettings.iSpottersModifier); + + gRebelCommandSettings.uRaidMinesProgressRequirement = iniReader.ReadUINT8("Rebel Command Settings", "RAID_MINES_PROGRESS_REQUIREMENT", 0, 0, 100); + gRebelCommandSettings.iRaidMinesFailChance = iniReader.ReadInteger("Rebel Command Settings", "RAID_MINES_FAIL_CHANCE", 15, 0, 100); + FillArrayValues(iniReader, "Rebel Command Settings", "RAID_MINES_COSTS", gRebelCommandSettings.iRaidMinesCosts); + FillArrayValues(iniReader, "Rebel Command Settings", "RAID_MINES_PERCENTAGE", gRebelCommandSettings.fRaidMinesPercentage); + + // admin actions + gRebelCommandSettings.iSupplyLineMaxLoyaltyIncrease = iniReader.ReadInteger("Rebel Command Settings", "SUPPLY_LINE_MAX_LOYALTY_INCREASE", 10, 1, 100); + + gRebelCommandSettings.iRebelRadioDailyLoyaltyGain = iniReader.ReadInteger("Rebel Command Settings", "REBEL_RADIO_DAILY_LOYALTY_GAIN", 400, 1, 10000); + + gRebelCommandSettings.iSafehouseReinforceChance = iniReader.ReadUINT32("Rebel Command Settings", "SAFEHOUSE_REINFORCE_CHANCE", 75, 0, 100); + gRebelCommandSettings.iSafehouseMinimumSoldiers = iniReader.ReadInteger("Rebel Command Settings", "SAFEHOUSE_MINIMUM_SOLDIERS", 2, 0, 10); + gRebelCommandSettings.iSafehouseBonusSoldiers = iniReader.ReadInteger("Rebel Command Settings", "SAFEHOUSE_BONUS_SOLDIERS", 4, 0, 10); + + gRebelCommandSettings.iSupplyDisruptionEnemyStatLoss = iniReader.ReadInteger("Rebel Command Settings", "SUPPLY_DISRUPTION_ENEMY_STAT_LOSS", 5, 0, 100); + + // SCOUTS - no variable effect, but included here for completeness + + gRebelCommandSettings.iDeadDropsDailyIntel = iniReader.ReadInteger("Rebel Command Settings", "DEAD_DROPS_DAILY_INTEL", 25, 0, 100); + + gRebelCommandSettings.iSmugglersDailySupplies = iniReader.ReadInteger("Rebel Command Settings", "SMUGGLERS_DAILY_SUPPLIES", 25, 0, 100); + + gRebelCommandSettings.iWarehousesDailyMilitiaGuns = iniReader.ReadInteger("Rebel Command Settings", "WAREHOUSES_DAILY_MILITIA_RESOURCE_GUNS", 2, 0, 100); + gRebelCommandSettings.iWarehousesDailyMilitiaArmour = iniReader.ReadInteger("Rebel Command Settings", "WAREHOUSES_DAILY_MILITIA_RESOURCE_ARMOUR", 2, 0, 100); + gRebelCommandSettings.iWarehousesDailyMilitiaMisc = iniReader.ReadInteger("Rebel Command Settings", "WAREHOUSES_DAILY_MILITIA_RESOURCE_MISC", 2, 0, 100); + + gRebelCommandSettings.iTaxesDailyIncome = iniReader.ReadInteger("Rebel Command Settings", "TAXES_DAILY_INCOME", 500, 0, 10000); + gRebelCommandSettings.iTaxesDailyLoyaltyLoss = iniReader.ReadInteger("Rebel Command Settings", "TAXES_DAILY_LOYALTY_LOSS", 250, 0, 10000); + + gRebelCommandSettings.iAssistCiviliansDailyVolunteers = iniReader.ReadInteger("Rebel Command Settings", "ASSIST_CIVILIANS_DAILY_VOLUNTEERS", 10, 0, 100); + + gRebelCommandSettings.iMercSupportBonus = iniReader.ReadInteger("Rebel Command Settings", "MERC_SUPPORT_BONUS", 25, 0, 100); + + gRebelCommandSettings.iMiningPolicyBonus = iniReader.ReadInteger("Rebel Command Settings", "MINING_POLICY_BONUS", 10, 0, 100); + +} + void FreeGameExternalOptions() { } diff --git a/GameSettings.h b/GameSettings.h index ab97c8f3..ba5e425e 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1584,6 +1584,9 @@ typedef struct UINT16 fMiniEventsMinHoursBetweenEvents; UINT16 fMiniEventsMaxHoursBetweenEvents; + // Rebel Command + BOOLEAN fRebelCommandEnabled; + } GAME_EXTERNAL_OPTIONS; typedef struct @@ -1685,6 +1688,90 @@ typedef struct UINT8 ubCrepitusFeedingSectorZ; } CREATURES_SETTINGS; +typedef struct +{ + FLOAT fIncomeModifier; + + INT8 iMaxLoyaltyNovice; + INT8 iMaxLoyaltyExperienced; + INT8 iMaxLoyaltyExpert; + INT8 iMaxLoyaltyInsane; + + INT16 iAdminActionCostIncreaseRegional; + INT16 iAdminActionCostIncreaseNational; + + FLOAT fLoyaltyGainModifier; + INT32 iMilitiaStatBonusPerLevel; + INT32 iMilitiaMarksmanshipBonusPerLevel; + std::vector iMilitiaUpgradeCosts; + + // directives + // this directive is always available + std::vector iGatherSuppliesCosts; + std::vector iGatherSuppliesIncome; + + UINT8 uSupportMilitiaProgressRequirement; + std::vector iSupportMilitiaCosts; + std::vector fSupportMilitiaDiscounts; + + UINT8 uTrainMilitiaProgressRequirement; + std::vector iTrainMilitiaCosts; + std::vector fTrainMilitiaDiscount; + std::vector iTrainMilitiaSpeedBonus; + + UINT8 uCreatePropagandaProgressRequirement; + std::vector iCreatePropagandaCosts; + std::vector fCreatePropagandaModifier; + + UINT8 uEliteMilitiaProgressRequirement; + std::vector iEliteMilitiaCosts; + std::vector iEliteMilitiaPerDay; + + UINT8 uHvtStrikesProgressRequirement; + std::vector iHvtStrikesCosts; + std::vector iHvtStrikesChance; + + UINT8 uSpottersProgressRequirement; + std::vector iSpottersCosts; + std::vector iSpottersModifier; + + UINT8 uRaidMinesProgressRequirement; + INT32 iRaidMinesFailChance; + std::vector iRaidMinesCosts; + std::vector fRaidMinesPercentage; + + // admin actions + INT32 iSupplyLineMaxLoyaltyIncrease; + + INT32 iRebelRadioDailyLoyaltyGain; + + UINT32 iSafehouseReinforceChance; + INT32 iSafehouseMinimumSoldiers; + INT32 iSafehouseBonusSoldiers; + + INT32 iSupplyDisruptionEnemyStatLoss; + + // SCOUTS - no variable effect, but included here for completeness + + INT32 iDeadDropsDailyIntel; + + INT32 iSmugglersDailySupplies; + + INT32 iWarehousesDailyMilitiaGuns; + INT32 iWarehousesDailyMilitiaArmour; + INT32 iWarehousesDailyMilitiaMisc; + + INT32 iTaxesDailyIncome; + INT32 iTaxesDailyLoyaltyLoss; + + INT32 iAssistCiviliansDailyVolunteers; + + INT32 iMercSupportBonus; + + INT32 iMiningPolicyBonus; + +} REBELCOMMAND_SETTINGS; + typedef struct { UINT8 ubMaxNumberOfTraits; @@ -2458,6 +2545,8 @@ extern REPUTATION_SETTINGS gReputationSettings; extern CREATURES_SETTINGS gCreaturesSettings; +extern REBELCOMMAND_SETTINGS gRebelCommandSettings; + // HEADROCK HAM 4: CTH constants read from a separate INI file extern CTH_CONSTANTS gGameCTHConstants; @@ -2479,6 +2568,7 @@ void LoadHelicopterRepairRefuelSettings(); void LoadMoraleSettings(); void LoadReputationSettings(); void LoadCreaturesSettings(); +void LoadRebelCommandSettings(); void FreeGameExternalOptions(); void InitGameOptions(); diff --git a/GameVersion.h b/GameVersion.h index 4fa11cd9..05d965f9 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 REBELCOMMAND 183 #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 REBELCOMMAND //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Laptop/DropDown.h b/Laptop/DropDown.h index 42ca005b..dd5e36de 100644 --- a/Laptop/DropDown.h +++ b/Laptop/DropDown.h @@ -144,6 +144,8 @@ enum definedDropDowns DROPDOWN_MILTIAWEBSITE_FILTER_RANK, DROPDOWN_MILTIAWEBSITE_FILTER_ORIGIN, DROPDOWN_MILTIAWEBSITE_FILTER_SECTOR, + + DROPDOWN_REBEL_COMMAND_DIRECTIVE, }; /* diff --git a/Laptop/Laptop All.h b/Laptop/Laptop All.h index 4ddb5f4f..c2efeeb9 100644 --- a/Laptop/Laptop All.h +++ b/Laptop/Laptop All.h @@ -141,4 +141,5 @@ #include "BriefingRoom_Data.h" #include "Encyclopedia_new.h" #include "Encyclopedia_Data_new.h" +#include "Rebel Command.h" #endif \ No newline at end of file diff --git a/Laptop/finances.h b/Laptop/finances.h index 259bdde0..6233155c 100644 --- a/Laptop/finances.h +++ b/Laptop/finances.h @@ -60,6 +60,7 @@ enum WORKERS_TRAINED, // Flugente: train workers PROMOTE_MILITIA, // Flugente: drill militia MINI_EVENT, // rftr: mini events + REBEL_COMMAND, // rftr: rebel command TEXT_NUM_FINCANCES }; diff --git a/Laptop/laptop.cpp b/Laptop/laptop.cpp index a4880188..60262c7e 100644 --- a/Laptop/laptop.cpp +++ b/Laptop/laptop.cpp @@ -93,6 +93,7 @@ #include "MilitiaWebsite.h" // added by Flugente #include "Intelmarket.h" // added by Flugente #include "FacilityProduction.h" // added by Flugente + #include "Rebel Command.h" #endif #include "connect.h" @@ -1081,6 +1082,11 @@ INT32 EnterLaptop() SetBookMark( PRODUCTION_BOOKMARK ); else RemoveBookmark( PRODUCTION_BOOKMARK ); + + if (gGameExternalOptions.fRebelCommandEnabled && gubQuest[QUEST_FOOD_ROUTE] == QUESTDONE) + SetBookMark( REBELCOMMAND_BOOKMARK ); + else + RemoveBookmark( REBELCOMMAND_BOOKMARK ); } LoadLoadPending( ); @@ -1531,6 +1537,10 @@ void RenderLaptop() case LAPTOP_MODE_FACILITY_PRODUCTION: RenderFacilityProduction(); break; + + case LAPTOP_MODE_REBEL_COMMAND: + RebelCommand::RenderWebsite(); + break; } if( guiCurrentLaptopMode >= LAPTOP_MODE_WWW ) @@ -2011,6 +2021,10 @@ void EnterNewLaptopMode() case LAPTOP_MODE_FACILITY_PRODUCTION: EnterFacilityProduction(); break; + + case LAPTOP_MODE_REBEL_COMMAND: + RebelCommand::EnterWebsite(); + break; } // first time using webbrowser in this laptop session @@ -2306,6 +2320,10 @@ void HandleLapTopHandles() case LAPTOP_MODE_FACILITY_PRODUCTION: HandleFacilityProduction(); break; + + case LAPTOP_MODE_REBEL_COMMAND: + RebelCommand::HandleWebsite(); + break; } } @@ -2908,6 +2926,10 @@ UINT32 ExitLaptopMode(UINT32 uiMode) case LAPTOP_MODE_FACILITY_PRODUCTION: ExitFacilityProduction(); break; + + case LAPTOP_MODE_REBEL_COMMAND: + RebelCommand::ExitWebsite(); + break; } if( ( uiMode != LAPTOP_MODE_NONE )&&( uiMode < LAPTOP_MODE_WWW ) ) @@ -4594,6 +4616,27 @@ void GoToWebPage(INT32 iPageId ) } } break; + + case REBELCOMMAND_BOOKMARK: + { + guiCurrentWWWMode = LAPTOP_MODE_REBEL_COMMAND; + guiCurrentLaptopMode = LAPTOP_MODE_REBEL_COMMAND; + + // do we have to have a World Wide Wait + if ( LaptopSaveInfo.fVisitedBookmarkAlready[REBELCOMMAND_BOOKMARK] == FALSE ) + { + // reset flag and set load pending flag + LaptopSaveInfo.fVisitedBookmarkAlready[REBELCOMMAND_BOOKMARK] = TRUE; + fLoadPendingFlag = TRUE; + } + else + { + // fast reload + fLoadPendingFlag = TRUE; + fFastLoadFlag = TRUE; + } + } + break; } #ifdef JA2UB diff --git a/Laptop/laptop.h b/Laptop/laptop.h index b2cadc80..a558dd1b 100644 --- a/Laptop/laptop.h +++ b/Laptop/laptop.h @@ -186,6 +186,8 @@ enum LAPTOP_MODE_AIM_MEMBERS_ARCHIVES_NEW, + LAPTOP_MODE_REBEL_COMMAND, + LAPTOP_MODE_MAX, }; @@ -255,6 +257,7 @@ enum{ MILITIAROSTER_BOOKMARK, // added by Flugente INTELMARKET_BOOKMARK, // added by Flugente PRODUCTION_BOOKMARK, // added by Flugente + REBELCOMMAND_BOOKMARK, TEXT_NUM_LAPTOP_BOOKMARKS }; diff --git a/MainMenuScreen.cpp b/MainMenuScreen.cpp index be1b7489..cf511e56 100644 --- a/MainMenuScreen.cpp +++ b/MainMenuScreen.cpp @@ -393,6 +393,8 @@ void InitDependingGameStyleOptions() LoadReputationSettings(); // Load creatures settings LoadCreaturesSettings(); + // Load rebel command settings + LoadRebelCommandSettings(); #ifdef JA2UB LoadGameUBOptions(); // JA25 UB diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 8473d3a9..8c55362d 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -118,6 +118,7 @@ #include "PMC.h" // added by Flugente #include "ASD.h" // added by Flugente #include "MilitiaIndividual.h" // added by Flugente + #include "Rebel Command.h" #endif #include "BobbyR.h" @@ -4499,6 +4500,12 @@ BOOLEAN SaveGame( int ubSaveGameID, STR16 pGameDesc ) goto FAILED_TO_SAVE; } + if (!RebelCommand::Save(hFile)) + { + ScreenMsg( FONT_MCOLOR_WHITE, MSG_ERROR, L"ERROR writing rebel command data" ); + goto FAILED_TO_SAVE; + } + //Close the saved game file FileClose( hFile ); @@ -6362,6 +6369,18 @@ BOOLEAN LoadSavedGame( int ubSavedGameID ) InitIndividualMilitiaData(); } + uiRelEndPerc += 1; + SetRelativeStartAndEndPercentage( 0, uiRelStartPerc, uiRelEndPerc, L"Load rebel command data..." ); + RenderProgressBar( 0, 100 ); + uiRelStartPerc = uiRelEndPerc; + + if ( !RebelCommand::Load( hFile ) ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Rebel Command data Load failed" ) ); + FileClose( hFile ); + return(FALSE); + } + #if LOADSAVEGAME_LOGTIME if ( fp_timelog ) { diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index e83cbfc8..d07b35e8 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -76,6 +76,7 @@ #include "ASD.h" // added by Flugente #include "Strategic AI.h" #include "MiniEvents.h" + #include "Rebel Command.h" #endif #include #include @@ -6214,7 +6215,7 @@ void HandleTrainingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) // a normal training session costs gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier // it promotes gGameExternalOptions.iTrainingSquadSize militia with gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular points each // thus a point costs gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier / ( gGameExternalOptions.iTrainingSquadSize * gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular) points - FLOAT costperpoint = (FLOAT)( gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier / ( gGameExternalOptions.iTrainingSquadSize * gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular ) ); + FLOAT costperpoint = (FLOAT)( RebelCommand::GetMilitiaTrainingCostModifier() * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier / ( gGameExternalOptions.iTrainingSquadSize * gGameExternalOptions.usIndividualMilitia_PromotionPoints_To_Regular ) ); FLOAT totalcost = drillpoints * costperpoint; @@ -9209,6 +9210,9 @@ INT16 GetTownTrainPtsForCharacter( SOLDIERTYPE *pTrainer, UINT16 *pusMaxPts ) sTrainingBonus += gGameExternalOptions.ubRpcBonusToTrainMilitia; } + // apply training bonus from rebel command + sTrainingBonus += RebelCommand::GetMilitiaTrainingSpeedBonus(); + // HEADROCK HAM 3.5: Training bonus given by local facilities if (pTrainer->bSectorZ == 0) { diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index 08dd4efa..2ac75605 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -72,6 +72,7 @@ #include "CampaignStats.h" // added by Flugente #include "DynamicDialogue.h" // added by Flugente #include "MilitiaIndividual.h" // added by Flugente + #include "Rebel Command.h" #endif #include "Reinforcement.h" @@ -2191,6 +2192,13 @@ void CreateAutoResolveInterface() ubRegMilitia = MilitiaInSectorOfRank( gpAR->ubSectorX, gpAR->ubSectorY, REGULAR_MILITIA ); ubGreenMilitia = MilitiaInSectorOfRank( gpAR->ubSectorX, gpAR->ubSectorY, GREEN_MILITIA ); + // see if we get any bonus militia from nearby towns + UINT8 bonusGreenMilitia = 0, bonusRegularMilitia = 0, bonusEliteMilitia = 0; + RebelCommand::GetBonusMilitia(gpAR->ubSectorX, gpAR->ubSectorY, bonusGreenMilitia, bonusRegularMilitia, bonusEliteMilitia, FALSE); // no need to create a group for autoresolve as we're just increasing local militia pop + ubEliteMilitia += bonusEliteMilitia; + ubRegMilitia += bonusRegularMilitia; + ubGreenMilitia += bonusGreenMilitia; + // This block should be unnecessary. If the counts do not line up, there is a bug. #if 0 while( ubEliteMilitia + ubRegMilitia + ubGreenMilitia < gpAR->ubCivs ) diff --git a/Strategic/Game Init.cpp b/Strategic/Game Init.cpp index 50540a01..5d81e25d 100644 --- a/Strategic/Game Init.cpp +++ b/Strategic/Game Init.cpp @@ -63,6 +63,7 @@ #include "PMC.h" // added by Flugente #include "ASD.h" // added by Flugente #include "MiniEvents.h" + #include "Rebel Command.h" #endif #include "Vehicles.h" @@ -821,6 +822,8 @@ fFirstTimeInMapScreen = TRUE; InitMiniEvents(); + RebelCommand::Init(); + return( TRUE ); } diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index 6398b920..a7d1d352 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -26,6 +26,7 @@ #include "Isometric Utils.h" // added by Flugente for NOWHERE #include "strategic.h" // added by Flugente #include "message.h" // added by Flugente for ScreenMsg(...) + #include "Rebel Command.h" #endif #include "Luaglobal.h" @@ -156,6 +157,8 @@ CHAR16 zString[128]; HourlyDrugUpdate(); + RebelCommand::HourlyUpdate(); + // WANNE: This check should avoid the resaving of a loaded auto-save game, when entering tactical BOOLEAN doAutoSave = TRUE; if (lastLoadedSaveGameDay == GetWorldDay() && lastLoadedSaveGameHour == GetWorldHour() ) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp new file mode 100644 index 00000000..b9de1122 --- /dev/null +++ b/Strategic/Rebel Command.cpp @@ -0,0 +1,2199 @@ +//#pragma optimize("", off) +/* +Rebel Command +by rftr + +This is a feature that mostly affects the strategic layer of JA2. While the player takes care of the fighting, this feature allows +the rebels to provide passive bonuses that can help out the player in various ways. + +The two new abilities for this feature are national Directives, which are bonuses that are always in effect, and Administrative Actions, +which are regional bonuses that are applied to towns that the player captures. + +A new resource, Supplies, is accumulated passively and is used to purchase and improve Administrative Actions. +Directives can be improved with money. + +At the start of the campaign, this feature is unavailable, but the player gains access to the ARC website as soon as they complete +the food delivery quest for the rebels. + + +How to add a new directive: +- add to the RebelCommandDirectives enum in the header +- add to the RebelCommandDirectivesText enum below +- add strings to text files (szRebelCommandDirectivesText) +- add to GameSettings (gRebelCommandSettings) and RebelCommand_Settings.ini +- add to SetupInfo to read from game settings +- add to switch in DailyUpdate (for completeness) +- add to switch in GetDirectiveEffect for website description + +How to add a new admin action: +- add to the RebelCommandAdminActions enum in the header +- add strings to text files (szRebelCommandAdminActionsText) +- add to DailyUpdate (for completeness) +- add to GameSettings (gRebelCommandSettings) and RebelCommand_Settings.ini +- add to SetupInfo to read from game settings +- add to Init to add to pool of valid actions on game start + +Points of interest: +- Init() - set up rebel command for the first time +- SetupInfo() - set constants +- RenderWebsite() - draw the website +- RebelCommandSaveInfo - pretty much everything important is in here + +*/ +#ifdef PRECOMPILEDHEADERS +#include "Laptop All.h" +#include "Strategic All.h" +#else +#include "Rebel Command.h" + +#include "Button System.h" +#include "Campaign.h" +#include "Campaign Types.h" +#include "Cheats.h" +#include "Cursors.h" +#include "DropDown.h" +#include "english.h" +#include "finances.h" +#include "Font Control.h" +#include "Game Clock.h" +#include "GameSettings.h" +#include "GameVersion.h" +#include "input.h" +#include "Line.h" +#include "insurance.h" +#include "laptop.h" +#include "message.h" +#include "MessageBoxScreen.h" +#include "MilitiaIndividual.h" +#include "mousesystem.h" +#include "Queen Command.h" +#include "random.h" +#include "SaveLoadGame.h" +#include "strategicmap.h" +#include "Strategic Mines.h" +#include "Strategic Movement.h" +#include "Strategic Town Loyalty.h" +#include "Text.h" +#include "Town Militia.h" +#include "Utilities.h" +#include "WCheck.h" +#include "WordWrap.h" +#endif + +#define DIRECTIVE_TEXT(id) RCDT_##id##, RCDT_##id##_EFFECT, RCDT_##id##_DESC, RCDT_##id##_IMPROVE, + +#define REBEL_COMMAND_DROPDOWN DropDownTemplate::getInstance() + +#define WEBSITE_LEFT LAPTOP_SCREEN_UL_X +#define WEBSITE_TOP LAPTOP_SCREEN_WEB_UL_Y + 3 +#define WEBSITE_WIDTH 500 +#define WEBSITE_HEIGHT 395 + +extern UINT32 gCoolnessBySector[256]; +extern UINT32 guiInsuranceBackGround; +extern BOOLEAN gfTownUsesLoyalty[MAX_TOWNS]; + +namespace RebelCommand +{ +void DEBUG_DAY(); +void DEBUG_PRINT(); + +enum WebsiteState +{ + RCS_NATIONAL_OVERVIEW, + RCS_REGIONAL_OVERVIEW, +}; + +enum RebelCommandText // keep this synced with szRebelCommandText in the text files +{ + RCT_NATIONAL_OVERVIEW = 0, + RCT_REGIONAL_OVERVIEW, + RCT_SWITCH_TO_REGIONAL, + RCT_SWITCH_TO_NATIONAL, + RCT_SUPPLIES, + RCT_INCOMING_SUPPLIES, + RCT_PER_DAY, + RCT_CURRENT_DIRECTIVE, + RCT_IMPROVE_DIRECTIVE, + RCT_IMPROVE_DIRECTIVE_PROMPT, + RCT_INSUFFICIENT_FUNDS, + RCT_DIRECTIVE_EFFECT_TIME, + RCT_MILITIA_OVERVIEW, + RCT_MILITIA_GREEN, + RCT_MILITIA_REGULAR, + RCT_MILITIA_ELITE, + RCT_MILITIA_TOTAL, + RCT_MILITIA_VOLUNTEERS, + RCT_MILITIA_RESOURCES, + RCT_MILITIA_RESOURCE_GUNS, + RCT_MILITIA_RESOURCE_ARMOUR, + RCT_MILITIA_RESOURCE_MISC, + RCT_MILITIA_TRAINING_COST, + RCT_MILITIA_UPKEEP_COST, + RCT_MILITIA_TRAINING_SPEED_BONUS, + RCT_MILITIA_COMBAT_BONUSES, + RCT_MILITIA_PHYSICAL_BONUS, + RCT_MILITIA_MARKSMANSHIP_BONUS, + RCT_MILITIA_UPGRADE_STATS, + RCT_MILITIA_UPGRADE_STATS_PROMPT, + RCT_REGION, + RCT_NEXT, + RCT_PREV, + RCT_ADMIN_TEAM, + RCT_NONE, + RCT_ACTIVE, + RCT_INACTIVE, + RCT_LOYALTY, + RCT_LOYALTY_MAX, + RCT_DEPLOY_ADMIN_TEAM, + RCT_REACTIVATE_ADMIN_TEAM, + RCT_CANNOT_DEPLOY_ADMIN_TEAM, + RCT_ADMIN_ACTIONS_TUTORIAL1, + RCT_ADMIN_ACTIONS_TUTORIAL2, + RCT_ADMIN_ACTIONS_TUTORIAL3, + RCT_ADMIN_ACTIONS, + RCT_ADMIN_ACTION_ESTABLISH, + RCT_ADMIN_ACTION_IMPROVE, + RCT_ADMIN_ACTION_TIER, + RCT_ADMIN_ACTION_COST, + RCT_DEAD_DROP_INCOME, + RCT_SMUGGLER_INCOME, + RCT_BONUS_MILITIA_JOINED, + RCT_WEBSITE_AVAILABLE, + RCT_NOT_SAFE_TO_REACTIVATE_ADMIN_TEAM, + RCT_MINE_RAID_SUCCESSFUL, +}; + +enum RebelCommandHelpText // keep this synced with szRebelCommandHelpText in the text files +{ + RCHT_SUPPLIES = 0, + RCHT_SUPPLIES_INCOME, + RCHT_DIRECTIVES, + RCHT_ADMIN_TEAM, + RCHT_MAX_LOYALTY, +}; + +// this must be kept in the same order as RebelCommandDirectives in the header +enum RebelCommandDirectivesText // keep this synced with szRebelCommandDirectivesText in the text files +{ + RCDT_FIRST = -1, + DIRECTIVE_TEXT(GATHER_SUPPLIES) + DIRECTIVE_TEXT(SUPPORT_MILITIA) + DIRECTIVE_TEXT(TRAIN_MILITIA) + DIRECTIVE_TEXT(CREATE_PROPAGANDA) + DIRECTIVE_TEXT(ELITE_MILITIA) + DIRECTIVE_TEXT(HVT_STRIKES) + DIRECTIVE_TEXT(SPOTTERS) + DIRECTIVE_TEXT(RAID_MINES) +}; + +// website functions +template +void ButtonHelper(GUI_BUTTON* btn, INT32 reason, voidFunc onClick); +void ClearAllButtons(); +void ClearAllHelpTextRegions(); +void DeployOrReactivateAdminTeam(INT16 regionId); +void GetDirectiveEffect(const RebelCommandDirectives directive, STR16 text); +INT32 GetDirectiveImprovementCost(const RebelCommandDirectives directive); +void ImproveDirective(const RebelCommandDirectives directiveId); +void PurchaseAdminAction(INT32 regionId, INT32 actionIndex); +void RegionNavNext(); +void RegionNavPrev(); +void RenderHeader(RebelCommandText titleText); +void RenderNationalOverview(); +void RenderRegionalOverview(); +void SetDirectiveDescriptionHelpText(INT32 reason, MOUSE_REGION& region, RebelCommandDirectives text); +void SetRegionHelpText(INT32 reason, MOUSE_REGION& helpTextRegion, RebelCommandHelpText text); +void SetupAdminActionBox(const UINT8 actionIndex, const UINT16 descriptionText, const UINT16 buttonText); +void ToggleWebsiteView(); + +void EvaluateDirectives(); +INT32 GetAdminActionCostForRegion(INT16 regionId); +INT16 GetAdminActionInRegion(INT16 regionId, RebelCommandAdminActions adminAction); +void HandleScouting(); +void SetupInfo(); +void UpgradeMilitiaStats(); + +// buttons +INT32 dbgAdvanceDayBtnId = -1; +INT32 dbgPrintBtnId = -1; +std::vector adminActionBtnIds; +INT32 adminTeamBtnId = -1; +INT32 improveDirectiveBtnId = -1; +INT32 regionNextBtnId = -1; +INT32 regionPrevBtnId = -1; +INT32 viewSwapBtnId = -1; +INT32 upgradeMilitiaStatsBtnId = -1; + +// help text regions +MOUSE_REGION adminTeamHelpTextRegion; +MOUSE_REGION directiveDescriptionHelpTextRegion; +MOUSE_REGION maxLoyaltyHelpTextRegion; +MOUSE_REGION suppliesHelpTextRegion; +MOUSE_REGION suppliesIncomeHelpTextRegion; + +BOOLEAN redraw = FALSE; +Info info; +INT16 iCurrentRegionId = 1; +INT32 iIncomingSuppliesPerDay = 0; +SaveInfo rebelCommandSaveInfo; +WebsiteState websiteState; + +// website +template +void ButtonHelper(GUI_BUTTON* btn, INT32 reason, voidFunc onClick) +{ + if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN) + { + btn->uiFlags |= (BUTTON_CLICKED_ON); + } + else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP && btn->uiFlags & BUTTON_CLICKED_ON) + { + btn->uiFlags &= ~(BUTTON_CLICKED_ON); + + onClick(); + + RenderWebsite(); + } +} + +void ClearAllButtons() +{ + for (const auto btnId : adminActionBtnIds) + { + RemoveButton(btnId); + } + adminActionBtnIds.clear(); + + if (adminTeamBtnId != -1) + { + RemoveButton(adminTeamBtnId); + adminTeamBtnId = -1; + } + + if (improveDirectiveBtnId != -1) + { + RemoveButton(improveDirectiveBtnId); + improveDirectiveBtnId = -1; + } + + if (regionNextBtnId != -1) + { + RemoveButton(regionNextBtnId); + regionNextBtnId = -1; + } + + if (regionPrevBtnId != -1) + { + RemoveButton(regionPrevBtnId); + regionPrevBtnId = -1; + } + + if (viewSwapBtnId != -1) + { + RemoveButton(viewSwapBtnId); + viewSwapBtnId = -1; + } + + if (upgradeMilitiaStatsBtnId != -1) + { + RemoveButton(upgradeMilitiaStatsBtnId); + upgradeMilitiaStatsBtnId = -1; + } + + if (dbgAdvanceDayBtnId != -1) + { + RemoveButton(dbgAdvanceDayBtnId); + dbgAdvanceDayBtnId = -1; + } + + if (dbgPrintBtnId != -1) + { + RemoveButton(dbgPrintBtnId); + dbgPrintBtnId = -1; + } +} + +void ClearAllHelpTextRegions() +{ + MSYS_RemoveRegion(&adminTeamHelpTextRegion); + MSYS_RemoveRegion(&directiveDescriptionHelpTextRegion); + MSYS_RemoveRegion(&maxLoyaltyHelpTextRegion); + MSYS_RemoveRegion(&suppliesHelpTextRegion); + MSYS_RemoveRegion(&suppliesIncomeHelpTextRegion); +} + +void DeployOrReactivateAdminTeam(INT16 regionId) +{ + INT16 numAdminTeams = 0; + // ignore omerta when calculating admin team deployment costs + for (int a = FIRST_TOWN + 1; a < NUM_TOWNS; ++a) + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_NONE) + numAdminTeams++; + + if (rebelCommandSaveInfo.regions[regionId].adminStatus == RAS_INACTIVE) + { + if (IsTownUnderCompleteControlByEnemy(regionId)) + { + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_NOT_SAFE_TO_REACTIVATE_ADMIN_TEAM], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); + return; + } + + const INT32 cost = rebelCommandSaveInfo.regions[regionId].GetAdminReactivateCost(numAdminTeams); + if (rebelCommandSaveInfo.iSupplies < cost) + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); + else + { + rebelCommandSaveInfo.iSupplies -= cost; + rebelCommandSaveInfo.regions[regionId].adminStatus = RAS_ACTIVE; + } + } + else + { + const INT32 cost = rebelCommandSaveInfo.regions[regionId].GetAdminDeployCost(numAdminTeams); + if (rebelCommandSaveInfo.iSupplies < cost) + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); + else + { + rebelCommandSaveInfo.iSupplies -= cost; + rebelCommandSaveInfo.regions[regionId].adminStatus = RAS_ACTIVE; + } + } + +} + +void EvaluateDirectives() +{ + const INT16 newDirective = REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey(); + rebelCommandSaveInfo.iSelectedDirective = newDirective; + iIncomingSuppliesPerDay = CurrentPlayerProgressPercentage() * gRebelCommandSettings.fIncomeModifier + static_cast((newDirective == RCD_GATHER_SUPPLIES ? rebelCommandSaveInfo.directives[RCD_GATHER_SUPPLIES].GetValue1() : 0)); +} + +INT32 GetAdminActionCostForRegion(INT16 regionId) +{ + INT16 totalLocalActions = 0; + INT16 totalNationalActions = 0; + + // ignore omerta when calculating action costs + for (int a = OMERTA+1; a < NUM_TOWNS; ++a) + { + for (int b = 0; b < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++b) + { + totalNationalActions += rebelCommandSaveInfo.regions[a].actionLevels[b]; + + if (a == regionId) + totalLocalActions += rebelCommandSaveInfo.regions[a].actionLevels[b]; + } + } + + return totalNationalActions * gRebelCommandSettings.iAdminActionCostIncreaseNational + totalLocalActions * gRebelCommandSettings.iAdminActionCostIncreaseRegional; +} + +INT16 GetAdminActionInRegion(INT16 regionId, RebelCommandAdminActions adminAction) +{ + if (regionId >= FIRST_TOWN && regionId < NUM_TOWNS) + { + for (int idx = 0; idx < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++idx) + { + if (rebelCommandSaveInfo.regions[regionId].actions[idx] == adminAction) + { + return idx; + } + } + } + + return -1; +} + +void GetDirectiveEffect(const RebelCommandDirectives directive, STR16 text) +{ + switch (directive) + { + case RCD_GATHER_SUPPLIES: + case RCD_CREATE_PROPAGANDA: + case RCD_SUPPORT_MILITIA: + case RCD_ELITE_MILITIA: + case RCD_HVT_STRIKES: + case RCD_SPOTTERS: + case RCD_RAID_MINES: + swprintf(text, szRebelCommandDirectivesText[directive * 4 + 1], rebelCommandSaveInfo.directives[directive].GetValue1()); + break; + + case RCD_TRAIN_MILITIA: + swprintf(text, szRebelCommandDirectivesText[directive * 4 + 1], rebelCommandSaveInfo.directives[directive].GetValue1(), (100.f + rebelCommandSaveInfo.directives[directive].GetValue2()) / 100.f); + break; + + default: + swprintf(text, L"Unrecognised directive id: %d. Do you need to add it to GetDirectiveEffect?", directive); + break; + } +} + +INT32 GetDirectiveImprovementCost(const RebelCommandDirectives directive) +{ + return rebelCommandSaveInfo.directives[directive].GetCostToImprove(); +} + +void ImproveDirective(const RebelCommandDirectives directive) +{ + const INT32 cost = rebelCommandSaveInfo.directives[directive].GetCostToImprove(); + if (cost > LaptopSaveInfo.iCurrentBalance) + { + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); + return; + } + + CHAR16 text[200]; + swprintf(text, szRebelCommandText[RCT_IMPROVE_DIRECTIVE_PROMPT], cost); + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, text, LAPTOP_SCREEN, MSG_BOX_FLAG_YESNO, [](UINT8 exitValue) { + if (exitValue == MSG_BOX_RETURN_YES) + { + const INT16 directive = REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey(); + const INT32 cost = rebelCommandSaveInfo.directives[directive].GetCostToImprove(); + rebelCommandSaveInfo.directives[directive].Improve(); + + LaptopSaveInfo.iCurrentBalance -= cost; + } + }); +} + +void PurchaseAdminAction(INT32 regionId, INT32 actionIndex) +{ + const INT32 cost = GetAdminActionCostForRegion(regionId); + + if (cost > rebelCommandSaveInfo.iSupplies) + { + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); + return; + } + + rebelCommandSaveInfo.regions[regionId].actionLevels[actionIndex]++; + + if (actionIndex == RCAA_SUPPLY_LINE) + { + rebelCommandSaveInfo.regions[regionId].ubMaxLoyalty += static_cast(info.adminActions[RCAA_SUPPLY_LINE].fValue1); + rebelCommandSaveInfo.regions[regionId].ubMaxLoyalty = min(rebelCommandSaveInfo.regions[regionId].ubMaxLoyalty, 100); + } + + rebelCommandSaveInfo.iSupplies -= cost; +} + +void RegionNavNext() +{ + if (websiteState == RCS_REGIONAL_OVERVIEW) + { + do + { + iCurrentRegionId++; + + if (iCurrentRegionId >= NUM_TOWNS) + iCurrentRegionId = 1; + } while (gfTownUsesLoyalty[iCurrentRegionId] == FALSE); + } +} + +void RegionNavPrev() +{ + if (websiteState == RCS_REGIONAL_OVERVIEW) + { + do + { + iCurrentRegionId--; + + if (iCurrentRegionId <= 0) + iCurrentRegionId = NUM_TOWNS - 1; + } while (gfTownUsesLoyalty[iCurrentRegionId] == FALSE); + } +} + +void SetupAdminActionBox(const UINT8 actionIndex, const UINT16 descriptionText, const UINT16 buttonText) +{ + CHAR16 text[200]; + INT16 x; + INT16 y; + + switch (actionIndex % 3) + { + case 0: x = WEBSITE_LEFT + 10; break; + case 1: x = WEBSITE_LEFT + 180; break; + case 2: x = WEBSITE_LEFT + 350; break; + } + + y = WEBSITE_TOP + 140 + 110 * (actionIndex / 3); + + // show label if maxed out + if ((actionIndex == RCAA_SUPPLY_LINE && rebelCommandSaveInfo.regions[iCurrentRegionId].ubMaxLoyalty >= MAX_LOYALTY_VALUE) + || (actionIndex != RCAA_SUPPLY_LINE && rebelCommandSaveInfo.regions[iCurrentRegionId].actionLevels[actionIndex] >= 2)) + { + DrawTextToScreen(szRebelCommandAdminActionsText[buttonText], x, y + 7, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + } + else // show button + { + const UINT8 level = rebelCommandSaveInfo.regions[iCurrentRegionId].actionLevels[actionIndex]; + swprintf(text, szRebelCommandText[level == 0? RCT_ADMIN_ACTION_ESTABLISH : RCT_ADMIN_ACTION_IMPROVE], szRebelCommandAdminActionsText[buttonText]); + const INT32 btnId = CreateTextButton(text, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x, y, 140, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, [btn]() { PurchaseAdminAction(btn->UserData[0], btn->UserData[1]); }); + }); + + Assert(ButtonList[btnId]); + ButtonList[btnId]->UserData[0] = iCurrentRegionId; + ButtonList[btnId]->UserData[1] = actionIndex; + + adminActionBtnIds.push_back(btnId); + } + + y += 22; + swprintf(text, szRebelCommandText[RCT_ADMIN_ACTION_TIER], rebelCommandSaveInfo.regions[iCurrentRegionId].actionLevels[actionIndex] ); + DrawTextToScreen(text, x, y, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + y += 13; + DisplayWrappedString(x, y, 140, 2, FONT10ARIAL, FONT_MCOLOR_BLACK, szRebelCommandAdminActionsText[descriptionText], FONT_MCOLOR_BLACK, FALSE, 0); +} + +void SetDirectiveDescriptionHelpText(INT32 reason, MOUSE_REGION& region, RebelCommandDirectives text) +{ + if (reason == MSYS_CALLBACK_REASON_MOVE) + SetRegionFastHelpText(®ion, szRebelCommandDirectivesText[text]); + else if (reason == MSYS_CALLBACK_REASON_LOST_MOUSE) + SetRegionFastHelpText(®ion, L""); +} + +void SetRegionHelpText(INT32 reason, MOUSE_REGION& helpTextRegion, RebelCommandHelpText text) +{ + if (reason == MSYS_CALLBACK_REASON_MOVE) + SetRegionFastHelpText(&helpTextRegion, szRebelCommandHelpText[text]); + else if (reason == MSYS_CALLBACK_REASON_LOST_MOUSE) + SetRegionFastHelpText(&helpTextRegion, L""); +} + +void ToggleWebsiteView() +{ + if (websiteState == RCS_REGIONAL_OVERVIEW) + websiteState = RCS_NATIONAL_OVERVIEW; + else + websiteState = RCS_REGIONAL_OVERVIEW; +} + +BOOLEAN EnterWebsite() +{ + // make sure we have a valid directive + if (rebelCommandSaveInfo.iActiveDirective < RCD_GATHER_SUPPLIES || rebelCommandSaveInfo.iActiveDirective >= RCD_NUM_DIRECTIVES) + { + rebelCommandSaveInfo.iActiveDirective = RCD_GATHER_SUPPLIES; + rebelCommandSaveInfo.iSelectedDirective = RCD_GATHER_SUPPLIES; + } + + ClearAllButtons(); + + websiteState = RCS_NATIONAL_OVERVIEW; + + VOBJECT_DESC VObjectDesc; + + // load the background (white tile) + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + FilenameForBPP("LAPTOP\\BackGroundTile.sti", VObjectDesc.ImageFile); + AddVideoObject(&VObjectDesc, &guiInsuranceBackGround); + + // set directives list + std::vector> directivesList; + directivesList.push_back(std::make_pair(RCD_GATHER_SUPPLIES, szRebelCommandDirectivesText[RCDT_GATHER_SUPPLIES])); + if (HighestPlayerProgressPercentage() >= gRebelCommandSettings.uSupportMilitiaProgressRequirement) + directivesList.push_back(std::make_pair(RCD_SUPPORT_MILITIA, szRebelCommandDirectivesText[RCDT_SUPPORT_MILITIA])); + if (HighestPlayerProgressPercentage() >= gRebelCommandSettings.uTrainMilitiaProgressRequirement) + directivesList.push_back(std::make_pair(RCD_TRAIN_MILITIA, szRebelCommandDirectivesText[RCDT_TRAIN_MILITIA])); + if (HighestPlayerProgressPercentage() >= gRebelCommandSettings.uCreatePropagandaProgressRequirement) + directivesList.push_back(std::make_pair(RCD_CREATE_PROPAGANDA, szRebelCommandDirectivesText[RCDT_CREATE_PROPAGANDA])); + if (HighestPlayerProgressPercentage() >= gRebelCommandSettings.uEliteMilitiaProgressRequirement) + directivesList.push_back(std::make_pair(RCD_ELITE_MILITIA, szRebelCommandDirectivesText[RCDT_ELITE_MILITIA])); + if (HighestPlayerProgressPercentage() >= gRebelCommandSettings.uHvtStrikesProgressRequirement && gGameExternalOptions.fEnemyRoles == TRUE && gGameExternalOptions.fAssignTraitsToEnemy == TRUE) + directivesList.push_back(std::make_pair(RCD_HVT_STRIKES, szRebelCommandDirectivesText[RCDT_HVT_STRIKES])); + if (HighestPlayerProgressPercentage() >= gRebelCommandSettings.uSpottersProgressRequirement) + directivesList.push_back(std::make_pair(RCD_SPOTTERS, szRebelCommandDirectivesText[RCDT_SPOTTERS])); + if (HighestPlayerProgressPercentage() >= gRebelCommandSettings.uRaidMinesProgressRequirement) + directivesList.push_back(std::make_pair(RCD_RAID_MINES, szRebelCommandDirectivesText[RCDT_RAID_MINES])); + + REBEL_COMMAND_DROPDOWN.SetEntries(directivesList); + REBEL_COMMAND_DROPDOWN.SetHelpText(szRebelCommandHelpText[RCHT_DIRECTIVES]); + REBEL_COMMAND_DROPDOWN.SetSelectedEntryKey(rebelCommandSaveInfo.iSelectedDirective); + + RenderWebsite(); + + return(TRUE); +} + +void ExitWebsite() +{ + ClearAllButtons(); + ClearAllHelpTextRegions(); + REBEL_COMMAND_DROPDOWN.Destroy(); + + DeleteVideoObjectFromIndex(guiInsuranceBackGround); +} + +void HandleWebsite() +{ + InputAtom input; + while (DequeueSpecificEvent(&input, KEY_DOWN | KEY_UP | KEY_REPEAT)) + { + if (input.usEvent == KEY_DOWN) + { + switch (input.usParam) + { + case TAB: + case SPACE: + ToggleWebsiteView(); + redraw = TRUE; + break; + + case 'a': + case LEFTARROW: + RegionNavPrev(); + redraw = TRUE; + break; + + case 'd': + case RIGHTARROW: + RegionNavNext(); + redraw = TRUE; + break; + + default: + HandleKeyBoardShortCutsForLapTop(input.usEvent, input.usParam, input.usKeyState); + break; + } + } + } + + if (redraw) + RenderWebsite(); + + redraw = FALSE; + +} + +void RenderWebsite() +{ + ClearAllButtons(); + ClearAllHelpTextRegions(); + REBEL_COMMAND_DROPDOWN.Destroy(); + + // background + WebPageTileBackground(4, 4, 125, 100, guiInsuranceBackGround); + + SetFontShadow(FONT_MCOLOR_WHITE); + + // national/regional views + switch (websiteState) + { + case RCS_REGIONAL_OVERVIEW: + RenderRegionalOverview(); + break; + + case RCS_NATIONAL_OVERVIEW: + default: + RenderNationalOverview(); + break; + } + + SetFontShadow(DEFAULT_SHADOW); + + MarkButtonsDirty(); + RenderWWWProgramTitleBar(); + InvalidateRegion(WEBSITE_LEFT, WEBSITE_TOP, WEBSITE_LEFT + WEBSITE_WIDTH, WEBSITE_TOP + WEBSITE_HEIGHT); +} + +void RenderHeader(RebelCommandText titleText) +{ + CHAR16 sText[500]; + UINT16 usPosX, usPosY; + + // title + usPosX = WEBSITE_LEFT + 1; + usPosY = WEBSITE_TOP + 3; + DrawTextToScreen(szRebelCommandText[titleText], usPosX, usPosY, 0, FONT16ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // supplies + usPosX = WEBSITE_LEFT + 1; + usPosY = WEBSITE_TOP + 23; + DrawTextToScreen(szRebelCommandText[RCT_SUPPLIES], usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // supply count + usPosX = WEBSITE_LEFT + 50; + usPosY = WEBSITE_TOP + 20; + swprintf(sText, L"%d", rebelCommandSaveInfo.iSupplies); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, rebelCommandSaveInfo.iSupplies > 0 ? FONT_GREEN : FONT_MCOLOR_LTRED, FONT_MCOLOR_BLACK, FALSE, 0); + + // supplies region + MSYS_DefineRegion(&suppliesHelpTextRegion, WEBSITE_LEFT, WEBSITE_TOP + 20, WEBSITE_LEFT + 100, WEBSITE_TOP + 35, MSYS_PRIORITY_HIGH, + CURSOR_LAPTOP_SCREEN, [](MOUSE_REGION* pRegion, INT32 iReason) { SetRegionHelpText(iReason, suppliesHelpTextRegion, RCHT_SUPPLIES); }, MSYS_NO_CALLBACK); + MSYS_AddRegion(&suppliesHelpTextRegion); + MSYS_SetRegionUserData(&suppliesHelpTextRegion, 0, 0); + + // line at the bottom of the header + usPosX = WEBSITE_LEFT - 1; + usPosY = WEBSITE_TOP + 35; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + + // DEBUG + if (CHEATER_CHEAT_LEVEL()) + { + usPosX = WEBSITE_LEFT + 400; + usPosY = WEBSITE_TOP + 380; + dbgAdvanceDayBtnId = CreateTextButton(L"DEBUG MAGIC!", FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 99, 14, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) { + ButtonHelper(btn, reason, []() { DEBUG_DAY(); }); + }); + + usPosY = WEBSITE_TOP + 365; + dbgPrintBtnId = CreateTextButton(L"DEBUG PRINT!", FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 99, 14, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) { + ButtonHelper(btn, reason, []() { DEBUG_PRINT(); }); + }); + } + +} + +void RenderNationalOverview() +{ + CHAR16 sText[500]; + UINT16 usPosX, usPosY; + + // title + RenderHeader(RCT_NATIONAL_OVERVIEW); + + // view swap button + usPosX = WEBSITE_LEFT + 350; + usPosY = WEBSITE_TOP + 1; + viewSwapBtnId = CreateTextButton(szRebelCommandText[RCT_SWITCH_TO_REGIONAL], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 149, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() { ToggleWebsiteView(); }); + }); + + // incoming supplies + usPosX = WEBSITE_LEFT + 1; + usPosY = WEBSITE_TOP + 40; + DrawTextToScreen(szRebelCommandText[RCT_INCOMING_SUPPLIES], usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + usPosX = WEBSITE_LEFT + 5; + usPosY += 10; + swprintf(sText, L"%d", iIncomingSuppliesPerDay); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, iIncomingSuppliesPerDay > 0 ? FONT_GREEN : FONT_MCOLOR_LTRED, FONT_MCOLOR_BLACK, FALSE, 0); + + INT32 width = 0; + INT32 value = iIncomingSuppliesPerDay; + do { + width += value % 10 == 1 ? 6 : 8; + value /= 10; + } while (value != 0); + usPosX += width; + usPosY += 3; + DrawTextToScreen(szRebelCommandText[RCT_PER_DAY], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // incoming supplies help text region + usPosX = WEBSITE_LEFT + 1; + usPosY -= 13; + MSYS_DefineRegion(&suppliesIncomeHelpTextRegion, usPosX, usPosY, usPosX + 100, usPosY + 35, MSYS_PRIORITY_HIGH, + CURSOR_LAPTOP_SCREEN, [](MOUSE_REGION* pRegion, INT32 iReason) { SetRegionHelpText(iReason, suppliesIncomeHelpTextRegion, RCHT_SUPPLIES_INCOME); }, MSYS_NO_CALLBACK); + MSYS_AddRegion(&suppliesIncomeHelpTextRegion); + MSYS_SetRegionUserData(&suppliesIncomeHelpTextRegion, 0, 0); + + // line between incoming supplies and directive + usPosX = WEBSITE_LEFT - 1; + usPosY += 43; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + + // current directive + usPosX = WEBSITE_LEFT + 1; + usPosY += 5; + DrawTextToScreen(szRebelCommandText[RCT_CURRENT_DIRECTIVE], usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // set directives dropdown coords for use later + const INT16 dropdownX = WEBSITE_LEFT + 5; + const INT16 dropdownY = usPosY + 10; + + // improve directive button + usPosX = WEBSITE_LEFT + WEBSITE_WIDTH / 2 + 5; + usPosY = dropdownY; + const INT16 directive = REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey(); + if (rebelCommandSaveInfo.directives[directive].CanImprove()) + { + swprintf(sText, szRebelCommandText[RCT_IMPROVE_DIRECTIVE], GetDirectiveImprovementCost(static_cast(directive))); + improveDirectiveBtnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 200, 24, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, [btn]() { ImproveDirective(static_cast(btn->UserData[0])); }); + }); + + Assert(ButtonList[improveDirectiveBtnId]); + ButtonList[improveDirectiveBtnId]->UserData[0] = REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey(); + } + + // directive effect + usPosX = dropdownX; + usPosY = dropdownY + 27; + GetDirectiveEffect(static_cast(directive), sText); + DisplayWrappedString(usPosX, usPosY, WEBSITE_WIDTH / 2 - 10, 2, FONT10ARIAL, FONT_MCOLOR_BLACK, sText, FONT_MCOLOR_BLACK, FALSE, 0); + + // directives description help text region + MSYS_DefineRegion(&directiveDescriptionHelpTextRegion, usPosX, usPosY, usPosX + WEBSITE_WIDTH / 2 - 5, usPosY + 40, MSYS_PRIORITY_HIGH, + CURSOR_LAPTOP_SCREEN, [](MOUSE_REGION* pRegion, INT32 iReason) { SetDirectiveDescriptionHelpText(iReason, directiveDescriptionHelpTextRegion, static_cast(REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey() * 4 + 2)); }, MSYS_NO_CALLBACK); + MSYS_AddRegion(&directiveDescriptionHelpTextRegion); + MSYS_SetRegionUserData(&directiveDescriptionHelpTextRegion, 0, 0); + + // directive improvement description + usPosX = WEBSITE_LEFT + WEBSITE_WIDTH / 2 + 5; + usPosY = dropdownY + 27; + if (rebelCommandSaveInfo.directives[directive].CanImprove()) + DisplayWrappedString(usPosX, usPosY, WEBSITE_WIDTH / 2 - 5, 2, FONT10ARIAL, FONT_MCOLOR_BLACK, szRebelCommandDirectivesText[directive * 4 + 3], FONT_MCOLOR_BLACK, FALSE, 0); + + // directive change notification, if applicable + usPosX = WEBSITE_LEFT + 5; + usPosY += 50; + if (rebelCommandSaveInfo.iActiveDirective != rebelCommandSaveInfo.iSelectedDirective) + DrawTextToScreen(szRebelCommandText[RCT_DIRECTIVE_EFFECT_TIME], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // line between directive and militia + usPosX = WEBSITE_LEFT - 1; + usPosY += 10; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + + // militia + usPosX = WEBSITE_LEFT + 1; + usPosY += 5; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_OVERVIEW], usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // militia count + UINT16 militiaGreen = 0, militiaRegular = 0, militiaElite = 0; + for (INT16 sX = 1; sX < (MAP_WORLD_X - 1); ++sX) + { + for (INT16 sY = 1; sY < (MAP_WORLD_Y - 1); ++sY) + { + militiaGreen += MilitiaInSectorOfRank(sX, sY, GREEN_MILITIA); + militiaRegular += MilitiaInSectorOfRank(sX, sY, REGULAR_MILITIA); + militiaElite += MilitiaInSectorOfRank(sX, sY, ELITE_MILITIA); + } + } + + // headers + usPosX = WEBSITE_LEFT + 10; + usPosY += 15; + const INT16 militiaY = usPosY; // cache for other militia elements + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_GREEN], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosY = militiaY + 15; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_REGULAR], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosY = militiaY + 30; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_ELITE], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // values + usPosX += 45; + usPosY = militiaY - 2; + swprintf(sText, L"%d", militiaGreen); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_LTGREEN, FONT_MCOLOR_BLACK, FALSE, 0); + usPosY += 15; + swprintf(sText, L"%d", militiaRegular); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_LTBLUE, FONT_MCOLOR_BLACK, FALSE, 0); + usPosY += 15; + swprintf(sText, L"%d", militiaElite); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_DKBLUE, FONT_MCOLOR_BLACK, FALSE, 0); + + // militia volunteer pool, if enabled + if (gGameExternalOptions.fMilitiaVolunteerPool) + { + // draw vertical line + usPosX += 75; + usPosY = militiaY - 3; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + + // header + usPosX += 20; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_VOLUNTEERS], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // value + usPosY += 12; + const INT16 volunteerPool = static_cast(LaptopSaveInfo.dMilitiaVolunteerPool); + swprintf(sText, L"%d", GetVolunteerPool()); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + usPosX += 50; + } + + // militia resources, if enabled + if (gGameExternalOptions.fMilitiaResources && !gGameExternalOptions.fMilitiaUseSectorInventory) + { + // draw vertical line + usPosX += 75; + usPosY = militiaY - 3; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + + // headers + usPosX += 20; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_RESOURCES], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosY += 12; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_RESOURCE_GUNS], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_RESOURCE_ARMOUR], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_RESOURCE_MISC], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // values + usPosX -= 132; + usPosY += 12; + swprintf(sText, L"%.1f", LaptopSaveInfo.dMilitiaGunPool); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_ORANGE, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + swprintf(sText, L"%.1f", LaptopSaveInfo.dMilitiaArmourPool); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_LTKHAKI, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + swprintf(sText, L"%.1f", LaptopSaveInfo.dMilitiaMiscPool); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_LTBLUE, FONT_MCOLOR_BLACK, FALSE, 0); + } + + // line + usPosX = WEBSITE_LEFT + 25; + usPosY = militiaY + 50; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); + + // training cost + usPosX = WEBSITE_LEFT + 10; + usPosY += 15; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_TRAINING_COST], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw vertical line + usPosX += 120; + DisplaySmallColouredLineWithShadow(usPosX, usPosY - 2, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + + // upkeep cost + usPosX += 20; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_UPKEEP_COST], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // upkeep cost per type + usPosY += 12; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_GREEN], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_REGULAR], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_ELITE], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 75; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_TOTAL], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // training cost value + usPosX = WEBSITE_LEFT + 15; + usPosY += 12; + const INT16 cost = static_cast(gGameExternalOptions.iMilitiaTrainingCost * GetMilitiaTrainingCostModifier()); + swprintf(sText, L"$%d", cost); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // upkeep costs + const INT16 costGreen = static_cast(gGameExternalOptions.usDailyCostTown[GREEN_MILITIA] * GetMilitiaUpkeepCostModifier()); + const INT16 costRegular = static_cast(gGameExternalOptions.usDailyCostTown[REGULAR_MILITIA] * GetMilitiaUpkeepCostModifier()); + const INT16 costElite = static_cast(gGameExternalOptions.usDailyCostTown[ELITE_MILITIA] * GetMilitiaUpkeepCostModifier()); + usPosX += 140; + swprintf(sText, L"$%d", costGreen); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + swprintf(sText, L"$%d", costRegular); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 66; + swprintf(sText, L"$%d", costElite); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + usPosX += 75; + swprintf(sText, L"$%d", (costGreen * militiaGreen + costRegular * militiaRegular + costElite * militiaElite)); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // line + usPosX = WEBSITE_LEFT + 25; + usPosY += 30; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); + + // training speed bonus + usPosX = WEBSITE_LEFT + 10; + usPosY += 15; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_TRAINING_SPEED_BONUS], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // training speed bonus value + usPosX += 5; + usPosY += 12; + value = GetMilitiaTrainingSpeedBonus(); + swprintf(sText, L"%d", value); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + width = 0; + do { + width += value % 10 == 1 ? 6 : 8; + value /= 10; + } while (value != 0); + DrawTextToScreen(L"%%", usPosX + width, usPosY + 3, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw vertical line + usPosX = WEBSITE_LEFT + 130; + usPosY -= 12; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + + // militia physical stat bonus + usPosX += 20; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_PHYSICAL_BONUS], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // militia marksmanship bonus + usPosY += 15; + DrawTextToScreen(szRebelCommandText[RCT_MILITIA_MARKSMANSHIP_BONUS], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // physical stat value + usPosX += 120; + usPosY -= 18; + swprintf(sText, L"+%d", gRebelCommandSettings.iMilitiaStatBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // marksmanship value + usPosY += 15; + swprintf(sText, L"+%d", gRebelCommandSettings.iMilitiaMarksmanshipBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // upgrade militia stats button + usPosX = WEBSITE_LEFT + 325; + usPosY -= 15; + if (rebelCommandSaveInfo.iMilitiaStatsLevel < static_cast(gRebelCommandSettings.iMilitiaUpgradeCosts.size())) + { + swprintf(sText, szRebelCommandText[RCT_MILITIA_UPGRADE_STATS], gRebelCommandSettings.iMilitiaUpgradeCosts[rebelCommandSaveInfo.iMilitiaStatsLevel]); + upgradeMilitiaStatsBtnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 150, 25, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) { + ButtonHelper(btn, reason, []() { UpgradeMilitiaStats(); }); + }); + } + + // dropdown - has to be last, or else things after this will be drawn twice + REBEL_COMMAND_DROPDOWN.Create(dropdownX, dropdownY); + REBEL_COMMAND_DROPDOWN.Display(); +} + +void RenderRegionalOverview() +{ + CHAR16 sText[800]; + UINT16 usPosX, usPosY; + + // title + RenderHeader(RCT_REGIONAL_OVERVIEW); + + // view swap button + usPosX = WEBSITE_LEFT + 350; + usPosY = WEBSITE_TOP + 1; + viewSwapBtnId = CreateTextButton(szRebelCommandText[RCT_SWITCH_TO_NATIONAL], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 149, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() { ToggleWebsiteView(); }); + }); + + // region + usPosX = WEBSITE_LEFT + 1; + usPosY = WEBSITE_TOP + 40; + DrawTextToScreen(szRebelCommandText[RCT_REGION], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // next region + usPosX = WEBSITE_LEFT + 300; + regionNextBtnId = CreateTextButton(szRebelCommandText[RCT_NEXT], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 99, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() + { + RegionNavNext(); + }); + }); + + // prev region + usPosX = WEBSITE_LEFT + 400; + regionPrevBtnId = CreateTextButton(szRebelCommandText[RCT_PREV], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 99, 16, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() + { + RegionNavPrev(); + }); + }); + + // region value + usPosX = WEBSITE_LEFT + 5; + usPosY += 12; + swprintf(sText, L"%s", pTownNames[iCurrentRegionId]); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // line between region info and admin info + usPosX = WEBSITE_LEFT - 1; + usPosY += 30; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + + // admin team + usPosX = WEBSITE_LEFT + 1; + usPosY += 5; + DrawTextToScreen(szRebelCommandText[RCT_ADMIN_TEAM], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // admin team status + const RegionAdminStatus adminStatus = rebelCommandSaveInfo.regions[iCurrentRegionId].adminStatus; + usPosX += 10; + usPosY += 12; + switch (adminStatus) + { + case RAS_ACTIVE: + DrawTextToScreen(szRebelCommandText[RCT_ACTIVE], usPosX, usPosY, 0, FONT14ARIAL, FONT_GREEN, FONT_MCOLOR_BLACK, FALSE, 0); + break; + + case RAS_INACTIVE: + DrawTextToScreen(szRebelCommandText[RCT_INACTIVE], usPosX, usPosY, 0, FONT14ARIAL, FONT_ORANGE, FONT_MCOLOR_BLACK, FALSE, 0); + break; + + default: + case RAS_NONE: + DrawTextToScreen(szRebelCommandText[RCT_NONE], usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_RED, FONT_MCOLOR_BLACK, FALSE, 0); + break; + } + + // admin team help text region + usPosX -= 10; + usPosY -= 12; + MSYS_DefineRegion(&adminTeamHelpTextRegion, usPosX, usPosY, usPosX + 100, usPosY + 35, MSYS_PRIORITY_HIGH, + CURSOR_LAPTOP_SCREEN, [](MOUSE_REGION* pRegion, INT32 iReason) { SetRegionHelpText(iReason, adminTeamHelpTextRegion, RCHT_ADMIN_TEAM); }, MSYS_NO_CALLBACK); + MSYS_AddRegion(&adminTeamHelpTextRegion); + MSYS_SetRegionUserData(&adminTeamHelpTextRegion, 0, 0); + + // vertical line between admin team and loyalty + usPosX = WEBSITE_LEFT + 164; + usPosY += 5; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); + + // loyalty + usPosX += 30; + usPosY -= 5; + DrawTextToScreen(szRebelCommandText[RCT_LOYALTY], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // loyalty value + usPosX += 10; + usPosY += 12; + swprintf(sText, L"%d", gTownLoyalty[iCurrentRegionId].ubRating); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + INT32 width = 0; + INT32 value = gTownLoyalty[iCurrentRegionId].ubRating; + do { + width += value % 10 == 1 ? 6 : 8; + value /= 10; + } while (value != 0); + DrawTextToScreen(L"%%", usPosX + width, usPosY + 3, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // vertical line between loyalty and max loyalty + usPosX = WEBSITE_LEFT + 334; + usPosY -= 7; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); + + // max loyalty + usPosX += 30; + usPosY -= 5; + DrawTextToScreen(szRebelCommandText[RCT_LOYALTY_MAX], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // max loyalty value + usPosX += 10; + usPosY += 12; + swprintf(sText, L"%d", rebelCommandSaveInfo.regions[iCurrentRegionId].ubMaxLoyalty); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + width = 0; + value = rebelCommandSaveInfo.regions[iCurrentRegionId].ubMaxLoyalty; + do { + width += value % 10 == 1 ? 6 : 8; + value /= 10; + } while (value != 0); + DrawTextToScreen(L"%%", usPosX + width, usPosY + 3, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // max loyalty region + usPosX -= 10; + usPosY -= 12; + MSYS_DefineRegion(&maxLoyaltyHelpTextRegion, usPosX, usPosY, usPosX + 100, usPosY + 35, MSYS_PRIORITY_HIGH, + CURSOR_LAPTOP_SCREEN, [](MOUSE_REGION* pRegion, INT32 iReason) { SetRegionHelpText(iReason, maxLoyaltyHelpTextRegion, RCHT_MAX_LOYALTY); }, MSYS_NO_CALLBACK); + MSYS_AddRegion(&maxLoyaltyHelpTextRegion); + MSYS_SetRegionUserData(&maxLoyaltyHelpTextRegion, 0, 0); + + // deploy/reactivate admin teams (if applicable) + // if we're displaying any of these, early exit since everything else is locked behind the admin team's deployment + if (iCurrentRegionId == OMERTA) + { + // omerta displays the tutorial about regional bonuses + usPosX = WEBSITE_LEFT + 100; + usPosY = WEBSITE_TOP + 150; + INT16 height = DisplayWrappedString(usPosX, usPosY, 300, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_ADMIN_ACTIONS_TUTORIAL1], FONT_MCOLOR_BLACK, FALSE, 0); + + usPosY += height + 15; + height = DisplayWrappedString(usPosX, usPosY, 300, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_ADMIN_ACTIONS_TUTORIAL2], FONT_MCOLOR_BLACK, FALSE, 0); + + usPosY += height + 15; + height = DisplayWrappedString(usPosX, usPosY, 300, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_ADMIN_ACTIONS_TUTORIAL3], FONT_MCOLOR_BLACK, FALSE, 0); + + return; + } + else if (!gTownLoyalty[iCurrentRegionId].fStarted || gTownLoyalty[iCurrentRegionId].ubRating == 0) + { + usPosX = WEBSITE_LEFT + 150; + usPosY = WEBSITE_TOP + 175; + DisplayWrappedString(usPosX, usPosY, 200, 2, FONT10ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_CANNOT_DEPLOY_ADMIN_TEAM], FONT_MCOLOR_BLACK, FALSE, 0); + + return; + } + else if (rebelCommandSaveInfo.regions[iCurrentRegionId].adminStatus == RAS_NONE) + { + INT16 numAdminTeams = 0; + for (int a = FIRST_TOWN + 1; a < NUM_TOWNS; ++a) + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_NONE) + numAdminTeams++; + const INT32 adminDeployCost = rebelCommandSaveInfo.regions[iCurrentRegionId].GetAdminDeployCost(numAdminTeams); + + // deploy admin team button (if no team deployed) + usPosX = WEBSITE_LEFT + 100; + usPosY = WEBSITE_TOP + 150; + swprintf(sText, szRebelCommandText[RCT_DEPLOY_ADMIN_TEAM], adminDeployCost); + adminTeamBtnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 300, 100, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, [btn]() { DeployOrReactivateAdminTeam(btn->UserData[0]); }); + }); + + Assert(ButtonList[adminTeamBtnId]); + ButtonList[adminTeamBtnId]->UserData[0] = iCurrentRegionId; + + return; + } + else if (rebelCommandSaveInfo.regions[iCurrentRegionId].adminStatus == RAS_INACTIVE) + { + INT16 numAdminTeams = 0; + for (int a = FIRST_TOWN + 1; a < NUM_TOWNS; ++a) + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_NONE) + numAdminTeams++; + const INT32 adminReactivateCost = rebelCommandSaveInfo.regions[iCurrentRegionId].GetAdminReactivateCost(numAdminTeams); + + // reactivate team button (when retaking a lost town) + usPosX = WEBSITE_LEFT + 100; + usPosY = WEBSITE_TOP + 150; + swprintf(sText, szRebelCommandText[RCT_REACTIVATE_ADMIN_TEAM], adminReactivateCost / 2); + adminTeamBtnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 300, 100, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, [btn]() { DeployOrReactivateAdminTeam(btn->UserData[0]); }); + }); + + Assert(ButtonList[adminTeamBtnId]); + ButtonList[adminTeamBtnId]->UserData[0] = iCurrentRegionId; + + return; + } + + // line between region info and admin info + usPosX = WEBSITE_LEFT - 1; + usPosY += 30; + DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + + // admin actions + usPosX = WEBSITE_LEFT + 1; + usPosY += 5; + DrawTextToScreen(szRebelCommandText[RCT_ADMIN_ACTIONS], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // setup action boxes (max 6) + UINT8 actionCount = 0; + for (int a = 0; a < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++a) + { + const RebelCommandAdminActions action = static_cast(rebelCommandSaveInfo.regions[iCurrentRegionId].actions[a]); + if (rebelCommandSaveInfo.regions[iCurrentRegionId].actions[a] != RCAA_NONE) + { + SetupAdminActionBox(actionCount++, action * 2 + 1, action * 2); + } + } + + // admin upgrade cost + usPosX = WEBSITE_LEFT + 5; + usPosY = WEBSITE_TOP + WEBSITE_HEIGHT - 15; + swprintf(sText, szRebelCommandText[RCT_ADMIN_ACTION_COST], GetAdminActionCostForRegion(iCurrentRegionId)); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); +} +// end website + +void ApplyEnemyPenalties(SOLDIERTYPE* pSoldier) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + const auto applyPenalties = [](SOLDIERTYPE* pSoldier, UINT8 level) + { + pSoldier->stats.bLife -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bLifeMax -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bAgility -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bDexterity -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bStrength -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bWisdom -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bLeadership -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bMarksmanship -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bMechanical -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bExplosive -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->stats.bMedical -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->bBreath -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + pSoldier->bBreathMax -= static_cast(info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level); + + pSoldier->stats.bLife = static_cast(max(25, pSoldier->stats.bLife)); + pSoldier->stats.bLifeMax = static_cast(max(25, pSoldier->stats.bLifeMax)); + pSoldier->stats.bAgility = static_cast(max(25, pSoldier->stats.bAgility)); + pSoldier->stats.bDexterity = static_cast(max(25, pSoldier->stats.bDexterity)); + pSoldier->stats.bStrength = static_cast(max(25, pSoldier->stats.bStrength)); + pSoldier->stats.bWisdom = static_cast(max(25, pSoldier->stats.bStrength)); + pSoldier->stats.bLeadership = static_cast(max(25, pSoldier->stats.bLeadership)); + pSoldier->stats.bMarksmanship = static_cast(max(25, pSoldier->stats.bMarksmanship)); + pSoldier->stats.bMechanical = static_cast(max(25, pSoldier->stats.bMechanical)); + pSoldier->stats.bExplosive = static_cast(max(25, pSoldier->stats.bExplosive)); + pSoldier->stats.bMedical = static_cast(max(25, pSoldier->stats.bMedical)); + pSoldier->bBreath = static_cast(max(25, info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level)); + pSoldier->bBreathMax = static_cast(max(25, info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1 * level)); + }; + + // need to get dist between soldier and town. + // run through all towns, check manhattan distance + for (int a = FIRST_TOWN; a < NUM_TOWNS; ++a) + { + // make sure town has active admins + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_ACTIVE) + continue; + + // make sure action exists in this town + const INT16 index = GetAdminActionInRegion(a, RCAA_SUPPLY_DISRUPTION); + if (index == -1) + continue; + + // and that it's not level 0 + const UINT8 level = rebelCommandSaveInfo.regions[a].actionLevels[index]; + if (level == 0) + continue; + + // get all sectors with this townid + std::vector> sectors; + for (int x = MINIMUM_VALID_X_COORDINATE; x <= MAXIMUM_VALID_X_COORDINATE; ++x) + for (int y = MINIMUM_VALID_Y_COORDINATE; y <= MAXIMUM_VALID_Y_COORDINATE; ++y) + if (GetTownIdForSector(x, y) == a) + sectors.push_back(std::pair(x, y)); + + // check if soldier is within range of the city + for (const auto pair : sectors) + { + const INT16 x = std::get<0>(pair); + const INT16 y = std::get<1>(pair); + + if (abs(x - pSoldier->sSectorX) + abs(y - pSoldier->sSectorY) <= level) + { + applyPenalties(pSoldier, level); + return; + } + } + } +} + +void ApplyMilitiaBonuses(SOLDIERTYPE* pMilitia) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + pMilitia->stats.bLife += (gRebelCommandSettings.iMilitiaStatBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + pMilitia->stats.bLifeMax += (gRebelCommandSettings.iMilitiaStatBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + pMilitia->stats.bAgility += (gRebelCommandSettings.iMilitiaStatBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + pMilitia->stats.bDexterity += (gRebelCommandSettings.iMilitiaStatBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + pMilitia->stats.bStrength += (gRebelCommandSettings.iMilitiaStatBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + pMilitia->stats.bMarksmanship += (gRebelCommandSettings.iMilitiaMarksmanshipBonusPerLevel * rebelCommandSaveInfo.iMilitiaStatsLevel); + + pMilitia->stats.bLife = min(100, pMilitia->stats.bLife); + pMilitia->stats.bLifeMax = min(100, pMilitia->stats.bLifeMax); + pMilitia->stats.bAgility = min(100, pMilitia->stats.bAgility); + pMilitia->stats.bDexterity = min(100, pMilitia->stats.bDexterity); + pMilitia->stats.bStrength = min(100, pMilitia->stats.bStrength); + pMilitia->stats.bMarksmanship = min(100, pMilitia->stats.bMarksmanship); +} + +UINT8 GetApproximateEnemyLocationResolutionIndex() +{ + return static_cast(rebelCommandSaveInfo.directives[RCD_SPOTTERS].GetValue1()); +} + +FLOAT GetAssignmentBonus(INT16 x, INT16 y) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return 0.f; + + const UINT8 townId = GetTownIdForSector(x, y); + + // make sure town has active admins + if (rebelCommandSaveInfo.regions[townId].adminStatus != RAS_ACTIVE) + return 0.f; + + const INT16 index = GetAdminActionInRegion(townId, RCAA_MERC_SUPPORT); + FLOAT value = 0.f; + + if (index >= 0) + { + const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + value += info.adminActions[RCAA_MERC_SUPPORT].fValue1 * level; + } + + return value/100.f; +} + +INT32 GetMiningPolicyBonus(INT16 townId) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return 0; + + // make sure town has active admins + if (rebelCommandSaveInfo.regions[townId].adminStatus != RAS_ACTIVE) + return 0; + + const INT16 index = GetAdminActionInRegion(townId, RCAA_MINING_POLICY); + + if (index >= 0) + { + const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + return static_cast(info.adminActions[RCAA_MINING_POLICY].fValue1 * level); + } + + return 0; +} + +void GetBonusMilitia(INT16 sx, INT16 sy, UINT8& green, UINT8& regular, UINT8& elite, BOOLEAN createGroup) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + // chance for militia to show up + if (Random(100) >= gRebelCommandSettings.iSafehouseReinforceChance) + return; + + const auto createBonusMilitia = [sx, sy, &green, ®ular, &elite, createGroup](UINT8 level) + { + if (level == 1) + { + green = static_cast(info.adminActions[RCAA_SAFEHOUSES].fValue1 + Random(static_cast(1 + info.adminActions[RCAA_SAFEHOUSES].fValue2))); + regular = Random(2); + elite = 0; + } + else if (level == 2) + { + green = 0; + regular = static_cast(info.adminActions[RCAA_SAFEHOUSES].fValue1 + Random(static_cast(1 + info.adminActions[RCAA_SAFEHOUSES].fValue2))); + elite = Random(2); + } + + for (int a = 0; a < max(green, max(regular, elite)); ++a) + { + if (a < green) + CreateNewIndividualMilitia(GREEN_MILITIA, MO_ARULCO, SECTOR(sx, sy)); + + if (a < regular) + CreateNewIndividualMilitia(REGULAR_MILITIA, MO_ARULCO, SECTOR(sx, sy)); + + if (a < elite) + CreateNewIndividualMilitia(ELITE_MILITIA, MO_ARULCO, SECTOR(sx, sy)); + } + + if (createGroup) + { + // randomise entry direction + std::vector> vec; + if (sx > MINIMUM_VALID_X_COORDINATE) + vec.push_back(std::pair(-1,0)); + if (sx < MAXIMUM_VALID_X_COORDINATE) + vec.push_back(std::pair(1,0)); + if (sy > MINIMUM_VALID_Y_COORDINATE) + vec.push_back(std::pair(0,-1)); + if (sy < MAXIMUM_VALID_Y_COORDINATE) + vec.push_back(std::pair(0,1)); + const UINT8 dir = Random(vec.size()); + const INT16 xmod = static_cast(std::get<0>(vec[dir])); + const INT16 ymod = static_cast(std::get<1>(vec[dir])); + + const GROUP* group = CreateNewMilitiaGroupDepartingFromSector(SECTOR(sx+xmod, sy+ymod), green, regular, elite); + + PlaceGroupInSector(group->ubGroupID, group->ubSectorX, group->ubSectorY, sx, sy, 0, FALSE); // no need to check for a battle we're jumping into + + gTacticalStatus.uiFlags |= WANT_MILITIA_REINFORCEMENTS; + } + + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szRebelCommandText[RCT_BONUS_MILITIA_JOINED]); + }; + + BOOLEAN found = FALSE; + for (int a = FIRST_TOWN; a < NUM_TOWNS; ++a) + { + // make sure town has active admins + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_ACTIVE) + continue; + + // make sure action exists in this town + const INT16 index = GetAdminActionInRegion(a, RCAA_SAFEHOUSES); + if (index == -1) + continue; + + // and that it's not level 0 + const UINT8 level = rebelCommandSaveInfo.regions[a].actionLevels[index]; + if (level == 0) + continue; + + // get all sectors with this townid + std::vector> sectors; + for (int x = MINIMUM_VALID_X_COORDINATE; x <= MAXIMUM_VALID_X_COORDINATE; ++x) + for (int y = MINIMUM_VALID_Y_COORDINATE; y <= MAXIMUM_VALID_Y_COORDINATE; ++y) + if (GetTownIdForSector(x, y) == a) + sectors.push_back(std::pair(x, y)); + + // check if sector is within range of the city + for (const auto pair : sectors) + { + const INT16 x = std::get<0>(pair); + const INT16 y = std::get<1>(pair); + + if (abs(x - sx) + abs(y - sy) <= level) + { + if (level == 2) + { + createBonusMilitia(level); + return; + } + + // let's keep searching to see if we are in range of a level 2 bonus + found = TRUE; + } + } + } + + if (found) + createBonusMilitia(1); +} + +FLOAT GetLoyaltyGainModifier() +{ + if (gGameExternalOptions.fRebelCommandEnabled) + return gRebelCommandSettings.fLoyaltyGainModifier * (rebelCommandSaveInfo.iActiveDirective == RCD_CREATE_PROPAGANDA ? rebelCommandSaveInfo.directives[RCD_CREATE_PROPAGANDA].GetValue1() : 1.f); + + return 1.f; +} + +UINT8 GetMaxTownLoyalty(INT8 townId) +{ + if (gGameExternalOptions.fRebelCommandEnabled) + return rebelCommandSaveInfo.regions[townId].ubMaxLoyalty; + + return MAX_LOYALTY_VALUE; +} + +INT16 GetMilitiaTrainingSpeedBonus() +{ + if (gGameExternalOptions.fRebelCommandEnabled && rebelCommandSaveInfo.iActiveDirective == RCD_TRAIN_MILITIA) + return static_cast(rebelCommandSaveInfo.directives[RCD_TRAIN_MILITIA].GetValue2()); + + return 0; +} + +FLOAT GetMilitiaTrainingCostModifier() +{ + if (gGameExternalOptions.fRebelCommandEnabled && rebelCommandSaveInfo.iActiveDirective == RCD_TRAIN_MILITIA) + return rebelCommandSaveInfo.directives[RCD_TRAIN_MILITIA].GetValue1(); + + return 1.f; +} + +FLOAT GetMilitiaUpkeepCostModifier() +{ + if (gGameExternalOptions.fRebelCommandEnabled && rebelCommandSaveInfo.iActiveDirective == RCD_SUPPORT_MILITIA) + return rebelCommandSaveInfo.directives[RCD_SUPPORT_MILITIA].GetValue1(); + + return 1.f; +} + +void HandleScouting() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + // get towns that have scouting + std::vector> townSectors; + for (INT16 x = MINIMUM_VALID_X_COORDINATE; x <= MAXIMUM_VALID_X_COORDINATE; ++x) + { + for (INT16 y = MINIMUM_VALID_Y_COORDINATE; y < MAXIMUM_VALID_Y_COORDINATE; ++y) + { + const UINT8 townId = GetTownIdForSector(x, y); + // not a town + if (townId < FIRST_TOWN || townId >= NUM_TOWNS) + continue; + + // no admin team + if (rebelCommandSaveInfo.regions[townId].adminStatus != RAS_ACTIVE) + continue; + + const INT16 index = GetAdminActionInRegion(townId, RCAA_SCOUTS); + + // action doesn't exist in region + if (index == -1) + continue; + + // no levels in region + const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + if (level == 0) + continue; + + // scouting range is level+1, since by default militia can see tiles adjacent to them + townSectors.push_back(std::tuple(x, y, level+1)); + } + } + + // run through all sectors, and see if they're within scouting range of a town + for (int x = MINIMUM_VALID_X_COORDINATE; x <= MAXIMUM_VALID_X_COORDINATE; ++x) + { + for (int y = MINIMUM_VALID_Y_COORDINATE; y <= MAXIMUM_VALID_Y_COORDINATE; ++y) + { + for (const auto trio : townSectors) + { + const INT16 sx = std::get<0>(trio); + const INT16 sy = std::get<1>(trio); + const INT16 range = std::get<2>(trio); + + if (abs(x - sx) + abs(y - sy) <= range) + { + if (NumNonPlayerTeamMembersInSector(x, y, ENEMY_TEAM) > 0) + { + SectorInfo[SECTOR(x, y)].uiFlags |= SF_ASSIGN_NOTICED_ENEMIES_HERE; + SectorInfo[SECTOR(x, y)].uiFlags |= SF_ASSIGN_NOTICED_ENEMIES_KNOW_NUMBER; + } + break; + } + } + } + } +} + +BOOLEAN NeutraliseRole(const SOLDIERTYPE* pSoldier) +{ + if (!gGameExternalOptions.fRebelCommandEnabled || !gGameExternalOptions.fEnemyRoles || !gGameExternalOptions.fAssignTraitsToEnemy) + return FALSE; + + if (rebelCommandSaveInfo.iActiveDirective != RCD_HVT_STRIKES) + return FALSE; + + if (!SOLDIER_CLASS_ENEMY(pSoldier->ubSoldierClass)) + return FALSE; + + const UINT32 chance = static_cast(rebelCommandSaveInfo.directives[RCD_HVT_STRIKES].GetValue1()); + + return Random(100) < chance; +} + +void RaidMines(INT32 &playerIncome, INT32 &enemyIncome) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + if (rebelCommandSaveInfo.iActiveDirective != RCD_RAID_MINES) + return; + + if (Random(100) < static_cast(gRebelCommandSettings.iRaidMinesFailChance)) + return; + + INT32 stolenIncome = static_cast(enemyIncome * rebelCommandSaveInfo.directives[RCD_RAID_MINES].GetValue1() * Random(100) / 100.f); + playerIncome += stolenIncome; + enemyIncome -= stolenIncome; + + if (stolenIncome > 0) + { + CHAR16 text[200]; + swprintf(text, szRebelCommandText[RCT_MINE_RAID_SUCCESSFUL], stolenIncome); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); + } +} + +BOOLEAN ShowApproximateEnemyLocations() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return FALSE; + + return rebelCommandSaveInfo.iActiveDirective == RCD_SPOTTERS; +} + +void ShowWebsiteAvailableMessage() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + StopTimeCompression(); + DoMessageBox(MSG_BOX_MINIEVENT_STYLE, szRebelCommandText[RCT_WEBSITE_AVAILABLE], guiCurrentScreen, MSG_BOX_FLAG_OK | MSG_BOX_FLAG_BIGGER, NULL, NULL); +} + +void DailyUpdate() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"DEBUG: ARC selected/active directive: %d/%d", rebelCommandSaveInfo.iSelectedDirective, rebelCommandSaveInfo.iActiveDirective ); + + // make sure we have a valid directive + if (rebelCommandSaveInfo.iActiveDirective < RCD_GATHER_SUPPLIES || rebelCommandSaveInfo.iActiveDirective >= RCD_NUM_DIRECTIVES) + { + rebelCommandSaveInfo.iActiveDirective = RCD_GATHER_SUPPLIES; + rebelCommandSaveInfo.iSelectedDirective = RCD_GATHER_SUPPLIES; + } + + // apply old directive bonus before setting new one + switch (rebelCommandSaveInfo.iActiveDirective) + { + case RCD_GATHER_SUPPLIES: + case RCD_SUPPORT_MILITIA: + case RCD_TRAIN_MILITIA: + case RCD_CREATE_PROPAGANDA: + case RCD_HVT_STRIKES: + case RCD_SPOTTERS: + case RCD_RAID_MINES: + // effects applied elsewhere + break; + + case RCD_ELITE_MILITIA: + const UINT8 elites = static_cast(rebelCommandSaveInfo.directives[RCD_ELITE_MILITIA].GetValue1()); + // get the top-right most omerta tile + INT16 sx = 1, sy = 1; + for (sx = MAXIMUM_VALID_X_COORDINATE; sx >= MINIMUM_VALID_X_COORDINATE; --sx) + { + for (sy = MINIMUM_VALID_Y_COORDINATE; sy <= MAXIMUM_VALID_Y_COORDINATE; ++sy) + { + if (GetTownIdForSector(sx, sy) == OMERTA) + { + goto foundOmerta; + } + } + } + + foundOmerta: + + StrategicAddMilitiaToSector(sx, sy, ELITE_MILITIA, elites); + for (int i = 0 ; i < elites ; ++i) + { + CreateNewIndividualMilitia( ELITE_MILITIA, MO_ARULCO, SECTOR(sx, sy) ); + } + break; + + } + + + // set new directive + const INT16 directive = rebelCommandSaveInfo.iSelectedDirective; + rebelCommandSaveInfo.iActiveDirective = directive; + + // increment supplies + const UINT8 progress = CurrentPlayerProgressPercentage(); + iIncomingSuppliesPerDay = progress * gRebelCommandSettings.fIncomeModifier + static_cast((directive == RCD_GATHER_SUPPLIES ? rebelCommandSaveInfo.directives[RCD_GATHER_SUPPLIES].GetValue1() : 0)); + rebelCommandSaveInfo.iSupplies += iIncomingSuppliesPerDay; + + // get regional bonuses + INT16 intelGain = 0; + INT16 supplyGain = 0; + INT16 moneyGain = 0; + for (int a = FIRST_TOWN; a < NUM_TOWNS; ++a) + { + // check to see if the town is lost + if (IsTownUnderCompleteControlByEnemy(a) && rebelCommandSaveInfo.regions[a].adminStatus == RAS_ACTIVE) + rebelCommandSaveInfo.regions[a].adminStatus = RAS_INACTIVE; + + // ignore this region if there is no active admin team + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_ACTIVE) + continue; + + UINT32 coolness = 0; + // clunky... get town coolness. just get the top/left most sector + for (int x = MINIMUM_VALID_X_COORDINATE ; x <= MAXIMUM_VALID_X_COORDINATE ; ++x) + { + for(int y = MINIMUM_VALID_Y_COORDINATE ; y < MAXIMUM_VALID_Y_COORDINATE ; ++y) + { + if (GetTownIdForSector(x, y) == a) + { + coolness = gCoolnessBySector[SECTOR(x, y)]; + goto foundCoolness; + } + } + } + foundCoolness: + coolness = max(coolness, 1); + + for (int b = 0; b < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++b) + { + const INT8 level = rebelCommandSaveInfo.regions[a].actionLevels[b]; + switch (static_cast(rebelCommandSaveInfo.regions[a].actions[b])) + { + case RCAA_SUPPLY_LINE: + // no daily bonuses + break; + + case RCAA_REBEL_RADIO: + IncrementTownLoyalty(a, static_cast(info.adminActions[RCAA_REBEL_RADIO].fValue1 * level)); + break; + + case RCAA_SAFEHOUSES: + // no daily bonuses + break; + + case RCAA_SUPPLY_DISRUPTION: + // no daily bonuses + break; + + case RCAA_SCOUTS: + // no daily bonuses + break; + + case RCAA_DEAD_DROPS: + intelGain += (Random(static_cast(info.adminActions[RCAA_DEAD_DROPS].fValue1)) * level); + break; + + case RCAA_SMUGGLERS: + supplyGain += static_cast((Random(static_cast(info.adminActions[RCAA_SMUGGLERS].fValue1)) * level)); + break; + + case RCAA_WAREHOUSES: + AddResources( + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue1 * level * Random(100) / 100.f), + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue2 * level * Random(100) / 100.f), + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue3 * level * Random(100) / 100.f)); + break; + + case RCAA_TAXES: + moneyGain += static_cast(info.adminActions[RCAA_TAXES].fValue1 * coolness * level * level); + DecrementTownLoyalty(a, static_cast(info.adminActions[RCAA_TAXES].fValue2 * level)); + break; + + case RCAA_ASSIST_CIVILIANS: + AddVolunteers(static_cast(info.adminActions[RCAA_ASSIST_CIVILIANS].fValue1 * level * Random(100) / 100.f)); + break; + + case RCAA_MERC_SUPPORT: + // no daily bonuses + break; + + case RCAA_MINING_POLICY: + // no daily bonuses + break; + + default: + AssertMsg(false, "Unknown Admin Action"); + break; + } + } + } + + CHAR16 text[200]; + if (intelGain > 0) + { + swprintf(text, szRebelCommandText[RCT_DEAD_DROP_INCOME], intelGain); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); + + AddIntel(intelGain, FALSE); + } + + if (supplyGain > 0) + { + swprintf(text, szRebelCommandText[RCT_SMUGGLER_INCOME], supplyGain); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text ); + + rebelCommandSaveInfo.iSupplies += supplyGain; + } + + if (moneyGain > 0) + { + AddTransactionToPlayersBook(REBEL_COMMAND, 0, GetWorldTotalMin(), moneyGain); + } +} + +void HourlyUpdate() +{ + HandleScouting(); + + // it's midnight! do the daily update + if (GetWorldHour() == 0) + { + DailyUpdate(); + } +} + +void Init() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + INT8 startingMaxLoyalty; + + switch (gGameOptions.ubDifficultyLevel) + { + case DIF_LEVEL_EASY: + startingMaxLoyalty = gRebelCommandSettings.iMaxLoyaltyNovice; + break; + + case DIF_LEVEL_HARD: + startingMaxLoyalty = gRebelCommandSettings.iMaxLoyaltyExpert; + break; + + case DIF_LEVEL_INSANE: + startingMaxLoyalty = gRebelCommandSettings.iMaxLoyaltyInsane; + break; + + case DIF_LEVEL_MEDIUM: + default: + startingMaxLoyalty = gRebelCommandSettings.iMaxLoyaltyExperienced; + break; + } + + // set base values + iIncomingSuppliesPerDay = CurrentPlayerProgressPercentage() * gRebelCommandSettings.fIncomeModifier; + rebelCommandSaveInfo.iSelectedDirective = RCD_GATHER_SUPPLIES; + rebelCommandSaveInfo.iActiveDirective = RCD_GATHER_SUPPLIES; + rebelCommandSaveInfo.iMilitiaStatsLevel = 0; + // let's be nice and give some supplies to people who enable this feature partway through a campaign so they don't start from zero + rebelCommandSaveInfo.iSupplies = GetWorldDay() * CurrentPlayerProgressPercentage() * gRebelCommandSettings.fIncomeModifier / 3; + + // initialise admin actions -- first one is always supply line + std::vector actions; + actions.push_back(RCAA_REBEL_RADIO); + actions.push_back(RCAA_SAFEHOUSES); + actions.push_back(RCAA_SUPPLY_DISRUPTION); + actions.push_back(RCAA_SCOUTS); + actions.push_back(RCAA_SMUGGLERS); + actions.push_back(RCAA_TAXES); + actions.push_back(RCAA_MERC_SUPPORT); + if (gGameExternalOptions.fMilitiaResources == TRUE) + actions.push_back(RCAA_WAREHOUSES); + if (gGameExternalOptions.fIntelResource == TRUE) + actions.push_back(RCAA_DEAD_DROPS); + if (gGameExternalOptions.fMilitiaVolunteerPool == TRUE) + actions.push_back(RCAA_ASSIST_CIVILIANS); + // RCAA_MINING_POLICY is added below in the region init + + SetupInfo(); + + for (int d = 0 ; d < RCD_NUM_DIRECTIVES ; ++d) + { + rebelCommandSaveInfo.directives[d].id = static_cast(d); + rebelCommandSaveInfo.directives[d].iLevel = 0; + } + + // init regions + for (int a = FIRST_TOWN; a < NUM_TOWNS; ++a) + { + // init max loyalty + if (a == OMERTA) + { + // as rebel hq, omerta gets 100% max loyalty and an admin team + rebelCommandSaveInfo.regions[OMERTA].adminStatus = RAS_ACTIVE; + rebelCommandSaveInfo.regions[OMERTA].ubMaxLoyalty = MAX_LOYALTY_VALUE; + } + else + { + rebelCommandSaveInfo.regions[a].ubMaxLoyalty = startingMaxLoyalty; + gTownLoyalty[a].ubRating = min(gTownLoyalty[a].ubRating, startingMaxLoyalty); + } + + // init admins + rebelCommandSaveInfo.regions[a].adminStatus = RAS_NONE; + + // init admin actions per region. each region has supply line + 5 random actions + std::vector vec(actions); + + // check to see if this town has a mine - if it does, add it to this region's admin action pool + if (GetMineSectorForTown(a) != -1) + vec.push_back(RCAA_MINING_POLICY); + + // randomise pool + for (size_t z = 0; z < vec.size(); ++z) + { + const int randomIndex = Random(vec.size()); + std::swap(vec[randomIndex], vec[z]); + } + vec.resize(5); + std::sort(vec.begin(), vec.end()); + for (int b = 0; b < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++b) + { + if (b == 0) + rebelCommandSaveInfo.regions[a].actions[0] = RCAA_SUPPLY_LINE; // first action is always supply line + else + rebelCommandSaveInfo.regions[a].actions[b] = vec[b - 1]; + + rebelCommandSaveInfo.regions[a].actionLevels[b] = 0; + } + } +} + +BOOLEAN Load(HWFILE file) +{ + if (guiCurrentSaveGameVersion >= REBELCOMMAND) + { + UINT32 numBytesRead = 0; + + numBytesRead = FileRead(file, &rebelCommandSaveInfo, sizeof(RebelCommand::SaveInfo), &numBytesRead); + + SetupInfo(); + } + else + { + Init(); + } + + return TRUE; +} + +BOOLEAN Save(HWFILE file) +{ + UINT32 uiNumBytesWritten = 0; + + if (!FileWrite(file, &rebelCommandSaveInfo, sizeof(RebelCommand::SaveInfo), &uiNumBytesWritten)) + return FALSE; + + return TRUE; +} + +void SetupInfo() +{ + iCurrentRegionId = 1; + + const auto toFloatVec = [](const std::vector intVec, std::vector& floatVec) + { + floatVec.clear(); + for (const auto val : intVec) + floatVec.push_back(static_cast(val)); + }; + + // initialise directives + Directive d; + info.directives.clear(); + + d.iCostToImprove = gRebelCommandSettings.iGatherSuppliesCosts; + toFloatVec(gRebelCommandSettings.iGatherSuppliesIncome, d.fValue1); + d.fValue2.clear(); + info.directives.insert(info.directives.begin() + RCD_GATHER_SUPPLIES, d); + + d.iCostToImprove = gRebelCommandSettings.iSupportMilitiaCosts; + d.fValue1 = gRebelCommandSettings.fSupportMilitiaDiscounts; + d.fValue2.clear(); + info.directives.insert(info.directives.begin() + RCD_SUPPORT_MILITIA, d); + + d.iCostToImprove = gRebelCommandSettings.iTrainMilitiaCosts; + d.fValue1 = gRebelCommandSettings.fTrainMilitiaDiscount; + toFloatVec(gRebelCommandSettings.iTrainMilitiaSpeedBonus, d.fValue2); + info.directives.insert(info.directives.begin() + RCD_TRAIN_MILITIA, d); + + d.iCostToImprove = gRebelCommandSettings.iCreatePropagandaCosts; + d.fValue1 = gRebelCommandSettings.fCreatePropagandaModifier; + d.fValue2.clear(); + info.directives.insert(info.directives.begin() + RCD_CREATE_PROPAGANDA, d); + + d.iCostToImprove = gRebelCommandSettings.iEliteMilitiaCosts; + toFloatVec(gRebelCommandSettings.iEliteMilitiaPerDay, d.fValue1); + d.fValue2.clear(); + info.directives.insert(info.directives.begin() + RCD_ELITE_MILITIA, d); + + d.iCostToImprove = gRebelCommandSettings.iHvtStrikesCosts; + toFloatVec(gRebelCommandSettings.iHvtStrikesChance, d.fValue1); + d.fValue2.clear(); + info.directives.insert(info.directives.begin() + RCD_HVT_STRIKES, d); + + d.iCostToImprove = gRebelCommandSettings.iSpottersCosts; + toFloatVec(gRebelCommandSettings.iSpottersModifier, d.fValue1); + d.fValue2.clear(); + info.directives.insert(info.directives.begin() + RCD_SPOTTERS, d); + + d.iCostToImprove = gRebelCommandSettings.iRaidMinesCosts; + d.fValue1 = gRebelCommandSettings.fRaidMinesPercentage; + d.fValue2.clear(); + info.directives.insert(info.directives.begin() + RCD_RAID_MINES, d); + + // init admin actions + AdminAction aa; + info.adminActions.clear(); + + aa.fValue1 = static_cast(gRebelCommandSettings.iSupplyLineMaxLoyaltyIncrease); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_SUPPLY_LINE, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iRebelRadioDailyLoyaltyGain); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_REBEL_RADIO, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iSafehouseMinimumSoldiers); + aa.fValue2 = static_cast(gRebelCommandSettings.iSafehouseBonusSoldiers); + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_SAFEHOUSES, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iSupplyDisruptionEnemyStatLoss); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_SUPPLY_DISRUPTION, aa); + + aa.fValue1 = 0.f; + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_SCOUTS, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iDeadDropsDailyIntel); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_DEAD_DROPS, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iSmugglersDailySupplies); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_SMUGGLERS, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iWarehousesDailyMilitiaGuns); + aa.fValue2 = static_cast(gRebelCommandSettings.iWarehousesDailyMilitiaArmour); + aa.fValue3 = static_cast(gRebelCommandSettings.iWarehousesDailyMilitiaMisc); + info.adminActions.insert(info.adminActions.begin() + RCAA_WAREHOUSES, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iTaxesDailyIncome); + aa.fValue2 = static_cast(gRebelCommandSettings.iTaxesDailyLoyaltyLoss); + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_TAXES, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iAssistCiviliansDailyVolunteers); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_ASSIST_CIVILIANS, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iMercSupportBonus); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_MERC_SUPPORT, aa); + + aa.fValue1 = static_cast(gRebelCommandSettings.iMiningPolicyBonus); + aa.fValue2 = 0.f; + aa.fValue3 = 0.f; + info.adminActions.insert(info.adminActions.begin() + RCAA_MINING_POLICY, aa); +} + +void UpgradeMilitiaStats() +{ + const INT32 cost = gRebelCommandSettings.iMilitiaUpgradeCosts[rebelCommandSaveInfo.iMilitiaStatsLevel]; + if (cost > LaptopSaveInfo.iCurrentBalance) + { + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); + return; + } + + CHAR16 text[200]; + swprintf(text, szRebelCommandText[RCT_MILITIA_UPGRADE_STATS_PROMPT], cost); + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, text, LAPTOP_SCREEN, MSG_BOX_FLAG_YESNO, [](UINT8 exitValue) { + if (exitValue == MSG_BOX_RETURN_YES) + { + const INT32 cost = gRebelCommandSettings.iMilitiaUpgradeCosts[rebelCommandSaveInfo.iMilitiaStatsLevel++]; + + LaptopSaveInfo.iCurrentBalance -= cost; + } + }); +} + +void DEBUG_DAY() +{ + DailyUpdate(); +} + +void DEBUG_PRINT() +{ + CHAR16 text[500]; + swprintf(text, L"radio_loyalty[%.0f] safehouse_chance/min/bon[%d, %.0f, %.0f] ", info.adminActions[RCAA_REBEL_RADIO].fValue1, gRebelCommandSettings.iSafehouseReinforceChance, info.adminActions[RCAA_SAFEHOUSES].fValue1, info.adminActions[RCAA_SAFEHOUSES].fValue2); + swprintf(text, L"%s supply_dis[%.0f] deaddrops[%.0f] smugglers[%.0f]", text, info.adminActions[RCAA_SUPPLY_DISRUPTION].fValue1, info.adminActions[RCAA_DEAD_DROPS].fValue1, info.adminActions[RCAA_SMUGGLERS].fValue1); + swprintf(text, L"%s warehouse[%.2f/%.2f/%.2f]", text, info.adminActions[RCAA_WAREHOUSES].fValue1, info.adminActions[RCAA_WAREHOUSES].fValue2, info.adminActions[RCAA_WAREHOUSES].fValue3); + swprintf(text, L"%s tax_inc/loy[%.0f/%.0f]", text, info.adminActions[RCAA_TAXES].fValue1, info.adminActions[RCAA_TAXES].fValue2); + swprintf(text, L"%s volunteers[%.0f] support[%.0f]", text, info.adminActions[RCAA_ASSIST_CIVILIANS].fValue1, info.adminActions[RCAA_MERC_SUPPORT].fValue1); + swprintf(text, L"%s minebonus[%0.1f]", text, info.adminActions[RCAA_MINING_POLICY].fValue1); + DoMessageBox(MSG_BOX_MINIEVENT_STYLE, text, guiCurrentScreen, MSG_BOX_FLAG_OK | MSG_BOX_FLAG_BIGGER, NULL, NULL); +} + +} + +template<> void DropDownTemplate::SetRefresh() { RebelCommand::EvaluateDirectives(); RebelCommand::redraw = TRUE; } + + diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h new file mode 100644 index 00000000..f409b3ac --- /dev/null +++ b/Strategic/Rebel Command.h @@ -0,0 +1,146 @@ +#ifndef REBEL_COMMAND_H +#define REBEL_COMMAND_H + +#include "mapscreen.h" +#include "Soldier Control.h" +#include "Types.h" + +#define REBEL_COMMAND_MAX_ACTIONS_PER_REGION 6 + +namespace RebelCommand +{ + +enum RebelCommandDirectives +{ + RCD_NONE = -1, + RCD_GATHER_SUPPLIES = 0, + RCD_SUPPORT_MILITIA, + RCD_TRAIN_MILITIA, + RCD_CREATE_PROPAGANDA, + RCD_ELITE_MILITIA, + RCD_HVT_STRIKES, + RCD_SPOTTERS, + RCD_RAID_MINES, + + RCD_NUM_DIRECTIVES +}; + +enum RebelCommandAdminActions +{ + RCAA_NONE = -1, + RCAA_SUPPLY_LINE = 0, + RCAA_REBEL_RADIO, + RCAA_SAFEHOUSES, + RCAA_SUPPLY_DISRUPTION, + RCAA_SCOUTS, + RCAA_DEAD_DROPS, + RCAA_SMUGGLERS, + RCAA_WAREHOUSES, + RCAA_TAXES, + RCAA_ASSIST_CIVILIANS, + RCAA_MERC_SUPPORT, + RCAA_MINING_POLICY, + + RCAA_NUM_ACTIONS +}; + +enum RegionAdminStatus +{ + RAS_NONE, + RAS_ACTIVE, + RAS_INACTIVE +}; + +typedef struct Directive { + std::vector iCostToImprove; + std::vector fValue1; + std::vector fValue2; + + INT32 GetCostToImprove(INT8 currentLevel) { return iCostToImprove[currentLevel]; } + FLOAT GetValue1(INT8 currentLevel) { return fValue1[currentLevel]; } + FLOAT GetValue2(INT8 currentLevel) { return fValue2[currentLevel]; } +} Directive; + +typedef struct AdminAction { + FLOAT fValue1; + FLOAT fValue2; + FLOAT fValue3; +} AdminAction; + +typedef struct Info { + std::vector directives; + std::vector adminActions; +} Info; + +extern Info info; + +typedef struct DirectiveSaveInfo { + INT8 iLevel = 0; + RebelCommandDirectives id = RCD_NONE; + + BOOLEAN CanImprove() { return id != RCD_NONE && (size_t)iLevel < info.directives[id].iCostToImprove.size() && info.directives[id].GetCostToImprove(iLevel); } + void Improve() { iLevel++; } + INT32 GetCostToImprove() { return info.directives[id].GetCostToImprove(iLevel); } + FLOAT GetValue1() { return info.directives[id].GetValue1(iLevel); } + FLOAT GetValue2() { return info.directives[id].GetValue2(iLevel); } +} DirectiveSaveInfo; + +typedef struct RegionSaveInfo +{ + RegionAdminStatus adminStatus = RAS_NONE; + RebelCommandAdminActions actions[REBEL_COMMAND_MAX_ACTIONS_PER_REGION] = { RCAA_SUPPLY_LINE, RCAA_NONE, RCAA_NONE, RCAA_NONE, RCAA_NONE, RCAA_NONE, }; + UINT8 actionLevels[REBEL_COMMAND_MAX_ACTIONS_PER_REGION] = { 0, 0, 0, 0, 0, 0 }; + UINT8 ubMaxLoyalty = 50; + + INT32 GetAdminDeployCost(INT16 numAdminTeams) { return 10 * numAdminTeams * numAdminTeams; }; + INT32 GetAdminReactivateCost(INT16 numAdminTeams) { return GetAdminDeployCost(numAdminTeams) / 4; }; +} RegionSaveInfo; + +typedef struct SaveInfo +{ + RegionSaveInfo regions[MAX_TOWNS]; + DirectiveSaveInfo directives[20]; + + INT32 iSupplies = 0; + INT32 iActiveDirective = RCD_GATHER_SUPPLIES; + INT32 iSelectedDirective = RCD_GATHER_SUPPLIES; + INT8 iMilitiaStatsLevel = 0; + + INT8 filler[20]; +} SaveInfo; + +extern SaveInfo rebelCommandSaveInfo; + +BOOLEAN EnterWebsite(); +void ExitWebsite(); +void RenderWebsite(); +void HandleWebsite(); + +void ApplyEnemyPenalties(SOLDIERTYPE* pSoldier); +void ApplyMilitiaBonuses(SOLDIERTYPE* pMilitia); +UINT8 GetApproximateEnemyLocationResolutionIndex(); +FLOAT GetAssignmentBonus(INT16 x, INT16 y); +INT32 GetMiningPolicyBonus(INT16 townId); +void GetBonusMilitia(INT16 x, INT16 y, UINT8& green, UINT8& regular, UINT8& elite, BOOLEAN createGroup); +FLOAT GetLoyaltyGainModifier(); +UINT8 GetMaxTownLoyalty(INT8 townId); +INT16 GetMilitiaTrainingSpeedBonus(); +FLOAT GetMilitiaTrainingCostModifier(); +FLOAT GetMilitiaUpkeepCostModifier(); +BOOLEAN NeutraliseRole(const SOLDIERTYPE* pSoldier); +void RaidMines(INT32 &playerIncome, INT32 &enemyIncome); +BOOLEAN ShowApproximateEnemyLocations(); +void ShowWebsiteAvailableMessage(); + +void DailyUpdate(); +void HourlyUpdate(); +void Init(); +BOOLEAN Load(HWFILE file); +BOOLEAN Save(HWFILE file); + +} + +//BOOLEAN LoadRebelCommand( HWFILE file ) { return RebelCommand::Load( file ); } + +#endif + diff --git a/Strategic/Strategic All.h b/Strategic/Strategic All.h index a16433a4..f0234cc7 100644 --- a/Strategic/Strategic All.h +++ b/Strategic/Strategic All.h @@ -228,4 +228,5 @@ #include "Debug Control.h" #include "expat.h" #include "MiniEvents.h" +#include "Rebel Command.h" #endif \ No newline at end of file diff --git a/Strategic/Strategic Event Handler.cpp b/Strategic/Strategic Event Handler.cpp index 917e97dc..7fa19180 100644 --- a/Strategic/Strategic Event Handler.cpp +++ b/Strategic/Strategic Event Handler.cpp @@ -30,6 +30,7 @@ #include "Town Militia.h" // added by Flugente #include "Campaign.h" // added by Flugente #include "Strategic AI.h" + #include "Rebel Command.h" #endif #include "Luaglobal.h" @@ -741,6 +742,8 @@ void HandleNPCSystemEvent( UINT32 uiEvent ) { EndQuest( QUEST_FOOD_ROUTE, 10, MAP_ROW_A ); SetFactTrue( FACT_FOOD_QUEST_OVER ); + + RebelCommand::ShowWebsiteAvailableMessage(); } break; case NPC_ACTION_DELAYED_MAKE_BRENDA_LEAVE: diff --git a/Strategic/Strategic Mines.cpp b/Strategic/Strategic Mines.cpp index 2788674b..19816871 100644 --- a/Strategic/Strategic Mines.cpp +++ b/Strategic/Strategic Mines.cpp @@ -23,6 +23,7 @@ #include "history.h" #include "Facilities.h" #include "ASD.h" // added by Flugente + #include "Rebel Command.h" #endif #include "GameInitOptionsScreen.h" @@ -693,8 +694,7 @@ void HandleIncomeFromMines( void ) INT32 iIncome = 0; INT32 iIncome_Enemy = 0; // Flugente: new AI gets money from mines - // HEADROCK HAM 3.6: Modifier from Facilities - INT32 iFacilityModifier = 0; + INT32 iModifier = 0; // mine each mine, check if we own it and such for ( INT8 bCounter = 0; bCounter < MAX_NUMBER_OF_MINES; ++bCounter ) @@ -702,10 +702,12 @@ void HandleIncomeFromMines( void ) if ( PlayerControlsMine( bCounter ) ) { // HEADROCK HAM 3.6: Add facility modifier as a percentage - iFacilityModifier = 100 + MineIncomeModifierFromFacility( bCounter ); + // add rebel command bonus + iModifier = 100 + MineIncomeModifierFromFacility( bCounter ) + RebelCommand::GetMiningPolicyBonus(gMineStatus[bCounter].bAssociatedTown); // mine this mine - iIncome += (MineAMine( bCounter ) * iFacilityModifier) / 100; + iIncome += (MineAMine( bCounter ) * iModifier) / 100; + } else { @@ -718,6 +720,8 @@ void HandleIncomeFromMines( void ) iIncome = (iIncome * gGameExternalOptions.usMineIncomePercentage) / 100; iIncome_Enemy = (iIncome_Enemy * gGameExternalOptions.usMineIncomePercentage) / 100; + RebelCommand::RaidMines(iIncome, iIncome_Enemy); + if( iIncome ) { AddTransactionToPlayersBook( DEPOSIT_FROM_SILVER_MINE, 0, GetWorldTotalMin( ), iIncome ); @@ -736,7 +740,7 @@ UINT32 PredictDailyIncomeFromAMine( INT8 bMineIndex, BOOLEAN fIncludeFacilities // (miner loyalty, % town controlled, monster infestation level, and current max removal rate may all in fact change) UINT32 uiAmtExtracted = 0; // HEADROCK HAM 3.6: Facilities can now modify income - INT32 iFacilityModifier = 0; + INT32 iModifier = 0; if(PlayerControlsMine(bMineIndex)) { @@ -752,8 +756,9 @@ UINT32 PredictDailyIncomeFromAMine( INT8 bMineIndex, BOOLEAN fIncludeFacilities if (bMineIndex && fIncludeFacilities) { // HEADROCK HAM 3.6: Facility modifier applied as a percentage - iFacilityModifier = 100 + MineIncomeModifierFromFacility( bMineIndex ); - uiAmtExtracted = (uiAmtExtracted * iFacilityModifier) / 100; + // add rebel command bonus + iModifier = 100 + MineIncomeModifierFromFacility( bMineIndex ) + RebelCommand::GetMiningPolicyBonus(gMineStatus[bMineIndex].bAssociatedTown); + uiAmtExtracted = (uiAmtExtracted * iModifier) / 100; } } diff --git a/Strategic/Strategic Town Loyalty.cpp b/Strategic/Strategic Town Loyalty.cpp index 50d96128..0572d672 100644 --- a/Strategic/Strategic Town Loyalty.cpp +++ b/Strategic/Strategic Town Loyalty.cpp @@ -38,6 +38,7 @@ #include "Facilities.h" #include "CampaignStats.h" // added by Flugente #include "DynamicDialogue.h" // added by Flugente + #include "Rebel Command.h" #endif #include "Luaglobal.h" @@ -293,7 +294,6 @@ void IncrementTownLoyalty( INT8 bTownId, UINT32 uiLoyaltyIncrease ) UINT32 uiRemainingIncrement; INT16 sThisIncrement; - AssertGE (bTownId, BLANK_SECTOR); AssertLT (bTownId, NUM_TOWNS); @@ -303,6 +303,9 @@ void IncrementTownLoyalty( INT8 bTownId, UINT32 uiLoyaltyIncrease ) return; } + // if rebel command is enabled, apply gain modifier + uiLoyaltyIncrease *= RebelCommand::GetLoyaltyGainModifier(); + // modify loyalty change by town's individual attitude toward rebelling (20 is typical) uiLoyaltyIncrease *= (5 * gubTownRebelSentiment[ bTownId ]); uiLoyaltyIncrease /= 100; @@ -394,6 +397,9 @@ void UpdateTownLoyaltyRating( INT8 bTownId ) ubMaxLoyalty = MAX_LOYALTY_VALUE; } + // if playing with rebel command, limit max loyalty + ubMaxLoyalty = min(ubMaxLoyalty, RebelCommand::GetMaxTownLoyalty(bTownId)); + // check if we'd be going over the max if( (gTownLoyalty[ bTownId ].ubRating + sRatingChange ) >= ubMaxLoyalty ) { diff --git a/Strategic/Strategic Town Loyalty.h b/Strategic/Strategic Town Loyalty.h index aa5ad557..abee6506 100644 --- a/Strategic/Strategic Town Loyalty.h +++ b/Strategic/Strategic Town Loyalty.h @@ -183,6 +183,9 @@ INT32 GetNumberOfWholeTownsUnderControl( void ); // is all the sectors of this town under control by the player INT32 IsTownUnderCompleteControlByPlayer( INT8 bTownId ); +// are all town sectors under control by the enemy +INT32 IsTownUnderCompleteControlByEnemy(INT8 bTownId); + // used when monsters attack a town sector without going through tactical and they win void AdjustLoyaltyForCivsEatenByMonsters( INT16 sSectorX, INT16 sSectorY, UINT8 ubHowMany, BOOLEAN aBandits ); diff --git a/Strategic/Strategic_VS2005.vcproj b/Strategic/Strategic_VS2005.vcproj index 6478ef84..348378c5 100644 --- a/Strategic/Strategic_VS2005.vcproj +++ b/Strategic/Strategic_VS2005.vcproj @@ -474,6 +474,10 @@ RelativePath=".\QuestText.h" > + + @@ -688,6 +692,10 @@ RelativePath=".\Quests.cpp" > + + diff --git a/Strategic/Strategic_VS2008.vcproj b/Strategic/Strategic_VS2008.vcproj index 6d371b77..5854184c 100644 --- a/Strategic/Strategic_VS2008.vcproj +++ b/Strategic/Strategic_VS2008.vcproj @@ -474,6 +474,10 @@ RelativePath="QuestText.h" > + + @@ -686,6 +690,10 @@ RelativePath="Quests.cpp" > + + diff --git a/Strategic/Strategic_VS2010.vcxproj b/Strategic/Strategic_VS2010.vcxproj index 021fb0e0..87c89ffe 100644 --- a/Strategic/Strategic_VS2010.vcxproj +++ b/Strategic/Strategic_VS2010.vcxproj @@ -57,6 +57,7 @@ + @@ -111,6 +112,7 @@ + diff --git a/Strategic/Strategic_VS2010.vcxproj.filters b/Strategic/Strategic_VS2010.vcxproj.filters index f55f73fa..31cd0018 100644 --- a/Strategic/Strategic_VS2010.vcxproj.filters +++ b/Strategic/Strategic_VS2010.vcxproj.filters @@ -105,7 +105,10 @@ Header Files - + + Header Files + + Header Files @@ -263,7 +266,10 @@ Source Files - + + Source Files + + Source Files diff --git a/Strategic/Strategic_VS2013.vcxproj b/Strategic/Strategic_VS2013.vcxproj index 3e4558b5..5f7c1038 100644 --- a/Strategic/Strategic_VS2013.vcxproj +++ b/Strategic/Strategic_VS2013.vcxproj @@ -57,6 +57,7 @@ + @@ -111,6 +112,7 @@ + diff --git a/Strategic/Strategic_VS2013.vcxproj.filters b/Strategic/Strategic_VS2013.vcxproj.filters index 9e782c76..f5758499 100644 --- a/Strategic/Strategic_VS2013.vcxproj.filters +++ b/Strategic/Strategic_VS2013.vcxproj.filters @@ -99,7 +99,10 @@ Header Files - + + Header Files + + Header Files @@ -257,7 +260,10 @@ Source Files - + + Source Files + + Source Files diff --git a/Strategic/Strategic_VS2017.vcxproj b/Strategic/Strategic_VS2017.vcxproj index b1835d6d..0995eb00 100644 --- a/Strategic/Strategic_VS2017.vcxproj +++ b/Strategic/Strategic_VS2017.vcxproj @@ -50,13 +50,14 @@ - + + @@ -105,12 +106,13 @@ - + + diff --git a/Strategic/Strategic_VS2019.vcxproj b/Strategic/Strategic_VS2019.vcxproj index f2a59618..4337e3f2 100644 --- a/Strategic/Strategic_VS2019.vcxproj +++ b/Strategic/Strategic_VS2019.vcxproj @@ -77,6 +77,7 @@ + @@ -131,6 +132,7 @@ + diff --git a/Strategic/Town Militia.cpp b/Strategic/Town Militia.cpp index c536944d..d9bba0ae 100644 --- a/Strategic/Town Militia.cpp +++ b/Strategic/Town Militia.cpp @@ -34,6 +34,7 @@ #include "MilitiaIndividual.h" // added by Flugente #include "Campaign.h" // added by Flugente #include "message.h" // added by Flugente + #include "Rebel Command.h" #endif // HEADROCK HAM 3: include these files so that a militia trainer's Effective Leadership can be determined. Used @@ -832,7 +833,7 @@ BOOLEAN ServeNextFriendlySectorInTown( INT16 *sNeighbourX, INT16 *sNeighbourY ) void HandleInterfaceMessageForCostOfTrainingMilitia( SOLDIERTYPE *pSoldier ) { - INT32 iMilitiaTrainingCost = gGameExternalOptions.iMilitiaTrainingCost; + INT32 iMilitiaTrainingCost = gGameExternalOptions.iMilitiaTrainingCost * RebelCommand::GetMilitiaTrainingCostModifier(); DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia2"); CHAR16 sString[ 128 ]; @@ -937,7 +938,7 @@ void HandleInterfaceMessageForContinuingTrainingMilitia( SOLDIERTYPE *pSoldier ) INT32 iCounter = 0; INT32 iMinLoyaltyToTrain = gGameExternalOptions.iMinLoyaltyToTrain; - INT32 iMilitiaTrainingCost = gGameExternalOptions.iMilitiaTrainingCost; + INT32 iMilitiaTrainingCost = gGameExternalOptions.iMilitiaTrainingCost * RebelCommand::GetMilitiaTrainingCostModifier(); DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia3"); @@ -1642,7 +1643,7 @@ void ContinueTrainingInThisSector( UINT8 ubMilitiaType ) void PayForTrainingInSector( UINT8 ubSector ) { - INT32 iMilitiaTrainingCost = gGameExternalOptions.iMilitiaTrainingCost; + INT32 iMilitiaTrainingCost = gGameExternalOptions.iMilitiaTrainingCost * RebelCommand::GetMilitiaTrainingCostModifier(); DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia6"); INT32 CostMultiplyer = 0; @@ -2083,7 +2084,7 @@ UINT32 CalcMilitiaUpkeep( void ) } } - return uiTotalPayment; + return uiTotalPayment * RebelCommand::GetMilitiaUpkeepCostModifier(); } // Flugente: our militia volunteer pool is limited diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 86e4c798..57788cf3 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -116,6 +116,7 @@ #include "Creature Spreading.h" // added by Flugente forResetCreatureAttackVariables() #include "finances.h" // added by Flugente #include "MilitiaIndividual.h" // added by Flugente +#include "Rebel Command.h" #endif #include "connect.h" @@ -182,6 +183,7 @@ INT32 giPauseAllAITimer = 0; BOOLEAN sniperwarning; BOOLEAN biggunwarning; BOOLEAN gogglewarning; +BOOLEAN checkBonusMilitia; //BOOLEAN airstrikeavailable; TacticalStatusType gTacticalStatus; @@ -993,6 +995,14 @@ BOOLEAN ExecuteOverhead( ) } } + // check if bonus militia join us + if (checkBonusMilitia == TRUE && gGameExternalOptions.fRebelCommandEnabled && gubPBSectorZ == 0) + { + UINT8 bonusGreenMilitia = 0, bonusRegularMilitia = 0, bonusEliteMilitia = 0; + RebelCommand::GetBonusMilitia(gubPBSectorX, gubPBSectorY, bonusGreenMilitia, bonusRegularMilitia, bonusEliteMilitia, TRUE); + checkBonusMilitia = FALSE; + } + for ( cnt = 0; cnt < guiNumMercSlots; cnt++ ) { pSoldier = MercSlots[ cnt ]; @@ -6748,6 +6758,7 @@ void SetEnemyPresence( ) sniperwarning = FALSE; biggunwarning = FALSE; gogglewarning = FALSE; + checkBonusMilitia = TRUE; // airstrikeavailable = TRUE; } else diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 72e5e8e7..9c8f1127 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -125,6 +125,7 @@ #include "LightEffects.h" // added by Flugente for CreatePersonalLight() #include "DynamicDialogue.h" // added by Flugente for HandleDynamicOpinions() #include "strategic town loyalty.h" // added by Flugente for gTownLoyalty +#include "Rebel Command.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; @@ -21382,7 +21383,7 @@ extern FLOAT GetAdministrationPercentage( INT16 sX, INT16 sY ); FLOAT SOLDIERTYPE::GetAdministrationModifier() { if ( ADMINISTRATION_BONUS( this->bAssignment ) ) - return 1.0f + GetAdministrationPercentage( this->sSectorX, this->sSectorY ) / 100.0f; + return 1.0f + GetAdministrationPercentage( this->sSectorX, this->sSectorY ) / 100.0f + RebelCommand::GetAssignmentBonus(this->sSectorX, this->sSectorY); return 1.0f; } diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index df8c57b6..e3ca328e 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -47,6 +47,7 @@ #include "Interface.h" // added by Flugente #include "Soldier macros.h" // added by Flugente #include "MilitiaIndividual.h" // added by Flugente + #include "Rebel Command.h" #endif #include "connect.h" @@ -1763,6 +1764,10 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT pSoldier->flags.bHasKeys = pCreateStruct->fHasKeys; pSoldier->ubSoldierClass = pCreateStruct->ubSoldierClass; + pSoldier->sSectorX = pCreateStruct->sSectorX; + pSoldier->sSectorY = pCreateStruct->sSectorY; + pSoldier->bSectorZ = pCreateStruct->bSectorZ; + // Flugente: soldier profiles // silversurfer: Don't replace tanks! if ( !ARMED_VEHICLE( pCreateStruct ) && !ENEMYROBOT( pCreateStruct ) ) @@ -1821,6 +1826,12 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT if ( gGameExternalOptions.fAssignTraitsToMilitia && SOLDIER_CLASS_MILITIA( pSoldier->ubSoldierClass ) ) AssignTraitsToSoldier( pSoldier, pCreateStruct ); + // if rebel command is enabled, apply bonuses and penalties + if (SOLDIER_CLASS_MILITIA(pSoldier->ubSoldierClass)) + RebelCommand::ApplyMilitiaBonuses(pSoldier); + if ((SOLDIER_CLASS_ENEMY(pSoldier->ubSoldierClass) || pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT)) + RebelCommand::ApplyEnemyPenalties(pSoldier); + // Flugente: enemy roles if ( gGameExternalOptions.fEnemyRoles && gGameExternalOptions.fEnemyOfficers && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) ) { @@ -1831,7 +1842,7 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT UINT8 numofficers = HighestEnemyOfficersInSector( officertype ); // this guy becomes an officer if there are enough soldiers around, and we aren't already at max of officers - if ( numenemies > gGameExternalOptions.usEnemyOfficersPerTeamSize * numofficers && numofficers < gGameExternalOptions.usEnemyOfficersMax ) + if ( numenemies > gGameExternalOptions.usEnemyOfficersPerTeamSize * numofficers && numofficers < gGameExternalOptions.usEnemyOfficersMax && !RebelCommand::NeutraliseRole(pSoldier) ) pSoldier->usSoldierFlagMask |= SOLDIER_ENEMY_OFFICER; } } @@ -4907,7 +4918,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre } // Now assign the trait - if ( Chance( iChance ) ) + if ( Chance( iChance ) && !RebelCommand::NeutraliseRole(pSoldier) ) { if ( !ATraitAssigned ) { @@ -5283,7 +5294,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre if ( gGameOptions.fNewTraitSystem && (!ATraitAssigned || !BTraitAssigned || !CTraitAssigned) ) { // if we have a radio set, give us the corresponding trait so we can use it... - if ( fRadioSetFound ) + if ( fRadioSetFound && !RebelCommand::NeutraliseRole(pSoldier)) { // this is a minor trait, so try to first fill the minor slot if possible // reasoning: this trait has to be one of the first evaluated - getting a radio set is rare, so e want to make sure we become a radio guy if we're lucky @@ -5307,7 +5318,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre } // HEAVY WEAPONS TRAIT - if ( foundMortar || foundRocketlauncher || foundGrenadelauncher ) + if ( (foundMortar || foundRocketlauncher || foundGrenadelauncher) && !RebelCommand::NeutraliseRole(pSoldier) ) { // setup basic chances based on soldier type if ( ubSolClass == SOLDIER_CLASS_ELITE || ubSolClass == SOLDIER_CLASS_ELITE_MILITIA ) @@ -5837,7 +5848,7 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre } // Flugente: enemy roles: allow medics - if ( gGameExternalOptions.fEnemyRoles && gGameExternalOptions.fEnemyMedics && gGameOptions.fNewTraitSystem && (!ATraitAssigned || !BTraitAssigned) ) + if ( gGameExternalOptions.fEnemyRoles && gGameExternalOptions.fEnemyMedics && gGameOptions.fNewTraitSystem && (!ATraitAssigned || !BTraitAssigned) && !RebelCommand::NeutraliseRole(pSoldier)) { // if we have a radio set, give us the corresponding trait so we can use it... if ( fFirstAidKitFound ) diff --git a/TileEngine/overhead map.cpp b/TileEngine/overhead map.cpp index aa77048a..ddad42f9 100644 --- a/TileEngine/overhead map.cpp +++ b/TileEngine/overhead map.cpp @@ -23,6 +23,7 @@ #include "Interactive Tiles.h" #include "gameloop.h" #include "Action Items.h" // added by Flugente + #include "Rebel Command.h" #endif #include "connect.h" @@ -662,16 +663,30 @@ void GoIntoOverheadMap( ) giXC += dX, giYC += dY; } if(WORLD_MAX == 129600){ - if(NightTime()){ - gubGridDivisor = ubResolutionTable360[gGameExternalOptions.ubGridResolutionNight]; - }else{ - gubGridDivisor = ubResolutionTable360[gGameExternalOptions.ubGridResolutionDay]; + if (RebelCommand::ShowApproximateEnemyLocations()) + { + gubGridDivisor = ubResolutionTable360[RebelCommand::GetApproximateEnemyLocationResolutionIndex()]; + } + else + { + if(NightTime()){ + gubGridDivisor = ubResolutionTable360[gGameExternalOptions.ubGridResolutionNight]; + }else{ + gubGridDivisor = ubResolutionTable360[gGameExternalOptions.ubGridResolutionDay]; + } } }else{ - if(NightTime()){ - gubGridDivisor = ubResolutionTable160[gGameExternalOptions.ubGridResolutionNight]; - }else{ - gubGridDivisor = ubResolutionTable160[gGameExternalOptions.ubGridResolutionDay]; + if (RebelCommand::ShowApproximateEnemyLocations()) + { + gubGridDivisor = ubResolutionTable160[RebelCommand::GetApproximateEnemyLocationResolutionIndex()]; + } + else + { + if(NightTime()){ + gubGridDivisor = ubResolutionTable160[gGameExternalOptions.ubGridResolutionNight]; + }else{ + gubGridDivisor = ubResolutionTable160[gGameExternalOptions.ubGridResolutionDay]; + } } } gusGridFrameX = WORLD_COLS * 4; @@ -1408,7 +1423,8 @@ void RenderOverheadOverlays() UINT16 jamcolour = Get16BPPColor( FROMRGB( 36, 219, 151 ) ); BOOLEAN marklastenemy = FALSE; - if ( gGameSettings.fOptions[TOPTION_SHOW_LAST_ENEMY] && gGameExternalOptions.ubMarkerMode && gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector <= gGameExternalOptions.ubSoldiersLeft ) + if ( (gGameSettings.fOptions[TOPTION_SHOW_LAST_ENEMY] && gGameExternalOptions.ubMarkerMode && gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector <= gGameExternalOptions.ubSoldiersLeft) + || RebelCommand::ShowApproximateEnemyLocations()) marklastenemy = TRUE; for( i = 0; i < end; ++i ) diff --git a/Utils/Text.h b/Utils/Text.h index 86d3e68d..bcf3d705 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -3115,6 +3115,11 @@ extern STR16 szFactoryText[]; extern STR16 szTurncoatText[]; +extern STR16 szRebelCommandText[]; +extern STR16 szRebelCommandHelpText[]; +extern STR16 szRebelCommandAdminActionsText[]; +extern STR16 szRebelCommandDirectivesText[]; + #define TACTICAL_INVENTORY_DIALOG_NUM 16 #define TACTICAL_COVER_DIALOG_NUM 16 diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 23a01150..05257b88 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11675,6 +11675,147 @@ STR16 gLbeStatsDesc[14] = L"兼容战斗包:", //L"Compatible combat packs:", }; +STR16 szRebelCommandText[] = // TODO.Translate +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = // TODO.Translate +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = // TODO.Translate +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = // TODO.Translate +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + // WANNE: Some Chinese specific strings that needs to be in unicode! STR16 ChineseSpecString1 = L"%%"; //defined in _ChineseText.cpp as this file is already unicode STR16 ChineseSpecString2 = L"*%3d%%%%"; //defined in _ChineseText.cpp as this file is already unicode diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 5690a5b7..97c743b9 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11677,4 +11677,145 @@ STR16 gLbeStatsDesc[14] = L"Compatible combat packs:", }; +STR16 szRebelCommandText[] = // TODO.Translate +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = // TODO.Translate +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = // TODO.Translate +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = // TODO.Translate +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + #endif //DUTCH diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 308dc41b..ebdcb7fb 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -4640,6 +4640,7 @@ STR16 pTransactionText[] = L"Trained workers", // Flugente: train workers L"Drill militia in %s", // Flugente: drill militia L"Mini event", // rftr: mini events + L"Funds transferred from rebel command", // rftr: rebel command }; STR16 pTransactionAlternateText[] = @@ -5092,6 +5093,7 @@ STR16 pBookMarkStrings[] = L"Militia Overview", L"R.I.S.", L"Factories", + L"A.R.C.", }; STR16 pBookmarkTitle[] = @@ -5198,7 +5200,7 @@ STR16 pWebPagesTitles[] = L"Contract", L"Comments", L"McGillicutty's Mortuary", - L"", + L"", //LAPTOP_MODE_SIRTECH L"URL not found.", L"%s Press Council - Conflict Summary", L"%s Press Council - Battle Reports", @@ -5224,6 +5226,9 @@ STR16 pWebPagesTitles[] = L"Encyclopedia - Data", L"Briefing Room", L"Briefing Room - Data", + L"", //LAPTOP_MODE_BRIEFING_ROOM_ENTER + L"", //LAPTOP_MODE_AIM_MEMBERS_ARCHIVES_NEW + L"A.R.C.", }; STR16 pShowBookmarkString[] = @@ -7028,6 +7033,7 @@ STR16 gzLaptopHelpText[] = L"Militia Overview", L"Recon Intelligence Services", L"Controlled factories", + L"Arulco Rebel Command", }; @@ -11675,4 +11681,145 @@ STR16 gLbeStatsDesc[14] = L"Compatible combat packs:", }; +STR16 szRebelCommandText[] = +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + #endif //ENGLISH diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 72d64c7a..fab72c29 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11659,4 +11659,145 @@ STR16 gLbeStatsDesc[14] = L"Compatible combat packs:", }; +STR16 szRebelCommandText[] = // TODO.Translate +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = // TODO.Translate +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = // TODO.Translate +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = // TODO.Translate +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + #endif //FRENCH diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index c87ce249..6ee2e74c 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11581,4 +11581,145 @@ STR16 gLbeStatsDesc[14] = L"Compatible combat packs:", }; +STR16 szRebelCommandText[] = // TODO.Translate +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = // TODO.Translate +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = // TODO.Translate +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = // TODO.Translate +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + #endif //GERMAN diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index c4d9c224..bf63b757 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11668,4 +11668,145 @@ STR16 gLbeStatsDesc[14] = L"Compatible combat packs:", }; +STR16 szRebelCommandText[] = // TODO.Translate +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = // TODO.Translate +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = // TODO.Translate +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = // TODO.Translate +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + #endif //ITALIAN diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index c41cc3fe..eec3f845 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11681,4 +11681,145 @@ STR16 gLbeStatsDesc[14] = L"Compatible combat packs:", }; +STR16 szRebelCommandText[] = // TODO.Translate +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = // TODO.Translate +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = // TODO.Translate +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = // TODO.Translate +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + #endif //POLISH diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 9f01d442..706ce0c7 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11675,4 +11675,145 @@ STR16 gLbeStatsDesc[14] = L"Совместимые ранцы:", }; +STR16 szRebelCommandText[] = // TODO.Translate +{ + L"Arulco Rebel Command - National Overview", + L"Arulco Rebel Command - Regional Overview", + L"Switch to Regional Overview", + L"Switch to National Overview", + L"Supplies:", + L"Incoming Supplies", + L"/day", + L"Current Directive", + L"Improve Directive ($%d)", + L"Improving the selected directive will cost $%d. Confirm expenditure?", + L"Insufficient funds.", + L"New directive will take effect at 00:00.", + L"Militia Overview", + L"Green:", + L"Regular:", + L"Elite:", + L"Projected Daily Total:", + L"Volunteer Pool:", + L"Resources Available:", + L"Guns:", + L"Armour:", + L"Misc:", + L"Training Cost:", + L"Upkeep Cost Per Soldier Per Day:", + L"Training Speed Bonus:", + L"Combat Bonuses:", + L"Physical Stats Bonus:", + L"Marksmanship Bonus:", + L"Upgrade Stats ($%d)", + L"Upgrading militia stats will cost $%d. Confirm expenditure?", + L"Region:", + L"Next", + L"Previous", + L"Administration Team:", + L"None", + L"Active", + L"Inactive", + L"Loyalty:", + L"Maximum Loyalty:", + L"Deploy Administration Team (%d supplies)", + L"Reactivate Administration Team (%d supplies)", + L"It is currently not safe to deploy an administration team to this region. You must establish a foothold by controlling at least one town sector first.", + L"No regional actions available in Omerta.", + L"Administration teams can be deployed to other regions once you capture at least one town sector. Once active, they will be able to expand your influence and power in the region. However, they will need supplies to operate and enact policies.", + L"Be mindful of where you choose to direct supplies. Enacting regional policies will increase supply costs for other policies in the same region and nationally (to a lesser extent).", + L"Administrative Actions:", + L"Establish %s", + L"Improve %s", + L"Current Tier: %d", + L"Taking any administrative action in this region will cost %d supplies.", + L"Dead drop intel gain: %d", + L"Smuggler supply gain: %d", + L"A small group of militia from a nearby safehouse have joined the battle!", + L"[A.R.C. WEBSITE AVAILABLE] With the delivery of food and basic supplies to Omerta, you have convinced the rebels that you're here to make an impact. You have been granted access to the command system they've been working on, which is now available through your laptop.", + L"It is currently not safe to reactivate the administration team here. Recapture a town sector first.", + L"Mine raid successful. Stole $%d.", +}; + +STR16 szRebelCommandHelpText[] = // TODO.Translate +{ + L"|S|u|p|p|l|i|e|s\n \nFood, water, medical supplies, weapons, and anything else that\nthe rebels might find useful. Supplies are obtained automatically\nby the rebels.", + L"|I|n|c|o|m|i|n|g |S|u|p|p|l|i|e|s\n \nEach day, the rebels will gather supplies on their own. As you\ntake over more towns, the amount of supplies they will be\nable to find per day will increase.", + L"|C|u|r|r|e|n|t |D|i|r|e|c|t|i|v|e\n \nYou can choose how the rebels will prioritise their strategic\nobjectives. New directives will become available as you make\nprogress.", + L"|A|d|m|i|n|i|s|t|r|a|t|i|o|n |T|e|a|m\n \nOnce deployed, an admin team is responsible for handling the\nday-to-day affairs of the region. This includes supporting\nlocals, creating rebel propaganda, establishing regional\npolicies, and more.", + L"|M|a|x|i|m|u|m |L|o|y|a|l|t|y\n \nYou will need to convince the locals to fully trust you. This\ncan be done by creating a supply line to them, showing that\nyou intend to improve their quality of life.", +}; + +// follows a specific format: +// x: "Admin Action Button Text", +// x+1: "Admin action description text", +STR16 szRebelCommandAdminActionsText[] = // TODO.Translate +{ + L"Supply Line", + L"Distribute much-needed supplies amongst the local population. Increases maximum regional loyalty.", + L"Rebel Radio", + L"Begin broadcasting rebel public radio in the region. The town gains loyalty daily.", + L"Safehouses", + L"Construct rebel safehouses in the countryside, far from prying eyes. Bonus militia may join you in combat when operating in this region.", + L"Supply Disruption", + L"The rebels will try to disrupt enemy movements in the area by targetting their supplies. Enemies fighting in this region are weaker.", + L"Scout Patrols", + L"Start regular scout patrols to monitor hostile activity in the area. Enemy groups will be spotted further from town.", + L"Dead Drops", + L"Set up dead drops for rebel scouts and infiltrators to deliver their intel. Provides daily intel.", + L"Smugglers", + L"Enlist the aid of smugglers to bring in supplies for the rebels. Provides an unreliable daily supply boost.", + L"Militia Warehouses", + L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", + L"Regional Taxes", + L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"Civilian Aid", + L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", + L"Merc Support", + L"Set up facilities to directly support your mercs assigned in the town. Increases the effectiveness of merc assignments (doctoring, repairing, militia training, etc).", + L"Mining Policy", + L"Import better equipment and work with the town's miners to create more balanced and efficient shift schedules. Increases the town's mine income.", +}; + +// follows a specific format: +// x: "Directive Name", +// x+1: "Directive Bonus Description", +// x+2: "Directive Help Text", +// x+3: "Directive Improvement Button Description", +STR16 szRebelCommandDirectivesText[] = // TODO.Translate +{ + L"Gather Supplies", + L"Gain an additional %.0f supplies per day.", + L"Increase daily supply income by amassing supplies from\nsympathetic locals, and seeking aid from international aid groups.", + L"Improving this directive will increase the amount of supplies that the rebels can gather daily.", + L"Support Militia", + L"Reduce militia daily upkeep costs. Militia daily upkeep cost modifier: %.2f.", + L"The rebels will help out with logistics about the militia\nyou've trained, reducing the strain on your wallet.", + L"Improving this directive will reduce the daily upkeep costs of your militia.", + L"Train Militia", + L"Reduce militia training costs and increase militia training speed. Militia training cost modifier: %.2f. Militia training speed modifier: %.2f.", + L"The rebels will assist when you are training militia,\nincreasing the efficiency at which you can train them.", + L"Improving this directive will further reduce training cost and increase training speed.", + L"Propaganda Campaign", + L"Town loyalty rises faster. Loyalty gain modifier: %.2f.", + L"Your victories and feats will be embellished as news reaches\nthe locals.", + L"Improving this directive will increase how quickly town loyalty rises.", + L"Deploy Elites", + L"%.0f elite militia appear in Omerta each day.", + L"The rebels release a small number of their highly-trained forces to your command.", + L"Improving this directive will increase the number of militia\nthat appear each day.", + L"High Value Target Strikes", + L"Enemy groups are less likely to have specialised soldiers.", + L"Surgical strikes will be conducted against enemy groups. Officers,\nmedics, radio operators, and other specialists are targetted.", + L"Improving this directive will make strikes more successful and effective.", + L"Spotter Teams", + L"When in combat, approximate enemy locations are revealed in the overhead map (press INSERT button in tactical).", + L"A small team will be attached to each of your squads, providing\napproximate locations of enemies when in combat.", + L"Improving this directive will make the locations of unspotted enemies more precise.", + L"Raid Mines", + L"Steal some income from mines not under your control. This directive becomes less useful as you claim mines.", + L"Conduct smash-and-grab raids on hostile mines. While not always\nsuccessful, the raids that do succeed should provide a\nsmall income bump.", + L"Improving this directive will increase the maximum value of stolen income.", +}; + #endif //RUSSIAN diff --git a/gameloop.cpp b/gameloop.cpp index 5189a407..50dea63f 100644 --- a/gameloop.cpp +++ b/gameloop.cpp @@ -149,6 +149,8 @@ BOOLEAN InitializeGame(void) LoadReputationSettings(); // Load creatures settings LoadCreaturesSettings(); + // Load rebel command settings + LoadRebelCommandSettings(); #ifdef JA2UB LoadGameUBOptions(); // JA25 UB