diff --git a/GameSettings.cpp b/GameSettings.cpp index 33734547..a130d2e9 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4236,10 +4236,28 @@ void LoadRebelCommandSettings() gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_SUCCESS_CHANCE", 50, 0, 100); gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_MAX_TRAINERS", 1, 1, 4); gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_MAX_TRAINERS_TEACHING", 1, 1, 4); - gRebelCommandSettings.iTrainMilitiaAnywhereDuration = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION", 72, 0, 255);; - gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION_BONUS_COVERT", 72, 0, 255);; - gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Survival = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION_BONUS_SURVIVAL", 72, 0, 255);; - gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Teaching = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION_BONUS_TEACHING", 72, 0, 255);; + gRebelCommandSettings.iTrainMilitiaAnywhereDuration = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION", 72, 0, 255); + gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION_BONUS_COVERT", 72, 0, 255); + gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Survival = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION_BONUS_SURVIVAL", 72, 0, 255); + gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Teaching = iniReader.ReadInteger("Rebel Command Settings", "TRAIN_MILITIA_ANYWHERE_DURATION_BONUS_TEACHING", 72, 0, 255); + + gRebelCommandSettings.iSoldierBountiesKingpinSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.iSoldierBountiesKingpinDuration = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_DURATION", 24, 0, 255); + gRebelCommandSettings.iSoldierBountiesKingpinDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_DURATION_BONUS_COVERT", 24, 0, 255); + gRebelCommandSettings.iSoldierBountiesKingpinDuration_Bonus_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_DURATION_BONUS_DEMOLITIONS", 24, 0, 255); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Admin = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_ADMIN", 100, 0, 5000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Troop = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_TROOP", 100, 0, 5000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Elite = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_ELITE", 100, 0, 5000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Robot = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_ROBOT", 100, 0, 5000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Jeep = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_JEEP", 100, 0, 5000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Tank = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_TANK", 100, 0, 5000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Officer = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_OFFICER", 100, 0, 5000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_LIMIT", 10000, 0, 30000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_LIMIT_DEMOLITIONS", 10000, 0, 30000); + gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Snitch = iniReader.ReadInteger("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_LIMIT_SNITCH", 10000, 0, 30000); + gRebelCommandSettings.fSoldierBountiesKingpinPayout_Bonus_Covert = iniReader.ReadFloat("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_BONUS_COVERT", 1.1f, 0.f, 2.f); + gRebelCommandSettings.fSoldierBountiesKingpinPayout_Bonus_Deputy = iniReader.ReadFloat("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_BONUS_DEPUTY", 1.1f, 0.f, 2.f); + gRebelCommandSettings.fSoldierBountiesKingpinPayout_Bonus_Snitch = iniReader.ReadFloat("Rebel Command Settings", "SOLDIER_BOUNTIES_KINGPIN_PAYOUT_BONUS_SNITCH", 1.1f, 0.f, 2.f); } void FreeGameExternalOptions() diff --git a/GameSettings.h b/GameSettings.h index b4c46b19..0f302a87 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1926,6 +1926,24 @@ typedef struct UINT8 iTrainMilitiaAnywhereDuration_Bonus_Survival; UINT8 iTrainMilitiaAnywhereDuration_Bonus_Teaching; + INT8 iSoldierBountiesKingpinSuccessChance; + UINT8 iSoldierBountiesKingpinDuration; + UINT8 iSoldierBountiesKingpinDuration_Bonus_Covert; + UINT8 iSoldierBountiesKingpinDuration_Bonus_Demolitions; + UINT16 iSoldierBountiesKingpinPayout_Admin; + UINT16 iSoldierBountiesKingpinPayout_Troop; + UINT16 iSoldierBountiesKingpinPayout_Elite; + UINT16 iSoldierBountiesKingpinPayout_Robot; + UINT16 iSoldierBountiesKingpinPayout_Jeep; + UINT16 iSoldierBountiesKingpinPayout_Tank; + UINT16 iSoldierBountiesKingpinPayout_Officer; + INT16 iSoldierBountiesKingpinPayout_Limit; + INT16 iSoldierBountiesKingpinPayout_Limit_Demolitions; + INT16 iSoldierBountiesKingpinPayout_Limit_Snitch; + FLOAT fSoldierBountiesKingpinPayout_Bonus_Covert; + FLOAT fSoldierBountiesKingpinPayout_Bonus_Deputy; + FLOAT fSoldierBountiesKingpinPayout_Bonus_Snitch; + } REBELCOMMAND_SETTINGS; typedef struct diff --git a/Laptop/finances.cpp b/Laptop/finances.cpp index 261f02a8..a65f2288 100644 --- a/Laptop/finances.cpp +++ b/Laptop/finances.cpp @@ -1612,6 +1612,10 @@ void ProcessTransactionString(STR16 pString, FinanceUnitPtr pFinance) case REBEL_COMMAND_SPENDING: swprintf(pString, L"%s", pTransactionText[REBEL_COMMAND_SPENDING]); break; + + case REBEL_COMMAND_BOUNTY_PAYOUT: + swprintf(pString, L"%s", pTransactionText[REBEL_COMMAND_BOUNTY_PAYOUT]); + break; } } diff --git a/Laptop/finances.h b/Laptop/finances.h index b617e198..6c03e486 100644 --- a/Laptop/finances.h +++ b/Laptop/finances.h @@ -62,6 +62,7 @@ enum MINI_EVENT, // rftr: mini events REBEL_COMMAND, // rftr: rebel command REBEL_COMMAND_SPENDING, // rftr: rebel command + REBEL_COMMAND_BOUNTY_PAYOUT, // rftr: rebel command soldier bounties TEXT_NUM_FINCANCES }; diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 13de9e87..cbcf5359 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -85,8 +85,10 @@ Points of interest: #include "mousesystem.h" #include "Overhead Types.h" #include "Queen Command.h" +#include "Quests.h" #include "random.h" #include "SaveLoadGame.h" +#include "Soldier macros.h" #include "Squads.h" #include "strategic.h" #include "strategicmap.h" @@ -145,6 +147,8 @@ constexpr UINT16 SABOTAGE_MECHANICAL_UNITS_COVERT = 1; constexpr UINT16 SABOTAGE_MECHANICAL_UNITS_DEMOLITIONS = 2; constexpr UINT16 SABOTAGE_MECHANICAL_UNITS_HEAVY_WEAPONS = 3; constexpr UINT16 TRAIN_MILITIA_ANYWHERE_TEACHING = 1; +constexpr UINT16 SOLDIER_BOUNTIES_KINGPIN_OFFICER_PAYOUTS = 1; +constexpr UINT16 SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS = 2; typedef struct { @@ -214,7 +218,6 @@ void GetMissionInfo(RebelCommandAgentMissions mission, const MERCPROFILESTRUCT* } void DEBUG_DAY(); -void DEBUG_PRINT(); enum WebsiteState { @@ -312,6 +315,10 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_MISSION_BONUS_INFANTRY_GEAR_QUALITY, RCT_MISSION_BONUS_MECHANICAL_STAT_LOSS, RCT_MISSION_BONUS_MAX_TRAINERS, + RCT_MISSION_BONUS_PAYOUT, + RCT_MISSION_BONUS_PAYOUT_LIMIT_INCREASE, + RCT_MISSION_BONUS_OFFICER_PAYOUT, + RCT_MISSION_BONUS_VEHICLE_PAYOUT, RCT_MISSION_BONUS_DURATION, RCT_MISSION_CANT_START_LOW_LOYALTY, RCT_MISSION_CANT_START_AGENT_UNAVAILABLE, @@ -374,6 +381,7 @@ enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentM MISSION_TEXT(SABOTAGE_INFANTRY_EQUIPMENT) MISSION_TEXT(SABOTAGE_MECHANICAL_UNITS) MISSION_TEXT(TRAIN_MILITIA_ANYWHERE) + MISSION_TEXT(SOLDIER_BOUNTIES_KINGPIN) }; enum ChangeAdminActionState @@ -1373,12 +1381,6 @@ void RenderHeader(RebelCommandText titleText) ButtonHelper(btn, reason, []() { DEBUG_DAY(); }); }); btnIds.push_back(btnId); - - usPosY = WEBSITE_TOP + 365; - btnId = 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(); }); - }); - btnIds.push_back(btnId); } } @@ -2176,6 +2178,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SABOTAGE_INFANTRY_EQUIPMENT_TITLE]); break; case RCAM_SABOTAGE_MECHANICAL_UNITS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SABOTAGE_MECHANICAL_UNITS_TITLE]); break; case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE]); break; + case RCAM_SOLDIER_BOUNTIES_KINGPIN: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SOLDIER_BOUNTIES_KINGPIN_TITLE]); break; default: swprintf(sText, L"Mission Index: %d", rebelCommandSaveInfo.availableMissions[index]); break; } @@ -2193,6 +2196,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: missionDurationBase = gRebelCommandSettings.iSabotageInfantryEquipmentDuration; break; case RCAM_SABOTAGE_MECHANICAL_UNITS: missionDurationBase = gRebelCommandSettings.iSabotageMechanicalUnitsDuration; break; case RCAM_TRAIN_MILITIA_ANYWHERE: missionDurationBase = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; break; + case RCAM_SOLDIER_BOUNTIES_KINGPIN: missionDurationBase = gRebelCommandSettings.iSoldierBountiesKingpinDuration; break; default: break; } @@ -2213,6 +2217,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: missionSuccessChanceBase = gRebelCommandSettings.iSabotageInfantryEquipmentSuccessChance; break; case RCAM_SABOTAGE_MECHANICAL_UNITS: missionSuccessChanceBase = gRebelCommandSettings.iSabotageMechanicalUnitsSuccessChance; break; case RCAM_TRAIN_MILITIA_ANYWHERE: missionSuccessChanceBase = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; break; + case RCAM_SOLDIER_BOUNTIES_KINGPIN: missionSuccessChanceBase = gRebelCommandSettings.iSoldierBountiesKingpinSuccessChance; break; default: break; } @@ -2230,6 +2235,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SABOTAGE_INFANTRY_EQUIPMENT_DESC]); break; case RCAM_SABOTAGE_MECHANICAL_UNITS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SABOTAGE_MECHANICAL_UNITS_DESC]); break; case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_DESC]); break; + case RCAM_SOLDIER_BOUNTIES_KINGPIN: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SOLDIER_BOUNTIES_KINGPIN_DESC], gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit); break; default: swprintf(sText, L"Mission description goes here. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut faucibus libero dui. Etiam facilisis posuere dictum. Etiam a velit viverra, interdum eros non, placerat lectus. Vivamus ut lorem id velit tempus auctor. Donec molestie, erat at molestie malesuada, diam purus tincidunt eros, vel hendrerit mi elit vitae leo. Suspendisse dui lectus, malesuada eu elementum at, viverra eu odio."); break; } @@ -2421,6 +2427,37 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } break; + case RCAM_SOLDIER_BOUNTIES_KINGPIN: + { + floatModifier = max(floatModifier, 1.f); + CHAR16 text[100]; + if (floatModifier > 1.f) + { + floatModifier *= 100; + floatModifier -= 100; + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_PAYOUT], floatModifier, L"%s", locSkillText[floatModifierSkill]); + agentBonusText.push_back(text); + } + + if (intModifier > 0) + { + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_PAYOUT_LIMIT_INCREASE], intModifier, locSkillText[intModifierSkill]); + agentBonusText.push_back(text); + } + + if (extraBits == MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_OFFICER_PAYOUTS) + { + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_OFFICER_PAYOUT], locSkillText[floatModifierSkill]); + agentBonusText.push_back(text); + } + else if (extraBits == MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS) + { + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_VEHICLE_PAYOUT], locSkillText[floatModifierSkill]); + agentBonusText.push_back(text); + } + } + break; + default: break; } @@ -2600,13 +2637,13 @@ void RenderMissionOverview() } UINT16 y = WEBSITE_TOP + 90; - for (int i = 0; i < evt1Strings.size(); ++i) + for (std::vector::size_type i = 0; i < evt1Strings.size(); ++i) { DrawTextToScreen(const_cast(evt1Strings[i].c_str()), WEBSITE_LEFT + 35, y, 0, FONT12ARIAL, FONT_DKYELLOW, FONT_MCOLOR_BLACK, FALSE, 0); y += 15; } - for (int i = 0; i < evt2Strings.size(); ++i) + for (std::vector::size_type i = 0; i < evt2Strings.size(); ++i) { DrawTextToScreen(const_cast(evt2Strings[i].c_str()), WEBSITE_LEFT + 35, y, 0, FONT12ARIAL, FONT_DKGREEN, FONT_MCOLOR_BLACK, FALSE, 0); y += 15; @@ -2723,6 +2760,14 @@ void StartMission(INT8 index) missionDuration = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; } break; + + case RCAM_SOLDIER_BOUNTIES_KINGPIN: + { + missionTitle = RCAMT_SOLDIER_BOUNTIES_KINGPIN_TITLE; + missionSuccessChance = gRebelCommandSettings.iSoldierBountiesKingpinSuccessChance; + missionDuration = gRebelCommandSettings.iSoldierBountiesKingpinDuration; + } + break; default: break; } @@ -3690,11 +3735,19 @@ void DailyUpdate() } // update missions + if (rebelCommandSaveInfo.cachedBountyPayout > 0) + { + AddTransactionToPlayersBook(REBEL_COMMAND_BOUNTY_PAYOUT, 0, GetWorldTotalMin(), rebelCommandSaveInfo.cachedBountyPayout); + rebelCommandSaveInfo.cachedBountyPayout = 0; + } + if (GetWorldDay() % gRebelCommandSettings.iMissionRefreshTimeDays == 0) { std::unordered_set validMissions; for (int i = 0; i < RCAM_NUM_MISSIONS; ++i) { + if (i == RCAM_SOLDIER_BOUNTIES_KINGPIN && !(CheckFact(FACT_KINGPIN_INTRODUCED_SELF, 0) == TRUE && CheckFact(FACT_KINGPIN_DEAD, 0) == FALSE && CheckFact(FACT_KINGPIN_IS_ENEMY, 0) == FALSE && CurrentPlayerProgressPercentage() >= 30)) continue; + validMissions.insert(static_cast(i)); } @@ -4123,6 +4176,16 @@ void SetupInfo() {gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching}, {0, 0, MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING} }); + //RCAM_SOLDIER_BOUNTIES_KINGPIN + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, SQUADLEADER_NT, SNITCH_NT, DEMOLITIONS_NT}, + {-1, -1, -1, -1}, + {gRebelCommandSettings.iSoldierBountiesKingpinDuration_Bonus_Covert, 0, 0, gRebelCommandSettings.iSoldierBountiesKingpinDuration_Bonus_Demolitions}, + {gRebelCommandSettings.fSoldierBountiesKingpinPayout_Bonus_Covert, gRebelCommandSettings.fSoldierBountiesKingpinPayout_Bonus_Deputy, gRebelCommandSettings.fSoldierBountiesKingpinPayout_Bonus_Snitch, 1.f}, + {0, 0, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Snitch, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Demolitions}, + {0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_OFFICER_PAYOUTS, 0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS} + }); } void UpgradeMilitiaStats() @@ -4148,6 +4211,65 @@ void UpgradeMilitiaStats() }); } +void ApplySoldierBounty(const SOLDIERTYPE* pSoldier) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + if (pSoldier->bTeam != ENEMY_TEAM) + return; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_SOLDIER_BOUNTIES_KINGPIN); + + if (iter == missionMap.end()) + return; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + if (!evt.isSecondEvent) + return; + + UINT16 payout = 0; + + if (TANK(pSoldier) && evt.extraBits == MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS) + payout += gRebelCommandSettings.iSoldierBountiesKingpinPayout_Tank; + else if (COMBAT_JEEP(pSoldier) && evt.extraBits == MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS) + payout += gRebelCommandSettings.iSoldierBountiesKingpinPayout_Jeep; + else if (ENEMYROBOT(pSoldier) && evt.extraBits == MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS) + payout += gRebelCommandSettings.iSoldierBountiesKingpinPayout_Robot; + else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR) + payout += gRebelCommandSettings.iSoldierBountiesKingpinPayout_Admin; + else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ARMY) + payout += gRebelCommandSettings.iSoldierBountiesKingpinPayout_Troop; + else if (pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE) + payout += gRebelCommandSettings.iSoldierBountiesKingpinPayout_Elite; + else // unknown kill, bail out! + return; + + // payout per role + if (pSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER && (evt.extraBits == MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_OFFICER_PAYOUTS)) + payout += gRebelCommandSettings.iSoldierBountiesKingpinPayout_Officer; + + + // apply payout limit + UINT32 durationBonus = 0; + int durationBonusSkill = 0; + INT16 intModifier = 0; + int intModifierSkill = 0; + FLOAT floatModifier = 0.f; + int floatModifierSkill = 0; + UINT16 extraBits = 0; + MissionHelpers::GetMissionInfo(RCAM_SOLDIER_BOUNTIES_KINGPIN, &gMercProfiles[evt.mercProfileId], durationBonus, floatModifier, intModifier, durationBonusSkill, floatModifierSkill, intModifierSkill, extraBits); + + const INT32 payoutLimit = max(gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit, intModifier); + // clamp payout like this in case the player maxes out payouts in config and we have to deal with a uint overflow + if (payoutLimit - payout < rebelCommandSaveInfo.cachedBountyPayout) + payout = payoutLimit - rebelCommandSaveInfo.cachedBountyPayout; + + rebelCommandSaveInfo.cachedBountyPayout += payout; +} + void ApplyEnemyMechanicalUnitPenalties(SOLDIERTYPE* pSoldier) { if (!gGameExternalOptions.fRebelCommandEnabled) @@ -4484,6 +4606,7 @@ void HandleStrategicEvent(const UINT32 eventParam) case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: case RCAM_SABOTAGE_MECHANICAL_UNITS: case RCAM_TRAIN_MILITIA_ANYWHERE: + case RCAM_SOLDIER_BOUNTIES_KINGPIN: { validMission = TRUE; } @@ -4597,18 +4720,6 @@ 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() diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index 314eaa7f..073349e1 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -1,6 +1,7 @@ #ifndef REBEL_COMMAND_H #define REBEL_COMMAND_H +#include "CampaignStats.h" #include "mapscreen.h" #include "Soldier Control.h" #include "Types.h" @@ -95,6 +96,7 @@ enum RebelCommandAgentMissions RCAM_SABOTAGE_INFANTRY_EQUIPMENT, // aka Sabotage Equipment RCAM_SABOTAGE_MECHANICAL_UNITS, // aka Sabotage Vehicles RCAM_TRAIN_MILITIA_ANYWHERE, + RCAM_SOLDIER_BOUNTIES_KINGPIN, RCAM_NUM_MISSIONS, @@ -182,8 +184,9 @@ typedef struct SaveInfo INT8 iMilitiaStatsLevel; UINT8 uSupplyDropCount; // keeping this around for compatibility with old saves INT8 availableMissions[NUM_ARC_AGENT_SLOTS]; + UINT16 cachedBountyPayout; - INT8 filler[17]; + INT8 filler[15]; } SaveInfo; extern SaveInfo rebelCommandSaveInfo; @@ -213,6 +216,7 @@ void RaidMines(INT32 &playerIncome, INT32 &enemyIncome); BOOLEAN ShowApproximateEnemyLocations(); // agent missions +void ApplySoldierBounty(const SOLDIERTYPE* pSoldier); void ApplyEnemyMechanicalUnitPenalties(SOLDIERTYPE* pSoldier); void ApplyMilitiaTraits(SOLDIERTYPE* pSoldier); void ApplyVisionModifier(const SOLDIERTYPE* pSoldier, INT32& sight); diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index 431f08b9..a615b863 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -66,6 +66,7 @@ #include "MilitiaIndividual.h" // added by Flugente #include "Town Militia.h" // added by Flugente #include "PreBattle Interface.h" // added by Flugente +#include "Rebel Command.h" #endif // anv: for enemy taunts @@ -4198,6 +4199,9 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse ) } } + // rftr: soldier bounty payout + RebelCommand::ApplySoldierBounty(pSoldier); + // Flugente: campaign stats gCurrentIncident.AddStat( pSoldier, CAMPAIGNHISTORY_TYPE_KILL ); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index ac3a36c0..69766222 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -4663,6 +4663,7 @@ STR16 pTransactionText[] = L"微型事件", //L"Mini event", rftr: mini events L"从反抗军司令部转移资金", //L"Funds transferred from rebel command", rftr: rebel command L"资金转移到反抗军司令部", //L"Funds transferred to rebel command", rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11952,6 +11953,10 @@ STR16 szRebelCommandText[] = L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12091,6 +12096,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index af0fe600..f2557313 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -4666,6 +4666,7 @@ STR16 pTransactionText[] = L"Mini event", // rftr: mini events // TODO: translate L"Funds transferred from rebel command", // rftr: rebel command L"Funds transferred to rebel command", // rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11962,6 +11963,10 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12101,6 +12106,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 93851595..da759cf2 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -4663,6 +4663,7 @@ STR16 pTransactionText[] = L"Mini event", // rftr: mini events L"Funds transferred from rebel command", // rftr: rebel command L"Funds transferred to rebel command", // rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11952,6 +11953,10 @@ STR16 szRebelCommandText[] = L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12091,6 +12096,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index d0a3afcd..1324f3dc 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -4670,6 +4670,7 @@ STR16 pTransactionText[] = L"Mini event", // rftr: mini events // TODO: translate L"Funds transferred from rebel command", // rftr: rebel command L"Funds transferred to rebel command", // rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11944,6 +11945,10 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12083,6 +12088,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index cbcbdac3..b3eae88a 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -4668,6 +4668,7 @@ STR16 pTransactionText[] = L"Mini event", // rftr: mini events // TODO: translate L"Funds transferred from rebel command", // rftr: rebel command L"Funds transferred to rebel command", // rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11866,6 +11867,10 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12005,6 +12010,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 595d1e8e..cbf94dc4 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -4660,6 +4660,7 @@ STR16 pTransactionText[] = L"Mini event", // rftr: mini events // TODO: translate L"Funds transferred from rebel command", // rftr: rebel command L"Funds transferred to rebel command", // rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11953,6 +11954,10 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12092,6 +12097,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 84ab44c3..a50c3982 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -4671,6 +4671,7 @@ STR16 pTransactionText[] = L"Mini event", // rftr: mini events // TODO: translate L"Funds transferred from rebel command", // rftr: rebel command L"Funds transferred to rebel command", // rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11966,6 +11967,10 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12105,6 +12110,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index ea60da77..968940e0 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -4663,6 +4663,7 @@ STR16 pTransactionText[] = L"Mini event", // rftr: mini events // TODO: translate L"Funds transferred from rebel command", // rftr: rebel command L"Funds transferred to rebel command", // rftr: rebel command + L"Bounty payout", // rftr: rebel command soldier bounties }; STR16 pTransactionAlternateText[] = @@ -11947,6 +11948,10 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Gear quality -%d (%s)", L"Overall stats -%d (%s)", L"Max trainers: %d (%s)", + L"Payout +%2.0f%s (%s)", + L"Payout limit increased to $%d (%s)", + L"Bonus for officers (%s)", + L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", L"Agent not in loyal town", L"Agent unavailable", @@ -12086,6 +12091,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", L"Train Militia Anywhere", L"Create training areas in the wilderness that can be quickly set up and torn down. Militia can be trained in uncontested sectors outside of town.", + L"Soldier Bounties (Kingpin)", + L"Get a payout for enemy kills. Negotiate with Kingpin, who feels he can use your presence here to indirectly weaken the Queen's power. Bounties are deposited into your account at midnight and are limited to $%d per day.", }; STR16 szRobotText[] = // TODO: Translate