From 7b0830c06042acfab2ce5b4650a2a8aa7ddf68b9 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 11 Oct 2022 00:17:12 -0700 Subject: [PATCH 01/52] Initial commit - SVN checkpoint to git branch --- GameSettings.cpp | 78 + GameSettings.h | 79 + Strategic/Assignments.cpp | 20 +- Strategic/Assignments.h | 1 + Strategic/Game Event Hook.cpp | 5 + Strategic/Game Event Hook.h | 2 + Strategic/Game Events.cpp | 1 + Strategic/Map Screen Interface Map.cpp | 38 + Strategic/MiniEvents.cpp | 1 + Strategic/Rebel Command.cpp | 1926 ++++++++++++++++++++++-- Strategic/Rebel Command.h | 94 +- Strategic/Strategic AI.cpp | 5 + Strategic/Town Militia.cpp | 5 +- Tactical/ArmsDealerInvInit.cpp | 6 +- Tactical/DisplayCover.cpp | 10 +- Tactical/Inventory Choosing.cpp | 26 +- Tactical/Soldier Create.cpp | 8 + TileEngine/Map Edgepoints.cpp | 3 +- TileEngine/Tactical Placement GUI.cpp | 14 +- Utils/Text.h | 1 + Utils/_ChineseText.cpp | 70 +- Utils/_DutchText.cpp | 2 +- Utils/_EnglishText.cpp | 39 +- Utils/_FrenchText.cpp | 2 +- Utils/_GermanText.cpp | 2 +- Utils/_ItalianText.cpp | 2 +- Utils/_PolishText.cpp | 2 +- Utils/_RussianText.cpp | 2 +- 28 files changed, 2235 insertions(+), 209 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 49ec4290f..3a7629833 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4157,6 +4157,84 @@ void LoadRebelCommandSettings() gRebelCommandSettings.iFortificationsBonus = iniReader.ReadInteger("Rebel Command Settings", "FORTIFICATIONS_BONUS", 10, 0, 100); + // agent missions + gRebelCommandSettings.iDeepDeploymentSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.iDeepDeploymentRangeNS = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_NS", 200, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeEW = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_EW", 350, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_NS_BONUS_COVERT", 50, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_EW_BONUS_COVERT" , 15, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Scouting = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_NS_BONUS_SCOUTING" , 25, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Scouting = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_EW_BONUS_SCOUTING" , 40, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Stealthy = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_NS_BONUS_STEALTHY" , 15, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Stealthy = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_EW_BONUS_STEALTHY" , 30, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Survival = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_NS_BONUS_SURVIVAL" , 15, 0, 1000); + gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Survival = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_EW_BONUS_SURVIVAL" , 30, 0, 1000); + gRebelCommandSettings.iDeepDeploymentDuration = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_DURATION" , 72, 0, 255); + gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_DURATION_BONUS_COVERT" , 24, 0, 255); + gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Scouting = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_DURATION_BONUS_SCOUTING" , 48, 0, 255); + gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Stealthy = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_DURATION_BONUS_STEALTHY" , 36, 0, 255); + gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Survival = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_DURATION_BONUS_SURVIVAL" , 36, 0, 255); + + gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.iGetEnemyMovementTargetsDuration = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_DURATION", 72, 0, 255); + gRebelCommandSettings.iGetEnemyMovementTargetsDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_DURATION_BONUS_COVERT", 48, 0, 255); + gRebelCommandSettings.iGetEnemyMovementTargetsDuration_Bonus_Radio = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_DURATION_BONUS_RADIO", 48, 0, 255); + + gRebelCommandSettings.iImproveLocalShopsSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "IMPROVE_LOCAL_SHOPS_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.iImproveLocalShopsDuration = iniReader.ReadInteger("Rebel Command Settings", "IMPROVE_LOCAL_SHOPS_DURATION", 72, 0, 255); + + gRebelCommandSettings.iReduceStrategicDecisionSpeedSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier = iniReader.ReadFloat("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_MODIFIER", 1.1f, 1.f, 10.f); + gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Covert = iniReader.ReadFloat("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_MODIFIER_BONUS_COVERT", 1.25f, 1.f, 10.f); + gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Deputy = iniReader.ReadFloat("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_MODIFIER_BONUS_DEPUTY", 1.25f, 1.f, 10.f); + gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Snitch = iniReader.ReadFloat("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_MODIFIER_BONUS_SNITCH", 1.25f, 1.f, 10.f); + gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration = iniReader.ReadInteger("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_DURATION", 72, 0, 255); + gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_DURATION_BONUS_COVERT", 24, 0, 255); + gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration_Bonus_Deputy = iniReader.ReadInteger("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_DURATION_BONUS_DEPUTY", 24, 0, 255); + gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration_Bonus_Snitch = iniReader.ReadInteger("Rebel Command Settings", "SLOWER_STRATEGIC_DECISIONS_DURATION_BONUS_SNITCH", 24, 0, 255); + + gRebelCommandSettings.iReduceUnalertedEnemyVisionSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "LOWER_READINESS_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier = iniReader.ReadFloat("Rebel Command Settings", "LOWER_READINESS_MODIFIER", 0.15f, 0.f, 1.f); + gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Covert = iniReader.ReadFloat("Rebel Command Settings", "LOWER_READINESS_MODIFIER_COVERT", 0.15f, 0.f, 1.f); + gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Radio = iniReader.ReadFloat("Rebel Command Settings", "LOWER_READINESS_MODIFIER_RADIO", 0.15f, 0.f, 1.f); + gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Stealthy = iniReader.ReadFloat("Rebel Command Settings", "LOWER_READINESS_MODIFIER_STEALTHY", 0.15f, 0.f, 1.f); + gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration = iniReader.ReadInteger("Rebel Command Settings", "LOWER_READINESS_DURATION", 72, 0, 255); + gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "LOWER_READINESS_DURATION_BONUS_COVERT", 72, 0, 255); + gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration_Bonus_Radio = iniReader.ReadInteger("Rebel Command Settings", "LOWER_READINESS_DURATION_BONUS_RADIO", 72, 0, 255); + + gRebelCommandSettings.iSabotageInfantryEquipmentSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentModifier = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_MODIFIER", 10, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Auto_Weapons = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_MODIFIER_AUTO_WEAPONS", 10, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Covert = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_MODIFIER_COVERT", 10, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_MODIFIER_DEMOLITIONS", 10, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Gunslinger = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_MODIFIER_GUNSLINGER", 10, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Ranger = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_MODIFIER_RANGER", 10, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Sniper = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_MODIFIER_SNIPER", 10, 0, 100); + gRebelCommandSettings.iSabotageInfantryEquipmentDuration = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_DURATION", 72, 0, 255); + gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Auto_Weapons = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_DURATION_BONUS_AUTO_WEAPONS", 72, 0, 255); + gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_DURATION_BONUS_COVERT", 72, 0, 255); + gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_DURATION_BONUS_DEMOLITIONS", 72, 0, 255); + gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Gunslinger = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_DURATION_BONUS_GUNSLINGER", 72, 0, 255); + gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Ranger = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_DURATION_BONUS_RANGER", 72, 0, 255); + gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Sniper = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_EQUIPMENT_DURATION_BONUS_SNIPER", 72, 0, 255); + + gRebelCommandSettings.iSabotageMechanicalUnitsSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_STAT_LOSS", 20, 0, 100); + gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Covert = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_STAT_LOSS_COVERT", 20, 0, 100); + gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_STAT_LOSS_DEMOLITIONS", 20, 0, 100); + gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Heavy_Weapons = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_STAT_LOSS_HEAVY_WEAPONS", 20, 0, 100); + gRebelCommandSettings.iSabotageMechanicalUnitsDuration = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_DURATION", 72, 0, 255); + gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_DURATION_BONUS_COVERT", 72, 0, 255); + gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_DURATION_BONUS_DEMOLITIONS", 72, 0, 255); + gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Heavy_Weapons = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_DURATION_BONUS_HEAVY_WEAPONS", 72, 0, 255); + + 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);; } void FreeGameExternalOptions() diff --git a/GameSettings.h b/GameSettings.h index 8ed96c485..117fcf069 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1842,6 +1842,85 @@ typedef struct INT16 iFortificationsBonus; + // agent missions + INT8 iDeepDeploymentSuccessChance; + INT16 iDeepDeploymentRangeNS; + INT16 iDeepDeploymentRangeEW; + INT16 iDeepDeploymentRangeNS_Bonus_Covert; + INT16 iDeepDeploymentRangeEW_Bonus_Covert; + INT16 iDeepDeploymentRangeNS_Bonus_Scouting; + INT16 iDeepDeploymentRangeEW_Bonus_Scouting; + INT16 iDeepDeploymentRangeNS_Bonus_Stealthy; + INT16 iDeepDeploymentRangeEW_Bonus_Stealthy; + INT16 iDeepDeploymentRangeNS_Bonus_Survival; + INT16 iDeepDeploymentRangeEW_Bonus_Survival; + UINT8 iDeepDeploymentDuration; + UINT8 iDeepDeploymentDuration_Bonus_Covert; + UINT8 iDeepDeploymentDuration_Bonus_Scouting; + UINT8 iDeepDeploymentDuration_Bonus_Stealthy; + UINT8 iDeepDeploymentDuration_Bonus_Survival; + + INT8 iGetEnemyMovementTargetsSuccessChance; + UINT8 iGetEnemyMovementTargetsDuration; + UINT8 iGetEnemyMovementTargetsDuration_Bonus_Covert; + UINT8 iGetEnemyMovementTargetsDuration_Bonus_Radio; + + INT8 iImproveLocalShopsSuccessChance; + UINT8 iImproveLocalShopsDuration; + + INT8 iReduceStrategicDecisionSpeedSuccessChance; + FLOAT fReduceStrategicDecisionSpeedModifier; + FLOAT fReduceStrategicDecisionSpeedModifier_Covert; + FLOAT fReduceStrategicDecisionSpeedModifier_Deputy; + FLOAT fReduceStrategicDecisionSpeedModifier_Snitch; + UINT8 iReduceStrategicDecisionSpeedDuration; + UINT8 iReduceStrategicDecisionSpeedDuration_Bonus_Covert; + UINT8 iReduceStrategicDecisionSpeedDuration_Bonus_Deputy; + UINT8 iReduceStrategicDecisionSpeedDuration_Bonus_Snitch; + + INT8 iReduceUnalertedEnemyVisionSuccessChance; + FLOAT fReduceUnlaertedEnemyVisionModifier; + FLOAT fReduceUnlaertedEnemyVisionModifier_Covert; + FLOAT fReduceUnlaertedEnemyVisionModifier_Radio; + FLOAT fReduceUnlaertedEnemyVisionModifier_Stealthy; + UINT8 iReduceUnalertedEnemyVisionDuration; + UINT8 iReduceUnalertedEnemyVisionDuration_Bonus_Covert; + UINT8 iReduceUnalertedEnemyVisionDuration_Bonus_Radio; + + INT8 iSabotageInfantryEquipmentSuccessChance; + INT8 iSabotageInfantryEquipmentModifier; + INT8 iSabotageInfantryEquipmentModifier_Auto_Weapons; + INT8 iSabotageInfantryEquipmentModifier_Covert; + INT8 iSabotageInfantryEquipmentModifier_Demolitions; + INT8 iSabotageInfantryEquipmentModifier_Gunslinger; + INT8 iSabotageInfantryEquipmentModifier_Ranger; + INT8 iSabotageInfantryEquipmentModifier_Sniper; + UINT8 iSabotageInfantryEquipmentDuration; + UINT8 iSabotageInfantryEquipmentDuration_Bonus_Auto_Weapons; + UINT8 iSabotageInfantryEquipmentDuration_Bonus_Covert; + UINT8 iSabotageInfantryEquipmentDuration_Bonus_Demolitions; + UINT8 iSabotageInfantryEquipmentDuration_Bonus_Gunslinger; + UINT8 iSabotageInfantryEquipmentDuration_Bonus_Ranger; + UINT8 iSabotageInfantryEquipmentDuration_Bonus_Sniper; + + INT8 iSabotageMechanicalUnitsSuccessChance; + INT8 iSabotageMechanicalUnitsStatLoss; + INT8 iSabotageMechanicalUnitsStatLoss_Covert; + INT8 iSabotageMechanicalUnitsStatLoss_Demolitions; + INT8 iSabotageMechanicalUnitsStatLoss_Heavy_Weapons; + UINT8 iSabotageMechanicalUnitsDuration; + UINT8 iSabotageMechanicalUnitsDuration_Bonus_Covert; + UINT8 iSabotageMechanicalUnitsDuration_Bonus_Demolitions; + UINT8 iSabotageMechanicalUnitsDuration_Bonus_Heavy_Weapons; + + INT8 iTrainMilitiaAnywhereSuccessChance; + INT8 iTrainMilitiaAnywhereMaxTrainers; + INT8 iTrainMilitiaAnywhereMaxTrainers_Teaching; + UINT8 iTrainMilitiaAnywhereDuration; + UINT8 iTrainMilitiaAnywhereDuration_Bonus_Covert; + UINT8 iTrainMilitiaAnywhereDuration_Bonus_Survival; + UINT8 iTrainMilitiaAnywhereDuration_Bonus_Teaching; + } REBELCOMMAND_SETTINGS; typedef struct diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 0e6398d6f..2b5faccee 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -1658,6 +1659,9 @@ BOOLEAN BasicCanCharacterTrainMilitia( SOLDIERTYPE *pSoldier ) // check if sam site if( fSamSitePresent == FALSE ) { + if (RebelCommand::CanTrainMilitiaAnywhere()) + return( TRUE ); + // nope return ( FALSE ); } @@ -1971,6 +1975,9 @@ BOOLEAN CanCharacterTrainMilitia( SOLDIERTYPE *pSoldier ) } } + if (RebelCommand::CanTrainMilitiaAnywhere()) + ubFacilityTrainersAllowed = RebelCommand::GetMaxTrainersForTrainMilitiaAnywhere(); + // Count number of trainers already operating here if ( CountMilitiaTrainersInSoldiersSector( pSoldier, TOWN_MILITIA ) >= ubFacilityTrainersAllowed ) { @@ -2033,6 +2040,9 @@ BOOLEAN DoesSectorMercIsInHaveSufficientLoyaltyToTrainMilitia( SOLDIERTYPE *pSol { return( TRUE ); } + + if (RebelCommand::CanTrainMilitiaAnywhere()) + return(TRUE); return( FALSE ); } @@ -2085,7 +2095,7 @@ BOOLEAN IsMilitiaTrainableFromSoldiersSectorMaxed( SOLDIERTYPE *pSoldier, INT8 i // is there a town really here if( bTownId == BLANK_SECTOR ) { - fSamSitePresent = IsThisSectorASAMSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); + fSamSitePresent = IsThisSectorASAMSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) || RebelCommand::CanTrainMilitiaAnywhere(); // if there is a sam site here if( fSamSitePresent ) @@ -6136,7 +6146,8 @@ void HandleTrainingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) } // check if we're doing a sector where militia can be trained - if( ( (StrategicMap[CALCULATE_STRATEGIC_INDEX(sMapX, sMapY) ].bNameId != BLANK_SECTOR ) || ( fSamSiteInSector == TRUE ) ) && (bZ == 0) ) + const BOOL canTrainMilitiaAnywhere = RebelCommand::CanTrainMilitiaAnywhere(); + if( (canTrainMilitiaAnywhere || (StrategicMap[CALCULATE_STRATEGIC_INDEX(sMapX, sMapY) ].bNameId != BLANK_SECTOR ) || ( fSamSiteInSector == TRUE ) ) && (bZ == 0) ) { // init town trainer list memset( TownTrainer, 0, sizeof( TownTrainer ) ); @@ -7898,7 +7909,7 @@ BOOLEAN TrainTownInSector( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMapY, INT1 // get town index ubTownId = StrategicMap[CALCULATE_STRATEGIC_INDEX(pTrainer->sSectorX, pTrainer->sSectorY ) ].bNameId; - if( fSamSiteInSector == FALSE ) + if( fSamSiteInSector == FALSE && !RebelCommand::CanTrainMilitiaAnywhere()) { AssertNE(ubTownId, BLANK_SECTOR); } @@ -20165,6 +20176,9 @@ BOOLEAN CanCharacterTrainMilitiaWithErrorReport( SOLDIERTYPE *pSoldier ) } } + if (RebelCommand::CanTrainMilitiaAnywhere()) + ubFacilityTrainersAllowed = RebelCommand::GetMaxTrainersForTrainMilitiaAnywhere(); + // If we are here, then TrainersAllowed > 0. // Otherwise we'd have failed the BasicCanTrain check if ( CountMilitiaTrainersInSoldiersSector( pSoldier, TOWN_MILITIA ) >= ubFacilityTrainersAllowed ) diff --git a/Strategic/Assignments.h b/Strategic/Assignments.h index a3c731ae0..03672ed70 100644 --- a/Strategic/Assignments.h +++ b/Strategic/Assignments.h @@ -100,6 +100,7 @@ enum ADMINISTRATION, // merc boosts the effectiveness of other mercs EXPLORATION, // merc searches the sector for undiscovered items ASSIGNMENT_MINIEVENT, + ASSIGNMENT_REBELCOMMAND, NUM_ASSIGNMENTS, }; diff --git a/Strategic/Game Event Hook.cpp b/Strategic/Game Event Hook.cpp index e951f7659..261fbd80d 100644 --- a/Strategic/Game Event Hook.cpp +++ b/Strategic/Game Event Hook.cpp @@ -51,6 +51,7 @@ #include "Player Command.h" // added by Flugente #include "LuaInitNPCs.h" // added by Flugente #include "MiniEvents.h" + #include "Rebel Command.h" #endif #include "connect.h" @@ -680,6 +681,10 @@ BOOLEAN ExecuteStrategicEvent( STRATEGICEVENT *pEvent ) CheckMiniEvents(pEvent->uiParam); } break; + + case EVENT_REBELCOMMAND: + RebelCommand::HandleStrategicEvent(pEvent->uiParam); + break; } gfPreventDeletionOfAnyEvent = fOrigPreventFlag; return TRUE; diff --git a/Strategic/Game Event Hook.h b/Strategic/Game Event Hook.h index 20077c042..29e08bb59 100644 --- a/Strategic/Game Event Hook.h +++ b/Strategic/Game Event Hook.h @@ -152,6 +152,8 @@ enum EVENT_MINIEVENT, + EVENT_REBELCOMMAND, + NUMBER_OF_EVENT_TYPES_PLUS_ONE, NUMBER_OF_EVENT_TYPES = NUMBER_OF_EVENT_TYPES_PLUS_ONE - 1 }; diff --git a/Strategic/Game Events.cpp b/Strategic/Game Events.cpp index a698d903f..ffcc77b82 100644 --- a/Strategic/Game Events.cpp +++ b/Strategic/Game Events.cpp @@ -140,6 +140,7 @@ CHAR16 gEventName[NUMBER_OF_EVENT_TYPES_PLUS_ONE][40]={ L"bandit attack", L"ArmyFinishTraining", L"MiniEvent", + L"ARC_Event", }; #endif diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 0f0619faa..580419138 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -49,6 +50,7 @@ #include "Map Screen Interface Map Inventory.h" // added by Flugente #include "LuaInitNPCs.h" // added by Flugente #include "Game Event Hook.h" // added by Flugente + #include "Rebel Command.h" #endif #include "Quests.h" @@ -844,6 +846,42 @@ void fillMapColoursForVisitedSectors(INT32(&colorMap)[ MAXIMUM_VALID_Y_COORDINAT } } } + + if (RebelCommand::ShowEnemyMovementTargets()) + { + const auto targetColor = MAP_SHADE_LT_RED; + GROUP* pGroup = gpGroupList; + + while (pGroup) + { + if (pGroup->usGroupTeam == ENEMY_TEAM) + { + const UINT8 intention = pGroup->pEnemyGroup->ubIntention; + if (intention == STAGING + || intention == REINFORCEMENTS + || intention == PURSUIT + || intention == ASSAULT) + { + WAYPOINT* wp = pGroup->pWaypoints; + + while (wp) + { + if (wp->next == nullptr) + break; + + wp = wp->next; + } + + if (GetSectorFlagStatus(wp->x-1, wp->y-1, (UINT8)iCurrentMapSectorZ, SF_ALREADY_VISITED)) + { + colorMap[wp->y-1][wp->x-1] = targetColor; + } + } + } + + pGroup = pGroup->next; + } + } } diff --git a/Strategic/MiniEvents.cpp b/Strategic/MiniEvents.cpp index 99a5585cf..ec801403a 100644 --- a/Strategic/MiniEvents.cpp +++ b/Strategic/MiniEvents.cpp @@ -1529,6 +1529,7 @@ void MiniEventsLua(UINT32 eventId) && pSoldier->stats.bLife > 0 && pSoldier->bAssignment != IN_TRANSIT && pSoldier->bAssignment != ASSIGNMENT_POW + && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) { gAllMercs.push_back(pSoldier); diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 2291b913c..737a89e09 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -1,4 +1,4 @@ -//#pragma optimize("", off) +#pragma optimize("", off) /* Rebel Command by rftr @@ -15,6 +15,9 @@ 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. +Missions were added later and provide powerful temporary bonuses. To enable these bonuses, Supplies must be spent as well as sending +either a generic rebel agent or one of their own mercenaries, the latter providing better mission bonuses. + How to add a new directive: - add to the RebelCommandDirectives enum in the header @@ -37,6 +40,16 @@ How to add a new admin action: - add admin-action-specific effect - if effect applies outside of towns, add help text range band as appropriate to SetupAdminActionBox +How to add a new mission: +- add to the RebelCommandAgentMissions enum in the header +- add strings to text files (szRebelCommandAgentMissionsText) +- add values to MissionHelpers::missionInfo table in SetupInfo() +- add to valid check in HandleStrategicEvent() (allows advance from first event/prepare to second event/active effect) +- add to SetupMissionAgentBox() (mission description and merc bonus text) +- add to StartMission() +- add mission-specific functions +- rftr todo: ??? + Points of interest: - Init() - set up rebel command for the first time - SetupInfo() - set constants @@ -60,19 +73,21 @@ Points of interest: #include "finances.h" #include "Font Control.h" #include "Game Clock.h" +#include "Game Event Hook.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 "Overhead Types.h" #include "Queen Command.h" #include "random.h" #include "SaveLoadGame.h" +#include "strategic.h" #include "strategicmap.h" #include "Strategic Mines.h" #include "Strategic Movement.h" @@ -84,10 +99,13 @@ Points of interest: #include "WordWrap.h" #endif +#include +#include + #define DIRECTIVE_TEXT(id) RCDT_##id##, RCDT_##id##_EFFECT, RCDT_##id##_DESC, RCDT_##id##_IMPROVE, +#define MISSION_TEXT(id) RCAMT_##id##_TITLE, RCAMT_##id##_DESC, #define ADMIN_ACTION_CHANGE_COST 15000 -#define GRANT_SUPPLIES_LOYALTY_GAIN 1000 #define REBEL_COMMAND_DROPDOWN DropDownTemplate::getInstance() @@ -97,12 +115,96 @@ Points of interest: #define WEBSITE_HEIGHT 395 extern UINT32 gCoolnessBySector[256]; -extern UINT32 guiInsuranceBackGround; extern BOOLEAN gfTownUsesLoyalty[MAX_TOWNS]; extern GROUP *gpGroupList; namespace RebelCommand { + +namespace MissionHelpers +{ +constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_COVERT = 1; +constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_SCOUTING = 2; +constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_STEALTHY = 3; +constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_SURVIVAL = 4; +constexpr UINT16 REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_COVERT = 1; +constexpr UINT16 REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_DEPUTY = 2; +constexpr UINT16 REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_SNITCH = 3; +constexpr UINT16 REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_COVERT = 1; +constexpr UINT16 REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_RADIO = 2; +constexpr UINT16 REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_STEALTHY = 3; +constexpr UINT16 SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_AUTO_WEAPONS = 1; +constexpr UINT16 SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_COVERT = 2; +constexpr UINT16 SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_DEMOLITIONS = 3; +constexpr UINT16 SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_GUNSLINGER = 4; +constexpr UINT16 SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_RANGER = 5; +constexpr UINT16 SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_SNIPER = 6; +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; + + +typedef struct { + std::vector newSkills; + std::vector oldSkills; + std::vector durationBonuses; + std::vector floatModifiers; + std::vector intModifiers; + std::vector extraBits; +} MissionInfo; + +// this vector serves as a comparison table to determine which bonuses will be applied to a mission +// see SetupInfo() for initialisation +std::vector missionInfo; + +// cached param for firing the preparation/first event. used in the mission start confirmation popup callback +UINT32 missionParam; + +void GetMissionInfo(RebelCommandAgentMissions mission, const MERCPROFILESTRUCT* merc, UINT32& durationBonus, FLOAT& floatModifier, INT16& intModifier, int& durationBonusSkill, int& floatModifierSkill, int& intModifierSkill, UINT16& extraBits) +{ + durationBonus = 0; + durationBonusSkill = 0; + floatModifier = 0; + floatModifierSkill = 0; + intModifier = 0; + intModifierSkill = 0; + extraBits = 0; + + const std::vector* skills = gGameOptions.fNewTraitSystem ? &missionInfo[mission].newSkills : &missionInfo[mission].oldSkills; + + for (int i = 0; i < sizeof(merc->bSkillTraits) / sizeof(merc->bSkillTraits[0]); ++i) + { + for (size_t j = 0; j < skills->size(); ++j) + { + if (merc->bSkillTraits[i] == (*skills)[j]) + { + if (missionInfo[mission].durationBonuses[j] > durationBonus) + { + durationBonus = missionInfo[mission].durationBonuses[j]; + durationBonusSkill = (*skills)[j]; + } + + if (missionInfo[mission].floatModifiers[j] > floatModifier) + { + floatModifier = missionInfo[mission].floatModifiers[j]; + floatModifierSkill = (*skills)[j]; + extraBits = missionInfo[mission].extraBits[j]; + } + + if (missionInfo[mission].intModifiers[j] > intModifier) + { + intModifier = missionInfo[mission].intModifiers[j]; + intModifierSkill = (*skills)[j]; + extraBits = missionInfo[mission].extraBits[j]; + } + } + } + } +} + +} + void DEBUG_DAY(); void DEBUG_PRINT(); @@ -110,16 +212,21 @@ enum WebsiteState { RCS_NATIONAL_OVERVIEW, RCS_REGIONAL_OVERVIEW, + RCS_AGENT_OVERVIEW, }; enum RebelCommandText // keep this synced with szRebelCommandText in the text files { RCT_NATIONAL_OVERVIEW = 0, RCT_REGIONAL_OVERVIEW, + RCT_AGENT_OVERVIEW, + RCT_SELECT_VIEW, RCT_SWITCH_TO_REGIONAL, RCT_SWITCH_TO_NATIONAL, + RCT_SWITCH_TO_AGENT, RCT_SUPPLIES, RCT_INCOMING_SUPPLIES, + RCT_INTEL, RCT_PER_DAY, RCT_CURRENT_DIRECTIVE, RCT_IMPROVE_DIRECTIVE, @@ -187,7 +294,6 @@ enum RebelCommandHelpText // keep this synced with szRebelCommandHelpText in the RCHT_ADMIN_TEAM, RCHT_LOYALTY, RCHT_MAX_LOYALTY, - RCHT_GRANT_SUPPLIES, RCHT_AA_TOWN_ONLY, RCHT_AA_TOWN_PLUS_ONE, RCHT_AA_TOWN_PLUS_TWO, @@ -210,21 +316,123 @@ enum RebelCommandDirectivesText // keep this synced with szRebelCommandDirective DIRECTIVE_TEXT(DRAFT) }; +enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentMissionsText in the text files +{ + //RCAMT_NOTIFY_MISSIONS_AVAILABLE, + RCAMT_NEW_MISSIONS_AVAILABLE_TIME, + RCAMT_MISSION_ACTIVE, + MISSION_TEXT(DEEP_DEPLOYMENT) + MISSION_TEXT(GET_ENEMY_MOVEMENT_TARGETS) + MISSION_TEXT(IMPROVE_LOCAL_SHOPS) + MISSION_TEXT(REDUCE_STRATEGIC_DECISION_SPEED) + MISSION_TEXT(REDUCE_UNALERTED_ENEMY_VISION) + MISSION_TEXT(SABOTAGE_INFANTRY_EQUIPMENT) + MISSION_TEXT(SABOTAGE_MECHANICAL_UNITS) + MISSION_TEXT(TRAIN_MILITIA_ANYWHERE) +}; + enum ChangeAdminActionState { CAAS_INIT, CAAS_CHANGING, }; +enum MissionOverviewSubview +{ + MOS_MISSION_LIST, + MOS_ACTIVE_MISSION_EFFECTS, +}; + +struct MissionFirstEvent +{ + BOOLEAN isFirstEvent; + BOOLEAN sentGenericRebelAgent; + BOOLEAN isMissionSuccess; + UINT8 mercProfileId; + UINT8 missionId; + UINT8 missionDurationInHours; + UINT8 extraBits; +}; + +struct MissionSecondEvent +{ + BOOLEAN isSecondEvent; + BOOLEAN sentGenericRebelAgent; + UINT8 mercProfileId; + UINT8 missionId; + UINT16 extraBits; +}; + +// serialisation/deserialisation functions for passing information into a strategic event param +UINT32 SerialiseMissionFirstEvent(BOOLEAN sentGenericRebelAgent, UINT8 mercProfileId, RebelCommandAgentMissions mission, UINT8 missionDuration, UINT8 extraBits) +{ + UINT32 ret = 0x00000000; + + if (!sentGenericRebelAgent) + ret |= 0x01000000; + + ret |= (mercProfileId << 16); + ret |= (static_cast(mission) << 8); + ret |= missionDuration; + + // extraBits can only be 6 bits + extraBits &= 0x3F; + + ret |= (extraBits << 25); + + return ret; +} + +void DeserialiseMissionFirstEvent(UINT32 param, MissionFirstEvent& evt) +{ + evt.isFirstEvent = ((param >> 31) & 0x00000001) == 0; + evt.sentGenericRebelAgent = ((param >> 24) & 0x00000001) == 0; + evt.isMissionSuccess = (param & 0x000000FF) > 0; + evt.mercProfileId = ((param >> 16) & 0x000000FF); + evt.missionId = ((param >> 8) & 0x000000FF); + evt.missionDurationInHours = (param & 0x000000FF); + evt.extraBits = ((param >> 25) & 0x0000003F); +} + +UINT32 SerialiseMissionSecondEvent(BOOLEAN sentGenericRebelAgent, UINT8 mercProfileId, RebelCommandAgentMissions mission, UINT16 extraBits) +{ + UINT32 ret = 0x80000000; + + if (!sentGenericRebelAgent) + ret |= 0x00010000; + + ret |= (mercProfileId << 8); + ret |= static_cast(mission); + + // extraBits can only be 14 bits + extraBits &= 0x3FFF; + + ret |= (extraBits << 17); + + return ret; +} + +void DeserialiseMissionSecondEvent(UINT32 param, MissionSecondEvent& evt) +{ + evt.isSecondEvent = ((param >> 31) & 0x00000001) == 1; + evt.sentGenericRebelAgent = ((param >> 16) & 0x00000001) == 0; + evt.mercProfileId = ((param >> 8) & 0x000000FF); + evt.missionId = (param & 0x000000FF); + evt.extraBits = ((param >> 17) & 0x0003FFF); +} + // website functions template void ButtonHelper(GUI_BUTTON* btn, INT32 reason, voidFunc onClick); +INT32 CalcIncomingSuppliesPerDay(RebelCommandDirectives directive); void ClearAllButtons(); void ClearAllHelpTextRegions(); void DeployOrReactivateAdminTeam(INT16 regionId); void DropdownSetup(); void GetDirectiveEffect(const RebelCommandDirectives directive, STR16 text); INT32 GetDirectiveImprovementCost(const RebelCommandDirectives directive); +INT32 GetMissionCost(); +INT8 GetMissionSuccessChanceBonus(const MERCPROFILESTRUCT* merc); void ImproveDirective(const RebelCommandDirectives directiveId); void PurchaseAdminAction(INT32 regionId, INT32 actionIndex); void RegionNavNext(); @@ -232,12 +440,18 @@ void RegionNavPrev(); void RenderHeader(RebelCommandText titleText); void RenderNationalOverview(); void RenderRegionalOverview(); +void RenderMissionOverview(); 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); +BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index); +void SetWebsiteView(WebsiteState newState); +void StartMission(INT8 index); void ToggleWebsiteView(); void UpdateAdminActionChangeList(INT16 regionId); +constexpr BOOLEAN CanAdminActionBeToggled(RebelCommandAdminActions action) { return action != RebelCommandAdminActions::RCAA_SUPPLY_LINE; } +BOOLEAN CanAdminActionBeUsed(INT32 regionIndex, INT32 actionIndex); INT32 GetAdminActionCostForRegion(INT16 regionId); INT16 GetAdminActionInRegion(INT16 regionId, RebelCommandAdminActions adminAction); UINT8 GetRegionLoyalty(INT16 regionId); @@ -250,8 +464,10 @@ std::vector btnIds; ChangeAdminActionState adminActionChangeState; // help text regions +MOUSE_REGION adminActionActiveTextRegion[5]; MOUSE_REGION adminActionHelpTextRegion[6]; MOUSE_REGION adminTeamHelpTextRegion; +//MOUSE_REGION agentNotifyToggleTextRegion; MOUSE_REGION directiveDescriptionHelpTextRegion; MOUSE_REGION loyaltyHelpTextRegion; MOUSE_REGION maxLoyaltyHelpTextRegion; @@ -266,6 +482,10 @@ INT16 iCurrentRegionId = 1; INT32 iIncomingSuppliesPerDay = 0; SaveInfo rebelCommandSaveInfo; WebsiteState websiteState; +//INT8 missionIndex[NUM_ARC_AGENT_SLOTS]; +INT8 agentIndex[NUM_ARC_AGENT_SLOTS]; +std::unordered_map missionMap; +MissionOverviewSubview missionOverviewSubview = MOS_MISSION_LIST; // website template @@ -285,6 +505,28 @@ void ButtonHelper(GUI_BUTTON* btn, INT32 reason, voidFunc onClick) } } +INT32 CalcIncomingSuppliesPerDay(RebelCommandDirectives directive) +{ + const INT32 base = static_cast(CurrentPlayerProgressPercentage() * gRebelCommandSettings.fIncomeModifier + (directive == RCD_GATHER_SUPPLIES ? rebelCommandSaveInfo.directives[RCD_GATHER_SUPPLIES].GetValue1() : 0)); + const INT32 supplyUpkeep = static_cast(gRebelCommandSettings.fIncomeModifier + 0.5f); + INT32 upkeepCount = 0; + + for (int a = FIRST_TOWN+1; a < NUM_TOWNS; ++a) + { + // ignore this region if there is no active admin team + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_ACTIVE) + continue; + + for (int b = 0; b < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++b) + { + if (rebelCommandSaveInfo.regions[a].IsActive(b) && rebelCommandSaveInfo.regions[a].GetLevel(b) > 0) + upkeepCount++; + } + } + + return base - upkeepCount * supplyUpkeep; +} + void ClearAllButtons() { for (const auto btnId : btnIds) @@ -296,9 +538,12 @@ void ClearAllButtons() void ClearAllHelpTextRegions() { + for (int a = 0; a < 5; a++) + MSYS_RemoveRegion(&adminActionActiveTextRegion[a]); for (int a = 0; a < 6; a++) MSYS_RemoveRegion(&adminActionHelpTextRegion[a]); MSYS_RemoveRegion(&adminTeamHelpTextRegion); + //MSYS_RemoveRegion(&agentNotifyToggleTextRegion); MSYS_RemoveRegion(&directiveDescriptionHelpTextRegion); MSYS_RemoveRegion(&loyaltyHelpTextRegion); MSYS_RemoveRegion(&maxLoyaltyHelpTextRegion); @@ -375,6 +620,19 @@ void DropdownSetup() REBEL_COMMAND_DROPDOWN.Create(WEBSITE_LEFT + 5, WEBSITE_TOP + 98); } +BOOLEAN CanAdminActionBeUsed(INT32 regionIndex, INT32 actionIndex) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) return FALSE; + + if (rebelCommandSaveInfo.regions[regionIndex].adminStatus != RAS_ACTIVE) return FALSE; + + if (rebelCommandSaveInfo.regions[regionIndex].GetLevel(actionIndex) == 0) return FALSE; + + if (CanAdminActionBeToggled(rebelCommandSaveInfo.regions[regionIndex].actions[actionIndex]) && !rebelCommandSaveInfo.regions[regionIndex].IsActive(actionIndex)) return FALSE; + + return TRUE; +} + INT32 GetAdminActionCostForRegion(INT16 regionId) { INT16 totalLocalActions = 0; @@ -385,10 +643,10 @@ INT32 GetAdminActionCostForRegion(INT16 regionId) { for (int b = 0; b < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++b) { - totalNationalActions += rebelCommandSaveInfo.regions[a].actionLevels[b]; + totalNationalActions += rebelCommandSaveInfo.regions[a].GetLevel(b); if (a == regionId) - totalLocalActions += rebelCommandSaveInfo.regions[a].actionLevels[b]; + totalLocalActions += rebelCommandSaveInfo.regions[a].GetLevel(b); } } @@ -401,7 +659,7 @@ INT16 GetAdminActionInRegion(INT16 regionId, RebelCommandAdminActions adminActio { for (int idx = 0; idx < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++idx) { - if (rebelCommandSaveInfo.regions[regionId].actions[idx] == adminAction) + if (rebelCommandSaveInfo.regions[regionId].actions[idx] == adminAction && rebelCommandSaveInfo.regions[regionId].IsActive(idx)) { return idx; } @@ -453,6 +711,17 @@ INT32 GetDirectiveImprovementCost(const RebelCommandDirectives directive) return rebelCommandSaveInfo.directives[directive].GetCostToImprove(); } +INT32 GetMissionCost() +{ + const INT32 additionalCost = missionMap.size() * 250; + return 500 + additionalCost; +} + +INT8 GetMissionSuccessChanceBonus(const MERCPROFILESTRUCT* merc) +{ + return merc ? merc->bExpLevel * 5 : 0; +} + void ImproveDirective(const RebelCommandDirectives directive) { const INT32 cost = rebelCommandSaveInfo.directives[directive].GetCostToImprove(); @@ -552,35 +821,111 @@ void SetupAdminActionBox(const UINT8 actionIndex, const UINT16 descriptionText, { // 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)) + || (actionIndex != RCAA_SUPPLY_LINE && rebelCommandSaveInfo.regions[iCurrentRegionId].GetLevel(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]; + const UINT8 level = rebelCommandSaveInfo.regions[iCurrentRegionId].GetLevel(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) + const INT32 btnId = CreateTextButton(text, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x, y, 140, 18, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) { - ButtonHelper(btn, reason, [btn]() { PurchaseAdminAction(btn->UserData[0], btn->UserData[1]); }); + ButtonHelper(btn, reason, [btn]() { PurchaseAdminAction(MSYS_GetBtnUserData(btn, 0), MSYS_GetBtnUserData(btn, 1)); }); }); - Assert(ButtonList[btnId]); - ButtonList[btnId]->UserData[0] = iCurrentRegionId; - ButtonList[btnId]->UserData[1] = actionIndex; + MSYS_SetBtnUserData(btnId, 0, iCurrentRegionId); + MSYS_SetBtnUserData(btnId, 1, actionIndex); btnIds.push_back(btnId); } y += 22; - swprintf(text, szRebelCommandText[RCT_ADMIN_ACTION_TIER], rebelCommandSaveInfo.regions[iCurrentRegionId].actionLevels[actionIndex]); + swprintf(text, szRebelCommandText[RCT_ADMIN_ACTION_TIER], rebelCommandSaveInfo.regions[iCurrentRegionId].GetLevel(actionIndex)); DrawTextToScreen(text, x, y, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + // show on/off switch for toggleable actions + if (CanAdminActionBeToggled(rebelCommandSaveInfo.regions[iCurrentRegionId].actions[actionIndex]) && rebelCommandSaveInfo.regions[iCurrentRegionId].GetLevel(actionIndex) > 0) + { + // draw checkbox text + DrawTextToScreen(szRebelCommandText[RCT_ACTIVE], x+125, y, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, RIGHT_JUSTIFIED); + + // draw checkbox + const INT32 btnId = CreateCheckBoxButton(x + 128, y-3, "INTERFACE\\OptionsCheckBoxes_12x12.sti", MSYS_PRIORITY_HIGH, [](GUI_BUTTON* btn, INT32 reason) { + const UINT8 regionIndex = (UINT8)MSYS_GetBtnUserData( btn, 0 ); + const UINT8 actionIndex = (UINT8)MSYS_GetBtnUserData( btn, 1 ); + + if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP) + { + if (btn->uiFlags & BUTTON_CLICKED_ON) + { + // don't toggle on if we have a bad supply balance + if (rebelCommandSaveInfo.iSupplies <= 0) + return; + + btn->uiFlags &= ~BUTTON_CLICKED_ON; + rebelCommandSaveInfo.regions[regionIndex].SetActive(actionIndex); + } + else + { + btn->uiFlags |= BUTTON_CLICKED_ON; + rebelCommandSaveInfo.regions[regionIndex].SetInactive(actionIndex); + } + } + RenderWebsite(); + }); + + MSYS_SetBtnUserData( btnId, 0, iCurrentRegionId ); + MSYS_SetBtnUserData( btnId, 1, actionIndex ); + + Assert(ButtonList[btnId]); + if (rebelCommandSaveInfo.regions[iCurrentRegionId].IsActive(actionIndex)) + ButtonList[btnId]->uiFlags |= BUTTON_CLICKED_ON; + + btnIds.push_back(btnId); + + // setup mouse target for "Active" text - setting this AFTER the checkbox so we can set the button id + MSYS_DefineRegion(&adminActionActiveTextRegion[actionIndex-1], x+75, y-2, x+125, y+14, MSYS_PRIORITY_HIGH, + CURSOR_LAPTOP_SCREEN, MSYS_NO_CALLBACK, [](MOUSE_REGION* pRegion, INT32 iReason) { + if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) + { + const UINT8 regionIndex = (UINT8)MSYS_GetRegionUserData( pRegion, 0 ); + const UINT8 actionIndex = (UINT8)MSYS_GetRegionUserData( pRegion, 1 ); + const INT32 buttonId = MSYS_GetRegionUserData( pRegion, 2 ); + GUI_BUTTON* btn = ButtonList[buttonId]; + + if (btn->uiFlags & BUTTON_CLICKED_ON) + { + // don't toggle on if we have a bad supply balance + if (rebelCommandSaveInfo.iSupplies <= 0) + return; + + btn->uiFlags &= ~BUTTON_CLICKED_ON; + rebelCommandSaveInfo.regions[regionIndex].SetInactive(actionIndex); + } + else + { + btn->uiFlags |= BUTTON_CLICKED_ON; + rebelCommandSaveInfo.regions[regionIndex].SetActive(actionIndex); + } + + RenderWebsite(); + } + }); + MSYS_AddRegion(&adminActionActiveTextRegion[actionIndex-1]); + MSYS_SetRegionUserData(&adminActionActiveTextRegion[actionIndex-1], 0, iCurrentRegionId); + MSYS_SetRegionUserData(&adminActionActiveTextRegion[actionIndex-1], 1, actionIndex); + MSYS_SetRegionUserData(&adminActionActiveTextRegion[actionIndex-1], 2, btnId); + + } + y += 13; - DisplayWrappedString(x, y, 140, 2, FONT10ARIAL, FONT_MCOLOR_BLACK, szRebelCommandAdminActionsText[descriptionText], FONT_MCOLOR_BLACK, FALSE, 0); + const UINT8 textColor = rebelCommandSaveInfo.regions[iCurrentRegionId].IsActive(actionIndex) ? FONT_MCOLOR_BLACK : FONT_MCOLOR_DKGRAY; + DisplayWrappedString(x, y, 140, 2, FONT10ARIAL, textColor, szRebelCommandAdminActionsText[descriptionText], FONT_MCOLOR_BLACK, FALSE, 0); helpTextY = y; + // special case for index 5: show state change button if (actionIndex == 5) { @@ -711,12 +1056,27 @@ void SetRegionHelpText(INT32 reason, MOUSE_REGION& helpTextRegion, RebelCommandH SetRegionFastHelpText(&helpTextRegion, L""); } +void SetWebsiteView(WebsiteState newState) +{ + websiteState = newState; +} + void ToggleWebsiteView() { - if (websiteState == RCS_REGIONAL_OVERVIEW) - websiteState = RCS_NATIONAL_OVERVIEW; - else + switch (websiteState) + { + case RCS_NATIONAL_OVERVIEW: websiteState = RCS_REGIONAL_OVERVIEW; + break; + + case RCS_REGIONAL_OVERVIEW: + websiteState = RCS_AGENT_OVERVIEW; + break; + + case RCS_AGENT_OVERVIEW: + websiteState = RCS_NATIONAL_OVERVIEW; + break; + } } void UpdateAdminActionChangeList(INT16 regionId) @@ -747,6 +1107,16 @@ void UpdateAdminActionChangeList(INT16 regionId) BOOLEAN EnterWebsite() { + // debugging. todo: randomise missions in DailyUpdate and save them in rebelcommandsaveinfo + for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + //missionIndex[i] = Random(RCAM_NUM_MISSIONS-1) + 1; + rebelCommandSaveInfo.availableMissions[i] = Random(RCAM_NUM_MISSIONS); + agentIndex[i] = -1; + } + //missionIndex[0] = RCAM_TRAIN_MILITIA_ANYWHERE; + //missionIndex[1] = RCAM_IMPROVE_LOCAL_SHOPS; + UpdateAdminActionChangeList(iCurrentRegionId); // make sure we have a valid directive @@ -760,14 +1130,6 @@ BOOLEAN EnterWebsite() 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); - - RenderWebsite(); return(TRUE); @@ -778,8 +1140,6 @@ void ExitWebsite() ClearAllButtons(); ClearAllHelpTextRegions(); REBEL_COMMAND_DROPDOWN.Destroy(); - - DeleteVideoObjectFromIndex(guiInsuranceBackGround); } void HandleWebsite() @@ -809,6 +1169,21 @@ void HandleWebsite() RenderWebsite(); break; + case '1': + SetWebsiteView(RCS_NATIONAL_OVERVIEW); + RenderWebsite(); + break; + + case '2': + SetWebsiteView(RCS_REGIONAL_OVERVIEW); + RenderWebsite(); + break; + + case '3': + SetWebsiteView(RCS_AGENT_OVERVIEW); + RenderWebsite(); + break; + default: HandleKeyBoardShortCutsForLapTop(input.usEvent, input.usParam, input.usKeyState); break; @@ -833,9 +1208,9 @@ void RenderWebsite() ClearAllHelpTextRegions(); // background - WebPageTileBackground(4, 4, 125, 100, guiInsuranceBackGround); + ColorFillVideoSurfaceArea(FRAME_BUFFER, WEBSITE_LEFT, WEBSITE_TOP, WEBSITE_LEFT + WEBSITE_WIDTH, WEBSITE_TOP + WEBSITE_HEIGHT, Get16BPPColor(FROMRGB(224, 224, 224))); - SetFontShadow(FONT_MCOLOR_WHITE); + SetFontShadow(FONT_GRAY1); // national/regional views switch (websiteState) @@ -844,6 +1219,10 @@ void RenderWebsite() RenderRegionalOverview(); break; + case RCS_AGENT_OVERVIEW: + RenderMissionOverview(); + break; + case RCS_NATIONAL_OVERVIEW: default: RenderNationalOverview(); @@ -861,10 +1240,11 @@ void RenderHeader(RebelCommandText titleText) { CHAR16 sText[500]; UINT16 usPosX, usPosY; + INT32 btnId; // title usPosX = WEBSITE_LEFT + 1; - usPosY = WEBSITE_TOP + 3; + usPosY = WEBSITE_TOP + 2; DrawTextToScreen(szRebelCommandText[titleText], usPosX, usPosY, 0, FONT16ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // supplies @@ -873,21 +1253,70 @@ void RenderHeader(RebelCommandText titleText) DrawTextToScreen(szRebelCommandText[RCT_SUPPLIES], usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // supply count - usPosX = WEBSITE_LEFT + 50; + usPosX = WEBSITE_LEFT + 55; 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); + // intel + usPosX = WEBSITE_LEFT + 150; + usPosY = WEBSITE_TOP + 23; + DrawTextToScreen(szRebelCommandText[RCT_INTEL], usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // intel count + usPosX = WEBSITE_LEFT + 185; + usPosY = WEBSITE_TOP + 20; + const int intel = (int)GetIntel(); + swprintf(sText, L"%d", intel); + DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, intel > 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); + // view select text + usPosX = WEBSITE_LEFT + 251; + usPosY = WEBSITE_TOP + 3; + DrawTextToScreen(szRebelCommandText[RCT_SELECT_VIEW], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // view swap buttons + usPosY = WEBSITE_TOP + 13; + btnId = CreateTextButton(szRebelCommandText[RCT_SWITCH_TO_NATIONAL], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 82, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() { SetWebsiteView(RCS_NATIONAL_OVERVIEW); }); + }); + btnIds.push_back(btnId); + usPosX = WEBSITE_LEFT + 334; + btnId = CreateTextButton(szRebelCommandText[RCT_SWITCH_TO_REGIONAL], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 82, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() { SetWebsiteView(RCS_REGIONAL_OVERVIEW); }); + }); + btnIds.push_back(btnId); + usPosX = WEBSITE_LEFT + 417; + btnId = CreateTextButton(szRebelCommandText[RCT_SWITCH_TO_AGENT], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 82, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() { SetWebsiteView(RCS_AGENT_OVERVIEW); }); + }); + btnIds.push_back(btnId); + // 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)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // DEBUG if (CHEATER_CHEAT_LEVEL()) @@ -920,15 +1349,6 @@ void RenderNationalOverview() // title RenderHeader(RCT_NATIONAL_OVERVIEW); - // view swap button - usPosX = WEBSITE_LEFT + 350; - usPosY = WEBSITE_TOP + 1; - btnId = CreateTextButton(szRebelCommandText[RCT_SWITCH_TO_REGIONAL], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 149, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) - { - ButtonHelper(btn, reason, []() { ToggleWebsiteView(); }); - }); - btnIds.push_back(btnId); - // incoming supplies usPosX = WEBSITE_LEFT + 1; usPosY = WEBSITE_TOP + 40; @@ -936,7 +1356,7 @@ void RenderNationalOverview() usPosX = WEBSITE_LEFT + 5; usPosY += 10; - iIncomingSuppliesPerDay = static_cast(CurrentPlayerProgressPercentage() * gRebelCommandSettings.fIncomeModifier + (rebelCommandSaveInfo.iSelectedDirective == RCD_GATHER_SUPPLIES ? rebelCommandSaveInfo.directives[RCD_GATHER_SUPPLIES].GetValue1() : 0)); + iIncomingSuppliesPerDay = CalcIncomingSuppliesPerDay(static_cast(rebelCommandSaveInfo.iSelectedDirective)); swprintf(sText, L"%d", iIncomingSuppliesPerDay); DrawTextToScreen(sText, usPosX, usPosY, 0, FONT14ARIAL, iIncomingSuppliesPerDay > 0 ? FONT_GREEN : FONT_MCOLOR_LTRED, FONT_MCOLOR_BLACK, FALSE, 0); @@ -954,14 +1374,62 @@ void RenderNationalOverview() 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); + CURSOR_LAPTOP_SCREEN, [](MOUSE_REGION* pRegion, INT32 iReason) { + if (iReason == MSYS_CALLBACK_REASON_MOVE) + { + CHAR16 text[1000]; + + // base income + const INT32 base = static_cast(CurrentPlayerProgressPercentage() * gRebelCommandSettings.fIncomeModifier); + swprintf(text, szRebelCommandHelpText[RCHT_SUPPLIES_INCOME], base); + + // admin action upkeep + const INT32 supplyUpkeep = static_cast(gRebelCommandSettings.fIncomeModifier + 0.5f); + + for (int a = FIRST_TOWN+1; a < NUM_TOWNS; ++a) + { + // ignore this region if there is no active admin team + if (rebelCommandSaveInfo.regions[a].adminStatus != RAS_ACTIVE) + continue; + + INT32 upkeepCount = 0; + for (int b = 0; b < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++b) + { + if (rebelCommandSaveInfo.regions[a].IsActive(b) && rebelCommandSaveInfo.regions[a].GetLevel(b) > 0) + upkeepCount++; + } + + if (upkeepCount > 0) + { + const INT32 totalUpkeep = upkeepCount * supplyUpkeep; + swprintf(text, L"%s\n-%d (%s)", text, totalUpkeep, pTownNames[a]); + } + } + + SetRegionFastHelpText(&suppliesIncomeHelpTextRegion, text); + } + else if (iReason == MSYS_CALLBACK_REASON_LOST_MOUSE) + SetRegionFastHelpText(&suppliesIncomeHelpTextRegion, L""); + }, 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)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // current directive usPosX = WEBSITE_LEFT + 1; @@ -981,12 +1449,11 @@ void RenderNationalOverview() swprintf(sText, szRebelCommandText[RCT_IMPROVE_DIRECTIVE], GetDirectiveImprovementCost(static_cast(directive))); btnId = 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])); }); + ButtonHelper(btn, reason, [btn]() { ImproveDirective(static_cast(MSYS_GetBtnUserData(btn, 0))); }); }); btnIds.push_back(btnId); - Assert(ButtonList[btnId]); - ButtonList[btnId]->UserData[0] = REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey(); + MSYS_SetBtnUserData( btnId, 0, REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey() ); } // directive effect @@ -1016,7 +1483,19 @@ void RenderNationalOverview() // line between directive and militia usPosX = WEBSITE_LEFT - 1; usPosY += 10; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // militia usPosX = WEBSITE_LEFT + 1; @@ -1063,7 +1542,19 @@ void RenderNationalOverview() // draw vertical line usPosX += 75; usPosY = militiaY - 3; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX, usPosY + 38, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // header usPosX += 20; @@ -1084,8 +1575,19 @@ void RenderNationalOverview() // draw vertical line usPosX += 75; usPosY = militiaY - 3; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX, usPosY + 38, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // headers usPosX += 20; DrawTextToScreen(szRebelCommandText[RCT_MILITIA_RESOURCES], usPosX, usPosY, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); @@ -1112,7 +1614,19 @@ void RenderNationalOverview() // line usPosX = WEBSITE_LEFT + 25; usPosY = militiaY + 50; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX + 450, usPosY, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // training cost usPosX = WEBSITE_LEFT + 10; @@ -1121,7 +1635,19 @@ void RenderNationalOverview() // draw vertical line usPosX += 120; - DisplaySmallColouredLineWithShadow(usPosX, usPosY - 2, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY - 2, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY - 2, usPosX, usPosY + 38, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // upkeep cost usPosX += 20; @@ -1164,7 +1690,19 @@ void RenderNationalOverview() // line usPosX = WEBSITE_LEFT + 25; usPosY += 30; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX + 450, usPosY, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // training speed bonus usPosX = WEBSITE_LEFT + 10; @@ -1187,7 +1725,19 @@ void RenderNationalOverview() // draw vertical line usPosX = WEBSITE_LEFT + 130; usPosY -= 12; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX, usPosY + 38, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // militia physical stat bonus usPosX += 20; @@ -1233,15 +1783,6 @@ void RenderRegionalOverview() // title RenderHeader(RCT_REGIONAL_OVERVIEW); - // view swap button - usPosX = WEBSITE_LEFT + 350; - usPosY = WEBSITE_TOP + 1; - btnId = CreateTextButton(szRebelCommandText[RCT_SWITCH_TO_NATIONAL], FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 149, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) - { - ButtonHelper(btn, reason, []() { ToggleWebsiteView(); }); - }); - btnIds.push_back(btnId); - // region usPosX = WEBSITE_LEFT + 1; usPosY = WEBSITE_TOP + 40; @@ -1277,12 +1818,24 @@ void RenderRegionalOverview() // line between region info and admin info usPosX = WEBSITE_LEFT - 1; - usPosY += 20; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + usPosY += 15; + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; - // admin team - usPosX = WEBSITE_LEFT + 1; - usPosY += 5; + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } + + // 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 @@ -1316,7 +1869,19 @@ void RenderRegionalOverview() // vertical line between admin team and loyalty usPosX = WEBSITE_LEFT + 105; usPosY += 5; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX, usPosY + 15, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // loyalty usPosX += 15; @@ -1347,7 +1912,19 @@ void RenderRegionalOverview() // vertical line between loyalty and max loyalty usPosX = WEBSITE_LEFT + 195; usPosY += 5; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX, usPosY + 15, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // max loyalty usPosX += 15; @@ -1375,37 +1952,21 @@ void RenderRegionalOverview() MSYS_AddRegion(&maxLoyaltyHelpTextRegion); MSYS_SetRegionUserData(&maxLoyaltyHelpTextRegion, 0, 0); - // vertical line between max loyalty and supply grant + // vertical line between max loyalty usPosX = WEBSITE_LEFT + 325; usPosY += 5; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); - - if (iCurrentRegionId != OMERTA && rebelCommandSaveInfo.regions[iCurrentRegionId].adminStatus == RAS_ACTIVE) + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); { - // supply grant - usPosX = WEBSITE_LEFT + 334; - btnId = CreateTextButton(L"Grant 100 Supplies", FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, usPosX, usPosY, 165, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) - { - ButtonHelper(btn, reason, []() - { - if (rebelCommandSaveInfo.iSupplies >= 100) - { - rebelCommandSaveInfo.iSupplies -= 100; - IncrementTownLoyalty(iCurrentRegionId, static_cast(GRANT_SUPPLIES_LOYALTY_GAIN)); + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; - if (rebelCommandSaveInfo.uSupplyDropCount < 255) - rebelCommandSaveInfo.uSupplyDropCount++; - } - else - { - DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); - } - }); - }); - btnIds.push_back(btnId); - - // supply grant region - SetButtonFastHelpText(btnId, szRebelCommandHelpText[RCHT_GRANT_SUPPLIES]); + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX, usPosY + 15, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); } // deploy/reactivate admin teams (if applicable) @@ -1447,12 +2008,11 @@ void RenderRegionalOverview() swprintf(sText, szRebelCommandText[RCT_DEPLOY_ADMIN_TEAM], adminDeployCost); btnId = 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]); }); + ButtonHelper(btn, reason, [btn]() { DeployOrReactivateAdminTeam(MSYS_GetBtnUserData(btn, 0)); }); }); btnIds.push_back(btnId); - Assert(ButtonList[btnId]); - ButtonList[btnId]->UserData[0] = iCurrentRegionId; + MSYS_SetBtnUserData( btnId, 0, iCurrentRegionId ); return; } else if (rebelCommandSaveInfo.regions[iCurrentRegionId].adminStatus == RAS_INACTIVE) @@ -1469,20 +2029,31 @@ void RenderRegionalOverview() swprintf(sText, szRebelCommandText[RCT_REACTIVATE_ADMIN_TEAM], adminReactivateCost / 2); btnId = 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]); }); + ButtonHelper(btn, reason, [btn]() { DeployOrReactivateAdminTeam(MSYS_GetBtnUserData(btn, 0)); }); }); btnIds.push_back(btnId); - Assert(ButtonList[btnId]); - ButtonList[btnId]->UserData[0] = iCurrentRegionId; + MSYS_SetBtnUserData( btnId, 0, iCurrentRegionId ); return; } // line between admin info and admin actions usPosX = WEBSITE_LEFT - 1; - usPosY += 30; - DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 500, usPosY, FROMRGB(240, 240, 240)); + usPosY += 25; + //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); + { + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + LineDraw(FALSE, usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + } // admin actions usPosX = WEBSITE_LEFT + 1; @@ -1506,6 +2077,587 @@ void RenderRegionalOverview() swprintf(sText, szRebelCommandText[RCT_ADMIN_ACTION_COST], GetAdminActionCostForRegion(iCurrentRegionId)); DrawTextToScreen(sText, usPosX, usPosY, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } + +BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) +{ + CHAR16 sText[800]; + INT32 btnId; + VOBJECT_DESC vObjDesc; + HVOBJECT hvObj; + char sTemp[100]; + UINT32 image; + UINT32 uiDestPitchBYTES; + UINT8 *pDestBuf; + + // temp/fixme + std::vector mercs; + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[i]; + + if (pSoldier && pSoldier->bActive + && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) + ) + { + mercs.push_back(pSoldier); + } + } + + pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + // top horizontal line + LineDraw(FALSE, x, y, x+230, y, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + // bottom horizontal line + LineDraw(FALSE, x, y+300, x+230, y+300, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + // left vertical line + LineDraw(FALSE, x, y, x, y+300, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + // right vertical line + LineDraw(FALSE, x+230, y, x+230, y+300, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + + UnLockVideoSurface( FRAME_BUFFER ); + + // clamp indices + //if (missionIndex[index] < 0) missionIndex[index] = RCAM_NUM_MISSIONS - 1; + //else if (missionIndex[index] >= RCAM_NUM_MISSIONS) missionIndex[index] = 0; + // we're reserving an index for the generic rebel agent, so no need to subtract 1 from size here + if (agentIndex[index] < 0) agentIndex[index] = static_cast(mercs.size()); + else if (agentIndex[index] > static_cast(mercs.size())) agentIndex[index] = 0; + + // draw mission title + switch (rebelCommandSaveInfo.availableMissions[index]) + { + case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_TITLE]); break; + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE]); break; + case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_TITLE]); break; + case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_TITLE]); break; + case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_TITLE]); break; + 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; + + default: swprintf(sText, L"Mission Index: %d", rebelCommandSaveInfo.availableMissions[index]); break; + } + DrawTextToScreen(sText, x+5, y+5, 0, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw mission base duration, in days + UINT8 missionDurationBase = 0; + switch (rebelCommandSaveInfo.availableMissions[index]) + { + case RCAM_DEEP_DEPLOYMENT: missionDurationBase = gRebelCommandSettings.iDeepDeploymentDuration; break; + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionDurationBase = gRebelCommandSettings.iGetEnemyMovementTargetsDuration; break; + case RCAM_IMPROVE_LOCAL_SHOPS: missionDurationBase = gRebelCommandSettings.iImproveLocalShopsDuration; break; + case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionDurationBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration; break; + case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionDurationBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration; break; + 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; + + default: break; + } + // convert from hours + missionDurationBase /= 24; + swprintf(sText, L"Mission duration: %d days", missionDurationBase); + DrawTextToScreen(sText, x+5, y+21, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw mission base success chance + int missionSuccessChanceBase = 50; + switch (rebelCommandSaveInfo.availableMissions[index]) + { + case RCAM_DEEP_DEPLOYMENT: missionSuccessChanceBase = gRebelCommandSettings.iDeepDeploymentSuccessChance; break; + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionSuccessChanceBase = gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance; break; + case RCAM_IMPROVE_LOCAL_SHOPS: missionSuccessChanceBase = gRebelCommandSettings.iImproveLocalShopsSuccessChance; break; + case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionSuccessChanceBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedSuccessChance; break; + case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionSuccessChanceBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionSuccessChance; break; + 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; + + default: break; + } + swprintf(sText, L"Chance of success: %d%s", missionSuccessChanceBase, L"%%"); + DrawTextToScreen(sText, x+5, y+33, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw mission description + switch (rebelCommandSaveInfo.availableMissions[index]) + { + case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_DESC]); break; + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_DESC]); break; + case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_DESC]); break; + case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_DESC]); break; + case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_DESC]); break; + 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; + + 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; + } + DisplayWrappedString(x+5, y+45, 220, 2, FONT10ARIAL, FONT_MCOLOR_BLACK, sText, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw agent portrait + if (agentIndex[index] == mercs.size()) + { + // draw black box for face + ColorFillVideoSurfaceArea(FRAME_BUFFER, x+5, y+150+10, x+5+48, y+150+10+43, Get16BPPColor(FROMRGB(64, 64, 64))); + + // draw question mark + SetFontShadow(NO_SHADOW); + DrawTextToScreen(L"?", x+5+20, y+150+10+16, 0, FONT14HUMANIST, FONT_MCOLOR_WHITE, FONT_MCOLOR_BLACK, FALSE, 0); + SetFontShadow(FONT_GRAY1); + + // draw name + DrawTextToScreen(L"Name: [REDACTED]", x+55, y+150+10, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw location + DrawTextToScreen(L"Location: [REDACTED]", x+55, y+150+22, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw assignment + DrawTextToScreen(L"Assignment: None", x+55, y+150+34, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw contract + DrawTextToScreen(L"Contract: ---", x+55, y+150+46, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + } + else + { + // draw face + vObjDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; + sprintf(sTemp, "FACES\\%02d.sti", gMercProfiles[mercs[agentIndex[index]]->ubProfile].ubFaceIndex); + FilenameForBPP(sTemp, vObjDesc.ImageFile); + CHECKF(AddVideoObject(&vObjDesc, &image)); + GetVideoObject(&hvObj, image); + BltVideoObject(FRAME_BUFFER, hvObj, 0, x+5, y+150+10, VO_BLT_SRCTRANSPARENCY, NULL); + + // draw name + swprintf(sText, L"Name: %s", gMercProfiles[mercs[agentIndex[index]]->ubProfile].zName); + DrawTextToScreen(sText, x+55, y+150+10, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw location + CHAR16 locationStr[128]; + GetSectorIDString(mercs[agentIndex[index]]->sSectorX, mercs[agentIndex[index]]->sSectorY, 0, locationStr, TRUE); + swprintf(sText, L"Location: %s", locationStr); + DrawTextToScreen(sText, x+55, y+150+22, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw assignment + swprintf( sText, L"Assignment: %s", pAssignmentStrings[mercs[agentIndex[index]]->bAssignment]); + DrawTextToScreen(sText, x+55, y+150+34, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw contract + const BOOLEAN fromAim = mercs[agentIndex[index]]->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC; + + if (fromAim) + { + const INT32 endTime = mercs[agentIndex[index]]->iEndofContractTime; + const INT32 worldMin = GetWorldTotalMin(); + const INT32 remaining = endTime - worldMin; + + if (remaining >= 24 * 60) + { + swprintf(sText, L"Contract: %d days", remaining / (24 * 60)); + } + else + { + swprintf(sText, L"Contract: %d hours", remaining / 60); + } + } + else + { + swprintf(sText, L"Contract: ---"); + } + DrawTextToScreen(sText, x+55, y+150+46, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + } + + // draw btns under face + btnId = CreateTextButton(L"<<", FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x+5, y+150+54, 24, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + const INT8 index = MSYS_GetBtnUserData(btn, 0); + ButtonHelper(btn, reason, [btn, index]() { agentIndex[index]--; }); + }); + MSYS_SetBtnUserData(btnId, 0, index); + btnIds.push_back(btnId); + + btnId = CreateTextButton(L">>", FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x+5+24, y+150+54, 24, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + const INT8 index = MSYS_GetBtnUserData(btn, 0); + ButtonHelper(btn, reason, [btn, index]() { agentIndex[index]++; }); + }); + MSYS_SetBtnUserData(btnId, 0, index); + btnIds.push_back(btnId); + + // draw agent bonus header text + swprintf(sText, L"Agent bonus:"); + DrawTextToScreen(sText, x+5, y+150+54+20+2, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + + // draw agent bonus text + UINT32 durationBonus = 0; + int durationBonusSkill = 0; + std::vector agentBonusText; + if (agentIndex[index] < static_cast(mercs.size())) + { + const MERCPROFILESTRUCT merc = gMercProfiles[mercs[agentIndex[index]]->ubProfile]; + const INT8 successBonus_expLevel = GetMissionSuccessChanceBonus(&merc); + CHAR16 successText[100]; + // stupid string hack to get the percent sign to display correctly + swprintf(successText, L"Chance of success +%d%s (%s)", successBonus_expLevel, L"%s", pShortAttributeStrings[5]); // "Lvl" + agentBonusText.push_back(successText); + + const STR16* locSkillText = gGameOptions.fNewTraitSystem ? gzMercSkillTextNew : gzMercSkillText; + INT16 intModifier; + int intModifierSkill; + FLOAT floatModifier; + int floatModifierSkill; + UINT16 extraBits; + MissionHelpers::GetMissionInfo(static_cast(rebelCommandSaveInfo.availableMissions[index]), &merc, durationBonus, floatModifier, intModifier, durationBonusSkill, floatModifierSkill, intModifierSkill, extraBits); + switch (rebelCommandSaveInfo.availableMissions[index]) + { + case RCAM_DEEP_DEPLOYMENT: + { + intModifier = max(intModifier, gRebelCommandSettings.iDeepDeploymentRangeEW); + CHAR16 rangeText[100]; + swprintf(rangeText, L"Deployment range +%d (%s)", intModifier, locSkillText[intModifierSkill]); + agentBonusText.push_back(rangeText); + } + break; + + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: + { + // no special modifiers. included for completeness. + } + break; + + case RCAM_IMPROVE_LOCAL_SHOPS: + { + // no special modifiers. included for completeness. + } + break; + + case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: + { + floatModifier = max(floatModifier, gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier); + floatModifier -= 1.f; + floatModifier *= 100.f; + CHAR16 rangeText[100]; + swprintf(rangeText, L"Time +%2.0f%s (%s)", floatModifier, L"%s", locSkillText[floatModifierSkill]); + agentBonusText.push_back(rangeText); + } + break; + + case RCAM_REDUCE_UNALERTED_ENEMY_VISION: + { + floatModifier = max(floatModifier, gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier); + floatModifier *= 100.f; + CHAR16 text[100]; + swprintf(text, L"Vision -%2.0f%s (%s)", floatModifier, L"%s", locSkillText[floatModifierSkill]); + agentBonusText.push_back(text); + } + break; + + case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: + { + intModifier = max(intModifier, gRebelCommandSettings.iSabotageInfantryEquipmentModifier); + CHAR16 text[100]; + swprintf(text, L"Gear quality -%d (%s)", intModifier, locSkillText[intModifierSkill]); + agentBonusText.push_back(text); + } + break; + + case RCAM_SABOTAGE_MECHANICAL_UNITS: + { + intModifier = max(intModifier, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss); + CHAR16 text[100]; + swprintf(text, L"Overall stats -%d (%s)", intModifier, locSkillText[intModifierSkill]); + agentBonusText.push_back(text); + } + break; + + case RCAM_TRAIN_MILITIA_ANYWHERE: + { + intModifier = max(intModifier, 1); + CHAR16 text[100]; + swprintf(text, L"Max trainers: %d (%s)", intModifier, locSkillText[intModifierSkill]); + agentBonusText.push_back(text); + } + break; + + default: break; + } + + if (durationBonus > 0) + { + CHAR16 durationText[100]; + swprintf(durationText, L"Duration +%d hours (%s)", durationBonus, locSkillText[durationBonusSkill]); + agentBonusText.push_back(durationText); + } + } + + if (agentBonusText.size() == 0) + { + DrawTextToScreen(L"None", x+10, y+150+54+20+2+11, 0, FONT10ARIAL, FONT_MCOLOR_RED, FONT_MCOLOR_BLACK, FALSE, 0); + } + else + { + for (UINT8 i = 0; i < agentBonusText.size(); ++i) + { + // the percent sign here is a hack to get it to display properly for string that need a percent sign + swprintf(sText, agentBonusText[i], L"%%"); + DrawTextToScreen(sText, x+10, y+150+54+20+2+11*(i+1), 0, FONT10ARIAL, FONT_GREEN, FONT_MCOLOR_BLACK, FALSE, 0); + } + } + + // draw "start mission" btn + swprintf(sText, L"Start Mission (%d supplies)", GetMissionCost()); + btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x, y+290, 231, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + const INT8 index = MSYS_GetBtnUserData(btn, 0); + ButtonHelper(btn, reason, [btn, index]() { + StartMission(index); + }); + }); + MSYS_SetBtnUserData(btnId, 0, index); + btnIds.push_back(btnId); + + return TRUE; +} + +void RenderMissionOverview() +{ + // randomised missions - preserved in bitarray (24h refresh if none selected) + // only 1 active mission? allow multiple? + // increase cost based on num active missions? + // need a ui toggle between active missions and mission select + // need to convey that different folks can go on different missions, skills provide different bonuses + // we can probably store a lot of info in the strategic event int64 since we don't need to query it that often - on load, on mission start (send event)/end (receive event) + // 24 hours to find out if success/fail, then hold agent for a few days? + // don't need to save active missions - on load game, check strategic events (I have confirmed that strategic events are loaded before rebelcommandsaveinfo) + CHAR16 sText[800]; + INT32 btnId; + + // title + RenderHeader(RCT_AGENT_OVERVIEW); + + // toggle between mission picker and active mission effects + switch (missionOverviewSubview) + { + case MOS_MISSION_LIST: + swprintf(sText, L"View active mission effects"); + break; + + case MOS_ACTIVE_MISSION_EFFECTS: + swprintf(sText, L"View available mission list"); + break; + } + btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, WEBSITE_LEFT + 15, WEBSITE_TOP + 40, 470, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() + { + switch (missionOverviewSubview) + { + case MOS_MISSION_LIST: + missionOverviewSubview = MOS_ACTIVE_MISSION_EFFECTS; + break; + + case MOS_ACTIVE_MISSION_EFFECTS: + missionOverviewSubview = MOS_MISSION_LIST; + break; + } + }); + }); + + btnIds.push_back(btnId); + + // main body + switch (missionOverviewSubview) + { + case MOS_MISSION_LIST: + for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + SetupMissionAgentBox(WEBSITE_LEFT + 15 + 240 * i, WEBSITE_TOP + 65, i); + } + break; + + case MOS_ACTIVE_MISSION_EFFECTS: + // rftr todo: run through active mission list (missionMap) and show a one-line description for each. + // need a scroll or pagination if several missions active + // otherwise, no active effects + DrawTextToScreen(L"No active missions.", WEBSITE_LEFT + 25, WEBSITE_TOP + 75, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + break; + } + + // "new missions every X hours" text + DrawTextToScreen(szRebelCommandAgentMissionsText[RCAMT_NEW_MISSIONS_AVAILABLE_TIME], WEBSITE_LEFT + 22, WEBSITE_TOP + WEBSITE_HEIGHT - 17, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); +} + +void StartMission(INT8 index) +{ + const INT32 cost = GetMissionCost(); + if (rebelCommandSaveInfo.iSupplies < cost) + { + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); + return; + } + + // todo do something with agentIndex[index] and missionIndex[index] (rebelCommandSaveInfo.availableMissions[index]) + // confirmation popup + std::vector mercs; + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[i]; + + if (pSoldier && pSoldier->bActive + && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) + ) + { + mercs.push_back(pSoldier); + } + } + + const MERCPROFILESTRUCT merc = gMercProfiles[mercs[agentIndex[index]]->ubProfile]; + CHAR16 text[400]; + RebelCommandAgentMissionsText missionTitle; + INT8 missionSuccessChance; + UINT8 missionDuration; + UINT32 durationBonus; + FLOAT floatModifier; + INT16 intModifier; + int durSkill; + int floatSkill; + int intSkill; + UINT16 extraBits; + + MissionHelpers::GetMissionInfo(static_cast(rebelCommandSaveInfo.availableMissions[index]), &merc, durationBonus, floatModifier, intModifier, durSkill, floatSkill, intSkill, extraBits); + switch (rebelCommandSaveInfo.availableMissions[index]) + { + case RCAM_DEEP_DEPLOYMENT: + { + missionTitle = RCAMT_DEEP_DEPLOYMENT_TITLE; + missionSuccessChance = gRebelCommandSettings.iDeepDeploymentSuccessChance; + missionDuration = gRebelCommandSettings.iDeepDeploymentDuration; + } + break; + + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: + { + missionTitle = RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE; + missionSuccessChance = gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance; + missionDuration = gRebelCommandSettings.iGetEnemyMovementTargetsDuration; + } + break; + + case RCAM_IMPROVE_LOCAL_SHOPS: + { + missionTitle = RCAMT_IMPROVE_LOCAL_SHOPS_TITLE; + missionSuccessChance = gRebelCommandSettings.iImproveLocalShopsSuccessChance; + missionDuration = gRebelCommandSettings.iImproveLocalShopsDuration; + } + break; + + case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: + { + missionTitle = RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_TITLE; + missionSuccessChance = gRebelCommandSettings.iReduceStrategicDecisionSpeedSuccessChance; + missionDuration = gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration; + } + break; + + case RCAM_REDUCE_UNALERTED_ENEMY_VISION: + { + missionTitle = RCAMT_REDUCE_UNALERTED_ENEMY_VISION_TITLE; + missionSuccessChance = gRebelCommandSettings.iReduceUnalertedEnemyVisionSuccessChance; + missionDuration = gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration; + } + break; + + case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: + { + missionTitle = RCAMT_SABOTAGE_INFANTRY_EQUIPMENT_TITLE; + missionSuccessChance = gRebelCommandSettings.iSabotageInfantryEquipmentSuccessChance; + missionDuration = gRebelCommandSettings.iSabotageInfantryEquipmentDuration; + } + break; + + case RCAM_SABOTAGE_MECHANICAL_UNITS: + { + missionTitle = RCAMT_SABOTAGE_MECHANICAL_UNITS_TITLE; + missionSuccessChance = gRebelCommandSettings.iSabotageMechanicalUnitsSuccessChance; + missionDuration = gRebelCommandSettings.iSabotageMechanicalUnitsDuration; + } + break; + + case RCAM_TRAIN_MILITIA_ANYWHERE: + { + missionTitle = RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE; + missionSuccessChance = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; + missionDuration = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; + } + break; + + default: break; + } + + missionSuccessChance += GetMissionSuccessChanceBonus(&merc); + + if (Random(100) > missionSuccessChance) + { + // mission failed! + missionDuration = 0; + } + else + { + missionDuration += durationBonus; + } + + swprintf(text, L"[%s (%d supplies)]", szRebelCommandAgentMissionsText[missionTitle], cost); + + if (agentIndex[index] == mercs.size()) + { + // sent a generic rebel + MissionHelpers::missionParam = SerialiseMissionFirstEvent(TRUE, 0 /* no profile needed */, static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, 0 /* no extra data */); + swprintf(text, L"%s Send a rebel agent to prepare this mission?", text); + } + else + { + MissionHelpers::missionParam = SerialiseMissionFirstEvent(FALSE, agentIndex[index], static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, static_cast(extraBits)); + if (merc.bSex == MALE) + swprintf(text, L"%s Send %s to prepare this mission? He will return in 24 hours.", text, merc.zNickname); + else + swprintf(text, L"%s Send %s to prepare this mission? She will return in 24 hours.", text, merc.zNickname); + } + + DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, text, LAPTOP_SCREEN, MSG_BOX_FLAG_YESNO, [](UINT8 exitValue) { + if (exitValue == MSG_BOX_RETURN_YES) + { + MissionFirstEvent evt; + DeserialiseMissionFirstEvent(MissionHelpers::missionParam, evt); + + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[i]; + + if (pSoldier->ubProfile != evt.mercProfileId) + continue; + + // rftr todo: send selected merc on assignment, like mini event adventure + for (INT8 i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + if (evt.missionId == rebelCommandSaveInfo.availableMissions[i]) + { + rebelCommandSaveInfo.availableMissions[i] = RCAM_NONE; + break; + } + } + + // actually start the mission + AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, MissionHelpers::missionParam); + missionMap[static_cast(evt.missionId)] = MissionHelpers::missionParam; + + return; + } + } + }); +} // end website void ApplyEnemyPenalties(SOLDIERTYPE* pSoldier) @@ -1560,7 +2712,7 @@ void ApplyEnemyPenalties(SOLDIERTYPE* pSoldier) continue; // and that it's not level 0 - const UINT8 level = rebelCommandSaveInfo.regions[a].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[a].GetLevel(index); if (level == 0) continue; @@ -1572,7 +2724,7 @@ void ApplyEnemyPenalties(SOLDIERTYPE* pSoldier) sectors.push_back(std::tuple(x, y, GetRegionLoyalty(a))); // check if soldier is within range of the city - for (const auto tuple : sectors) + for (const auto& tuple : sectors) { const INT16 x = std::get<0>(tuple); const INT16 y = std::get<1>(tuple); @@ -1639,7 +2791,7 @@ FLOAT GetAssignmentBonus(INT16 x, INT16 y) if (index >= 0) { - const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[townId].GetLevel(index); value += info.adminActions[RCAA_MERC_SUPPORT].fValue1 * level; } @@ -1659,7 +2811,7 @@ INT32 GetMiningPolicyBonus(INT16 townId) if (index >= 0) { - const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[townId].GetLevel(index); return static_cast(info.adminActions[RCAA_MINING_POLICY].fValue1 * level); } @@ -1738,7 +2890,7 @@ void GetBonusMilitia(INT16 sx, INT16 sy, UINT8& green, UINT8& regular, UINT8& el continue; // and that it's not level 0 - const UINT8 level = rebelCommandSaveInfo.regions[a].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[a].GetLevel(index); if (level == 0) continue; @@ -1750,7 +2902,7 @@ void GetBonusMilitia(INT16 sx, INT16 sy, UINT8& green, UINT8& regular, UINT8& el sectors.push_back(std::tuple(x, y, GetRegionLoyalty(a))); // check if sector is within range of the city - for (const auto tuple : sectors) + for (const auto& tuple : sectors) { const INT16 x = std::get<0>(tuple); const INT16 y = std::get<1>(tuple); @@ -1801,7 +2953,7 @@ INT16 GetFortificationsBonus(UINT8 sector) return 0; // no levels in region - const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[townId].GetLevel(index); if (level == 0) return 0; @@ -1838,7 +2990,7 @@ FLOAT GetHarriersSpeedPenalty(UINT8 sector) continue; // no levels in region - const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[townId].GetLevel(index); if (level == 0) continue; @@ -1848,7 +3000,7 @@ FLOAT GetHarriersSpeedPenalty(UINT8 sector) // run through townSectors to find the biggest harriers penalty BOOLEAN found = FALSE; - for (const auto trio : townSectors) + for (const auto& trio : townSectors) { const INT16 sx = std::get<0>(trio); const INT16 sy = std::get<1>(trio); @@ -1940,7 +3092,7 @@ void HandleScouting() continue; // no levels in region - const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[townId].GetLevel(index); if (level == 0) continue; @@ -1954,7 +3106,7 @@ void HandleScouting() { for (int y = MINIMUM_VALID_Y_COORDINATE; y <= MAXIMUM_VALID_Y_COORDINATE; ++y) { - for (const auto trio : townSectors) + for (const auto& trio : townSectors) { const INT16 sx = std::get<0>(trio); const INT16 sy = std::get<1>(trio); @@ -2004,7 +3156,7 @@ FLOAT GetPathfindersSpeedBonus(UINT8 sector) continue; // no levels in region - const UINT8 level = rebelCommandSaveInfo.regions[townId].actionLevels[index]; + const UINT8 level = rebelCommandSaveInfo.regions[townId].GetLevel(index); if (level == 0) continue; @@ -2014,7 +3166,7 @@ FLOAT GetPathfindersSpeedBonus(UINT8 sector) // run through townSectors to find the biggest pathfinders bonus BOOLEAN found = FALSE; - for (const auto trio : townSectors) + for (const auto& trio : townSectors) { const INT16 sx = std::get<0>(trio); const INT16 sy = std::get<1>(trio); @@ -2068,7 +3220,9 @@ void RaidMines(INT32 &playerIncome, INT32 &enemyIncome) INT32 stolenIncome = static_cast(enemyIncome * rebelCommandSaveInfo.directives[RCD_RAID_MINES].GetValue1() * Random(100) / 100.f); playerIncome += stolenIncome; - enemyIncome -= stolenIncome; + enemyIncome -= stolenIncome*2; + + if (enemyIncome < 0) enemyIncome = 0; if (stolenIncome > 0) { @@ -2265,15 +3419,20 @@ void DailyUpdate() rebelCommandSaveInfo.iActiveDirective = directive; // increment supplies - const UINT8 progress = CurrentPlayerProgressPercentage(); - iIncomingSuppliesPerDay = static_cast(progress * gRebelCommandSettings.fIncomeModifier + (directive == RCD_GATHER_SUPPLIES ? rebelCommandSaveInfo.directives[RCD_GATHER_SUPPLIES].GetValue1() : 0)); + iIncomingSuppliesPerDay = CalcIncomingSuppliesPerDay(static_cast(directive)); rebelCommandSaveInfo.iSupplies += iIncomingSuppliesPerDay; + // rftr todo: check bitmask + //if (purchasing supplies through agent mission) + // what gets subtracted? current balance? daily income? how do we pick? + // get regional bonuses + const INT32 supplyUpkeep = static_cast(gRebelCommandSettings.fIncomeModifier + 0.5f); INT16 intelGain = 0; INT16 supplyGain = 0; INT16 moneyGain = 0; - for (int a = FIRST_TOWN; a < NUM_TOWNS; ++a) + CHAR16 text[200]; + for (int a = FIRST_TOWN+1; a < NUM_TOWNS; ++a) { // check to see if the town is lost if (IsTownUnderCompleteControlByEnemy(a) && rebelCommandSaveInfo.regions[a].adminStatus == RAS_ACTIVE) @@ -2302,27 +3461,51 @@ void DailyUpdate() const UINT8 loyalty = GetRegionLoyalty(a); for (int b = 0; b < REBEL_COMMAND_MAX_ACTIONS_PER_REGION; ++b) { - const INT8 level = rebelCommandSaveInfo.regions[a].actionLevels[b]; + const INT8 level = rebelCommandSaveInfo.regions[a].GetLevel(b); + if (level == 0) continue; + + if (CanAdminActionBeToggled(rebelCommandSaveInfo.regions[a].actions[b]) && !rebelCommandSaveInfo.regions[a].IsActive(b)) continue; + switch (static_cast(rebelCommandSaveInfo.regions[a].actions[b])) { case RCAA_SUPPLY_LINE: - case RCAA_SAFEHOUSES: case RCAA_SUPPLY_DISRUPTION: case RCAA_SCOUTS: case RCAA_MERC_SUPPORT: - case RCAA_MINING_POLICY: case RCAA_PATHFINDERS: - case RCAA_HARRIERS: case RCAA_FORTIFICATIONS: // no daily bonuses break; + case RCAA_HARRIERS: + case RCAA_MINING_POLICY: + case RCAA_SAFEHOUSES: + // no daily bonuses, but gotta pay upkeep + if (rebelCommandSaveInfo.iSupplies > supplyUpkeep) + { + // what to do on success? + } + else + { + swprintf(text, L"Not enough supplies for harriers/miningpolicy/safehouses!"); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); + } + break; + case RCAA_REBEL_RADIO: IncrementTownLoyalty(a, static_cast(info.adminActions[RCAA_REBEL_RADIO].fValue1 * level)); break; case RCAA_DEAD_DROPS: - intelGain += Random(static_cast(info.adminActions[RCAA_DEAD_DROPS].fValue1 * level * loyalty / 100.f)); + if (rebelCommandSaveInfo.iSupplies > supplyUpkeep) + { + intelGain += Random(static_cast(info.adminActions[RCAA_DEAD_DROPS].fValue1 * level * loyalty / 100.f)); + } + else + { + swprintf(text, L"Not enough supplies for dead drops"); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); + } break; case RCAA_SMUGGLERS: @@ -2330,10 +3513,18 @@ void DailyUpdate() break; case RCAA_WAREHOUSES: - AddResources( - static_cast(info.adminActions[RCAA_WAREHOUSES].fValue1 * level * Random(100) * loyalty / 10000.f), - static_cast(info.adminActions[RCAA_WAREHOUSES].fValue2 * level * Random(100) * loyalty / 10000.f), - static_cast(info.adminActions[RCAA_WAREHOUSES].fValue3 * level * Random(100) * loyalty / 10000.f)); + if (rebelCommandSaveInfo.iSupplies > supplyUpkeep) + { + AddResources( + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue1 * level * Random(100) * loyalty / 10000.f), + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue2 * level * Random(100) * loyalty / 10000.f), + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue3 * level * Random(100) * loyalty / 10000.f)); + } + else + { + swprintf(text, L"Not enough supplies for warehouses"); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); + } break; case RCAA_TAXES: @@ -2353,7 +3544,6 @@ void DailyUpdate() } } - CHAR16 text[200]; if (intelGain > 0) { swprintf(text, szRebelCommandText[RCT_DEAD_DROP_INCOME], intelGain); @@ -2374,6 +3564,46 @@ void DailyUpdate() { AddTransactionToPlayersBook(REBEL_COMMAND, 0, GetWorldTotalMin(), moneyGain); } + + // update missions + // rftr todo: test me + // rftr todo: don't do this every day! + std::unordered_set validMissions; + for (int i = 0; i < RCAM_NUM_MISSIONS; ++i) + { + validMissions.insert(static_cast(i)); + } + + for (const auto& pair : missionMap) + { + const RebelCommandAgentMissions mission = pair.first; + validMissions.erase(mission); + } + + if (validMissions.size() >= NUM_ARC_AGENT_SLOTS) + { + for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + const INT8 mission = static_cast(Random(validMissions.size())); + rebelCommandSaveInfo.availableMissions[i] = mission; + validMissions.erase(static_cast(mission)); + } + } + else + { + int idx = 0; + for (auto iter = validMissions.cbegin(); iter != validMissions.cend(); ++iter) + { + rebelCommandSaveInfo.availableMissions[idx] = *iter; + idx++; + } + + while (idx < NUM_ARC_AGENT_SLOTS) + { + rebelCommandSaveInfo.availableMissions[idx] = RCAM_NONE; + idx++; + } + } } void HourlyUpdate() @@ -2510,6 +3740,42 @@ BOOLEAN Load(HWFILE file) Init(); } + // rftr TEST it works hooray, assuming I don't change the layout of the bitflag + //const UINT32 param1 = SerialiseMissionFirstEvent(FALSE, 8, RCAM_DEEP_DEPLOYMENT, 200, 0x0F); + //const UINT32 param2 = SerialiseMissionSecondEvent(FALSE, 10, RCAM_GET_ENEMY_MOVEMENT_TARGETS, 0xFF); + //MissionFirstEvent evt1; + //MissionSecondEvent evt2; + //DeserialiseMissionFirstEvent(param1, evt1); + //DeserialiseMissionSecondEvent(param2, evt2); + + // go through every strategic event to find active agent missions + std::vector> missions = GetAllStrategicEventsOfType(EVENT_REBELCOMMAND); + missionMap.clear(); + // example is EVENT_BLOODCAT_ATTACK + for (std::vector>::iterator it = missions.begin(); it != missions.end(); ++it) + { + // FIRST EVENT EXAMPLE + //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, my32bitparam); + // SECOND EVENT EXAMPLE + //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * durationInHours, my32bitparam); + //const UINT32 first = it->first; // timestamp - when this event will be fired + //const UINT32 second = it->second; // uiParam + + MissionFirstEvent evt1; + DeserialiseMissionFirstEvent(it->second, evt1); + if (evt1.isFirstEvent) + { + missionMap[static_cast(evt1.missionId)] = it->second; + } + + MissionSecondEvent evt2; + DeserialiseMissionSecondEvent(it->second, evt2); + + if (evt2.isSecondEvent) + { + missionMap[static_cast(evt2.missionId)] = it->second; + } + } return TRUE; } @@ -2667,6 +3933,87 @@ void SetupInfo() aa.fValue3 = 0.f; info.adminActions.insert(info.adminActions.begin() + RCAA_FORTIFICATIONS, aa); + MissionHelpers::missionInfo.clear(); + // example format + // { + // { new skill traits to check }, + // { old skill traits to check. use -1 to not match against anything }, + // { duration bonus for checked trait }, + // { float modifier for checked trait. either this line or the next is zeroed out. }, + // { int modifier for checked trait. either this line or the previous is zeroed out. }, + // { value to place in extra bits, used to determine what bonus is applied. } + // } + //RCAM_DEEP_DEPLOYMENT + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, SCOUTING_NT, STEALTHY_NT, SURVIVAL_NT}, + {-1, -1, STEALTHY_OT, CAMOUFLAGED_OT}, + {gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Covert, gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Scouting, gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Stealthy, gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Survival}, + {0.f, 0.f, 0.f, 0.f}, + {gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Covert, gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Scouting, gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Stealthy, gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Survival}, + {MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_COVERT, MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SCOUTING, MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_STEALTHY, MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SURVIVAL} + }); + //RCAM_GET_ENEMY_MOVEMENT_TARGETS + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, RADIO_OPERATOR_NT}, + {-1, -1}, + {gRebelCommandSettings.iGetEnemyMovementTargetsDuration_Bonus_Covert, gRebelCommandSettings.iGetEnemyMovementTargetsDuration_Bonus_Radio}, + {0.f, 0.f}, + {0, 0}, + {0, 0} + }); + //RCAM_IMPROVE_LOCAL_SHOPS + MissionHelpers::missionInfo.push_back({ }); // no entries necessary - no modifiers + //RCAM_REDUCE_STRATEGIC_DECISION_SPEED + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, SQUADLEADER_NT, SNITCH_NT}, + {-1, -1, -1}, + {gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration_Bonus_Covert, gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration_Bonus_Deputy, gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration_Bonus_Snitch}, + {gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Covert, gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Deputy, gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Snitch}, + {0, 0, 0}, + {MissionHelpers::REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_COVERT, MissionHelpers::REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_DEPUTY, MissionHelpers::REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_SNITCH} + }); + //RCAM_REDUCE_UNALERTED_ENEMY_VISION + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, RADIO_OPERATOR_NT, STEALTHY_NT}, + {-1, -1, STEALTHY_OT}, + {gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration_Bonus_Covert, gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration_Bonus_Radio, 0}, + {gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Covert, gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Radio, gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Stealthy}, + {0, 0, 0}, + {MissionHelpers::REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_COVERT, MissionHelpers::REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_RADIO, MissionHelpers::REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_STEALTHY} + }); + //RCAM_SABOTAGE_INFANTRY_EQUIPMENT + MissionHelpers::missionInfo.push_back({ + {AUTO_WEAPONS_NT, COVERT_NT, DEMOLITIONS_NT, GUNSLINGER_NT, RANGER_NT, SNIPER_NT }, + {AUTO_WEAPS_OT, -1, -1, -1, -1, PROF_SNIPER_OT }, + {gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Auto_Weapons, gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Covert, gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Demolitions, gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Gunslinger, gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Ranger, gRebelCommandSettings.iSabotageInfantryEquipmentDuration_Bonus_Sniper}, + {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Auto_Weapons, gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Covert, gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Demolitions, gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Gunslinger, gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Ranger, gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Sniper}, + {MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_AUTO_WEAPONS, MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_COVERT, MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_DEMOLITIONS, MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_GUNSLINGER, MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_RANGER, MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_SNIPER} + }); + //RCAM_SABOTAGE_MECHANICAL_UNITS + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, DEMOLITIONS_NT, HEAVY_WEAPONS_NT}, + {-1, -1, HEAVY_WEAPS_OT}, + {gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Covert, gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Demolitions, gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Heavy_Weapons}, + {0.f, 0.f, 0.f}, + {gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Covert, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Demolitions, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Heavy_Weapons}, + {MissionHelpers::SABOTAGE_MECHANICAL_UNITS_COVERT, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_DEMOLITIONS, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_HEAVY_WEAPONS} + }); + //RCAM_TRAIN_MILITIA_ANYWHERE + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, SURVIVAL_NT, TEACHING_NT}, + {-1, CAMOUFLAGED_OT, TEACHING_OT}, + {gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Covert, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Survival, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Teaching}, + {0.f, 0.f, 0.f}, + {gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching}, + {0, 0, MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING} + }); } void UpgradeMilitiaStats() @@ -2692,6 +4039,313 @@ void UpgradeMilitiaStats() }); } +void ApplyEnemyMechanicalUnitPenalties(SOLDIERTYPE* pSoldier) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + // rftr todo: check agent mission bitmask + + pSoldier->stats.bLife -= 40; + pSoldier->stats.bLifeMax = pSoldier->stats.bLife; + pSoldier->stats.bAgility -= 40; + pSoldier->stats.bDexterity -= 40; + pSoldier->stats.bStrength -= 40; + pSoldier->stats.bMarksmanship -= 40; + + pSoldier->stats.bLife = max(33, pSoldier->stats.bLife); + pSoldier->stats.bLifeMax = max(33, pSoldier->stats.bLifeMax); + pSoldier->stats.bAgility = max(33, pSoldier->stats.bAgility); + pSoldier->stats.bDexterity = max(33, pSoldier->stats.bDexterity); + pSoldier->stats.bStrength = max(33, pSoldier->stats.bStrength); + pSoldier->stats.bMarksmanship = max(33, pSoldier->stats.bMarksmanship); +} + +void ApplyMilitiaTraits(SOLDIERTYPE* pSoldier) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + // rftr todo: check bitmask for specific possible traits +} + +void ApplyVisionModifier(const SOLDIERTYPE* pSoldier, INT32& sight) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + // rftr todo: check bitmask + + if (pSoldier->bTeam == ENEMY_TEAM && pSoldier->aiData.bAlertStatus == STATUS_GREEN) + { + sight = static_cast(sight * (1.f - 0.15f)); + } +} + +BOOLEAN CanAssignTraitsToMilitia() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return FALSE; + + // rftr todo: check bitmask + + return TRUE; +} + +BOOLEAN CanTrainMilitiaAnywhere() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return FALSE; + + // rftr todo: check bitmask + return TRUE; +} + +UINT8 GetMaxTrainersForTrainMilitiaAnywhere() +{ + return 1; +} + +INT16 GetAdditionalDeployRange(const UINT8 insertionCode) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return 0; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_DEEP_DEPLOYMENT); + + if (iter == missionMap.end()) + return 0; + + // rftr todo: check bitmask + + switch (insertionCode) + { + case INSERTION_CODE_NORTH: + case INSERTION_CODE_SOUTH: + { + INT16 range = 0; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + // we only get a range bonus if the mission is active! + if (evt.isSecondEvent) + { + range = gRebelCommandSettings.iDeepDeploymentRangeNS; + + // rftr todo: bitmagic to get bonus range + switch (evt.extraBits) + { + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_COVERT: range += gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Covert; break; + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SCOUTING: range += gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Scouting; break; + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_STEALTHY: range += gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Stealthy; break; + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SURVIVAL: range += gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Survival; break; + + default: break; + } + } + + return range; + } + + case INSERTION_CODE_WEST: + case INSERTION_CODE_EAST: + { + INT16 range = 0; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + // we only get a range bonus if the mission is active! + if (evt.isSecondEvent) + { + range = gRebelCommandSettings.iDeepDeploymentRangeEW; + + switch (evt.extraBits) + { + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_COVERT: range += gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Covert; break; + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SCOUTING: range += gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Scouting; break; + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_STEALTHY: range += gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Stealthy; break; + case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SURVIVAL: range += gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Survival; break; + + default: break; + } + } + + return range; + } + } + + return 0; +} + +INT8 GetEnemyEquipmentCoolnessModifier() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return 0; + + // rftr todo: check bitmask + + return -1; +} + +INT8 GetEnemyEquipmentStatusModifier(const INT8 initialStatus) +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return initialStatus; + + // rftr todo: check bitmask + + INT8 newStatus = initialStatus; + newStatus -= 10; + + newStatus = max(1, min(newStatus, 100)); + return newStatus; +} + +UINT8 GetMerchantCoolnessBonus() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return 0; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_IMPROVE_LOCAL_SHOPS); + + if (iter == missionMap.end()) + return 0; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + // rftr todo: check bitmask + + return evt.isSecondEvent ? 1 : 0; +} + +FLOAT GetStrategicDecisionSpeedModifier() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return 1.f; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_REDUCE_STRATEGIC_DECISION_SPEED); + + if (iter == missionMap.end()) + return 0; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + // rftr todo: check bitmask + + FLOAT modifier = 1.f; + + if (evt.isSecondEvent) + { + switch (evt.extraBits) + { + case MissionHelpers::REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_COVERT: modifier = gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Covert; break; + default: modifier = gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier; break; + } + } + + return modifier; +} + +void HandleStrategicEvent(const UINT32 eventParam) +{ + // this handles the transition from "mission prep" (first event) to "mission active" (second event), which happens 24 hours after the player clicks on "start mission" + // rftr todo: update agent mission bitmask + MissionFirstEvent evt1; + MissionSecondEvent evt2; + DeserialiseMissionFirstEvent(eventParam, evt1); + DeserialiseMissionSecondEvent(eventParam, evt2); + + if (evt1.isFirstEvent) + { + // mission prep is over. see if we can activate the mission + missionMap.erase(static_cast(evt1.missionId)); + + // rftr todo: end the merc's assignment (like mini event adventures) + + if (evt1.isMissionSuccess) + { + const RebelCommandAgentMissions mission = static_cast(evt1.missionId); + const MERCPROFILESTRUCT merc = gMercProfiles[evt1.mercProfileId]; + + // rftr todo: mission successful! give some experience pts + + // what mission did we do? apply bonuses here, and don't forget to check them later when checking to see if a mission bonus should be applied + UINT32 durationBonus = 0; + int durationBonusSkill = 0; + INT16 intModifier = 0; + int intModifierSkill = 0; + FLOAT floatModifier = 0.f; + int floatModifierSkill = 0; + UINT16 extraBits = 0; + MissionHelpers::GetMissionInfo(mission, &merc, durationBonus, floatModifier, intModifier, durationBonusSkill, floatModifierSkill, intModifierSkill, extraBits); + + BOOLEAN validMission = FALSE; + switch (mission) + { + case RCAM_DEEP_DEPLOYMENT: + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: + case RCAM_IMPROVE_LOCAL_SHOPS: + case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: + case RCAM_REDUCE_UNALERTED_ENEMY_VISION: + case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: + case RCAM_SABOTAGE_MECHANICAL_UNITS: + case RCAM_TRAIN_MILITIA_ANYWHERE: + { + validMission = TRUE; + } + break; + + default: + { + ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, L"Unrecognised mission ID: %d", mission); + } + break; + } + + if (validMission) + { + AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, + SerialiseMissionSecondEvent(evt1.sentGenericRebelAgent, evt1.mercProfileId, mission, extraBits)); + + // rftr todo: tell the player that the mission has started. popupbox or screenmsg? + } + + missionMap[mission] = eventParam; + } + else + { + // rftr todo: tell the player that the mission prep failed. some popup box blurb or somesuch. + } + } + else if (evt2.isSecondEvent) + { + // mission duration is over. deactivate the mission + missionMap.erase(static_cast(evt2.missionId)); + } +} + +BOOLEAN ShowEnemyMovementTargets() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return FALSE; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_GET_ENEMY_MOVEMENT_TARGETS); + + if (iter == missionMap.end()) + return FALSE; + + // rftr todo: check bitmask + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + return evt.isSecondEvent; +} + void DEBUG_DAY() { DailyUpdate(); @@ -2716,7 +4370,7 @@ template<> void DropDownTemplate::SetRefresh() using namespace RebelCommand; const INT16 newDirective = REBEL_COMMAND_DROPDOWN.GetSelectedEntryKey(); rebelCommandSaveInfo.iSelectedDirective = newDirective; - iIncomingSuppliesPerDay = static_cast(CurrentPlayerProgressPercentage() * gRebelCommandSettings.fIncomeModifier + (newDirective == RCD_GATHER_SUPPLIES ? rebelCommandSaveInfo.directives[RCD_GATHER_SUPPLIES].GetValue1() : 0)); + iIncomingSuppliesPerDay = CalcIncomingSuppliesPerDay(static_cast(newDirective)); redraw = TRUE; } diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index 8b4e24f6b..f3b56d953 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -6,9 +6,43 @@ #include "Types.h" #define REBEL_COMMAND_MAX_ACTIONS_PER_REGION 6 +#define NUM_ARC_AGENT_SLOTS 2 namespace RebelCommand { + // applies to RegionSaveInfo.actionLevels: use the MSB as the active flag since I don't expect it to be used otherwise + constexpr UINT8 ADMIN_ACTION_ACTIVE_BIT = 1 << 7; + + // for rebelCommandSaveInfo.uBitMask + // requirement breakdown + // 1 bit for notification toggle + // 5 * 4 bits for random mission selection (2off, 2def) = 32 choices each + // need some bits to track mission area (friendly/hostile? num towns?) + // remaining bits to track up/downgrades? + // some should be ASD specific? + // can we not do this and just check strategic events? GetAllStrategicEventsOfType(). could be costly. iterates over event LL on each call + // can we cache in-flight events on load? no real need to save this, right? + //constexpr UINT64 AGENT_NOTIFICATION_BIT = 1 << 0; + + // the FIRST and SECOND strategic events share the same type (EVENT_REBELCOMMAND - no need to have multiple types yet, I think...) + // so the 32-bit int will have to block out information for both events + // FIRST EVENT BREAKDOWN + // A######B CCCCCCCC DDDDDDDD EEEEEEEE + // A (1 bit) - always 0 to indicate that this is the FIRST event (ie, keeping a merc busy for a set duration) + // B (1 bit) - 0 if the player sent a generic rebel agent, 1 if the player sent one of their own mercs + // C (8 bit) - the profile number of the merc that was sent. invalid if B == 0 + // D (8 bit) - the mission ID. should match up with RebelCommandAgentMissions enum + // E (8 bit) - the mission duration, in hours. if 0, mission failed. + // the rest of the bits depend on the mission? + // + + // SECOND EVENT BREAKDOWN + // A####### #######B CCCCCCCC DDDDDDDD + // A (1 bit) - always 1 to indicate that this is the SECOND event (ie, this event fires when the mission bonus expires) + // B (1 bit) - 0 if the player sent a generic rebel agent, 1 if the player sent one of their own mercs + // C (8 bit) - the profile number of the merc that was sent. invalid if B == 0 + // D (8 bit) - the mission ID. should match up with RebelCommandAgentMissions enum + // extra bits are for ??????????? enum RebelCommandDirectives { @@ -49,6 +83,36 @@ enum RebelCommandAdminActions RCAA_NUM_ACTIONS }; +enum RebelCommandAgentMissions +{ + RCAM_NONE = -1, + RCAM_DEEP_DEPLOYMENT = 0, + RCAM_GET_ENEMY_MOVEMENT_TARGETS, // aka Strategic Intel + RCAM_IMPROVE_LOCAL_SHOPS, + RCAM_REDUCE_STRATEGIC_DECISION_SPEED, // aka Slower Strategic Decisions + RCAM_REDUCE_UNALERTED_ENEMY_VISION, // aka Lower Readiness + RCAM_SABOTAGE_INFANTRY_EQUIPMENT, // aka Sabotage Equipment + RCAM_SABOTAGE_MECHANICAL_UNITS, // aka Sabotage Vehicles + RCAM_TRAIN_MILITIA_ANYWHERE, + + RCAM_NUM_MISSIONS, + + // ideas/unimplemented - rename some? + // need to have permanent and temporary boons + RCAM_SEND_SUPPLIES_TO_TOWN, + RCAM_BOOST_TOWN_ADMIN_ACTIONS, + RCAM_PROCURE_ITEMS, + RCAM_MILITIA_SKILL_TRAITS, // should override militia skill traits ini option - split into multiple (weapon spec, bodybuilding, athletic, night ops) + RCAM_OBSERVE_SECTORS, // ??? competes with scouts? + RCAM_PURCHASE_SUPPLIES, // increase daily supply income, decrease daily $ income + RCAM_SABOTAGE_ASD, // see ASD.cpp for things that can be played with + RCAM_SABOTAGE_MINE, + RCAM_REDUCE_ENEMY_POOL, // need to make sure enemy pool is not infinite // giReinforcementPool, also gfUnlimitedTroops = zDiffSetting[gGameOptions.ubDifficultyLevel].bUnlimitedPoolOfTroops; + // militia/mercs get bonus vision (???) + // share vision with civilians? + +}; + enum RegionAdminStatus { RAS_NONE, @@ -97,8 +161,13 @@ typedef struct RegionSaveInfo UINT8 actionLevels[REBEL_COMMAND_MAX_ACTIONS_PER_REGION]; UINT8 ubMaxLoyalty; + BOOLEAN IsActive(UINT8 index) { return (actionLevels[index] & ADMIN_ACTION_ACTIVE_BIT) == 0; } + // rftr: I know these fly in the face of convention, but I'm lazy and this preserves savegame compatibility without needing to add any additional code + void SetActive(UINT8 index) { actionLevels[index] &= ~ADMIN_ACTION_ACTIVE_BIT; } // active bit value = 0 + void SetInactive(UINT8 index) { actionLevels[index] |= ADMIN_ACTION_ACTIVE_BIT; } // inactive bit value = 1 INT32 GetAdminDeployCost(INT16 numAdminTeams) { return 10 * numAdminTeams * numAdminTeams; }; INT32 GetAdminReactivateCost(INT16 numAdminTeams) { return GetAdminDeployCost(numAdminTeams) / 4; }; + UINT8 GetLevel(INT16 index) { return actionLevels[index] & ~ADMIN_ACTION_ACTIVE_BIT; } } RegionSaveInfo; typedef struct SaveInfo @@ -110,9 +179,10 @@ typedef struct SaveInfo INT32 iActiveDirective; INT32 iSelectedDirective; INT8 iMilitiaStatsLevel; - UINT8 uSupplyDropCount; + UINT8 uSupplyDropCount; // keeping this around for compatibility with old saves + INT8 availableMissions[NUM_ARC_AGENT_SLOTS]; - INT8 filler[19]; + INT8 filler[17]; } SaveInfo; extern SaveInfo rebelCommandSaveInfo; @@ -122,6 +192,7 @@ void ExitWebsite(); void RenderWebsite(); void HandleWebsite(); +// admin actions void ApplyEnemyPenalties(SOLDIERTYPE* pSoldier); void ApplyMilitiaBonuses(SOLDIERTYPE* pMilitia); UINT8 GetApproximateEnemyLocationResolutionIndex(); @@ -139,17 +210,30 @@ FLOAT GetPathfindersSpeedBonus(UINT8 sector); BOOLEAN NeutraliseRole(const SOLDIERTYPE* pSoldier); void RaidMines(INT32 &playerIncome, INT32 &enemyIncome); BOOLEAN ShowApproximateEnemyLocations(); -void ShowWebsiteAvailableMessage(); + +// agent missions +void ApplyEnemyMechanicalUnitPenalties(SOLDIERTYPE* pSoldier); +void ApplyMilitiaTraits(SOLDIERTYPE* pSoldier); +void ApplyVisionModifier(const SOLDIERTYPE* pSoldier, INT32& sight); +BOOLEAN CanAssignTraitsToMilitia(); +BOOLEAN CanTrainMilitiaAnywhere(); +UINT8 GetMaxTrainersForTrainMilitiaAnywhere(); +INT16 GetAdditionalDeployRange(const UINT8 insertionCode); +INT8 GetEnemyEquipmentCoolnessModifier(); +INT8 GetEnemyEquipmentStatusModifier(const INT8 initialStatus); +UINT8 GetMerchantCoolnessBonus(); +FLOAT GetStrategicDecisionSpeedModifier(); +void HandleStrategicEvent(const UINT32 eventParam); +BOOLEAN ShowEnemyMovementTargets(); void DailyUpdate(); void HourlyUpdate(); void Init(); +void ShowWebsiteAvailableMessage(); BOOLEAN Load(HWFILE file); BOOLEAN Save(HWFILE file); } -//BOOLEAN LoadRebelCommand( HWFILE file ) { return RebelCommand::Load( file ); } - #endif diff --git a/Strategic/Strategic AI.cpp b/Strategic/Strategic AI.cpp index 96e0ab4ef..573493b77 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -36,6 +36,7 @@ #include "Map Information.h" #include "interface dialogue.h" #include "ASD.h" // added by Flugente + #include "Rebel Command.h" #endif #include "GameInitOptionsScreen.h" @@ -1198,6 +1199,8 @@ void InitStrategicAI() dEnemyGeneralsSpeedupFactor = max( 0.5f, dEnemyGeneralsSpeedupFactor - gStrategicStatus.usVIPsLeft * gGameExternalOptions.fEnemyGeneralStrategicDecisionSpeedBonus ); } + dEnemyGeneralsSpeedupFactor *= RebelCommand::GetStrategicDecisionSpeedModifier(); + giReinforcementPool = zDiffSetting[gGameOptions.ubDifficultyLevel].iQueensInitialPoolOfTroops; giForcePercentage = zDiffSetting[gGameOptions.ubDifficultyLevel].iInitialGarrisonPercentages; giArmyAlertness = zDiffSetting[gGameOptions.ubDifficultyLevel].iEnemyStartingAlertLevel; @@ -3456,6 +3459,8 @@ void EvaluateQueenSituation() { dEnemyGeneralsSpeedupFactor = max( 0.5f, dEnemyGeneralsSpeedupFactor - gStrategicStatus.usVIPsLeft * gGameExternalOptions.fEnemyGeneralStrategicDecisionSpeedBonus ); } + + dEnemyGeneralsSpeedupFactor *= RebelCommand::GetStrategicDecisionSpeedModifier(); uiOffset += dEnemyGeneralsSpeedupFactor * (zDiffSetting[gGameOptions.ubDifficultyLevel].iBaseDelayInMinutesBetweenEvaluations + Random( zDiffSetting[gGameOptions.ubDifficultyLevel].iEvaluationDelayVariance )); diff --git a/Strategic/Town Militia.cpp b/Strategic/Town Militia.cpp index 5ec21b592..9a3e3ed92 100644 --- a/Strategic/Town Militia.cpp +++ b/Strategic/Town Militia.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #include "builddefines.h" #ifdef PRECOMPILEDHEADERS @@ -279,7 +280,7 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa if( ubTownId == BLANK_SECTOR ) { - Assert( IsThisSectorASAMSector( sMapX, sMapY, 0 ) ); + Assert( IsThisSectorASAMSector( sMapX, sMapY, 0 ) || RebelCommand::CanTrainMilitiaAnywhere() ); } // force tactical to update militia status @@ -1293,7 +1294,7 @@ BOOLEAN IsSAMSiteFullOfMilitia( INT16 sSectorX, INT16 sSectorY, INT8 iMilitiaTyp INT32 iMaxMilitiaPerSector = gGameExternalOptions.iMaxMilitiaPerSector; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia5"); // check if SAM site is ours? - fSamSitePresent = IsThisSectorASAMSector( sSectorX, sSectorY, 0 ); + fSamSitePresent = IsThisSectorASAMSector(sSectorX, sSectorY, 0) || RebelCommand::CanTrainMilitiaAnywhere(); if( fSamSitePresent == FALSE ) { diff --git a/Tactical/ArmsDealerInvInit.cpp b/Tactical/ArmsDealerInvInit.cpp index 9e018066a..16d0fec63 100644 --- a/Tactical/ArmsDealerInvInit.cpp +++ b/Tactical/ArmsDealerInvInit.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -15,6 +16,7 @@ #include "Random.h" #include "Shopkeeper Interface.h" #include "connect.h" + #include "Rebel Command.h" #endif //forward declarations of common classes to eliminate includes @@ -1008,8 +1010,8 @@ UINT8 GetCurrentSuitabilityForItem( INT8 bArmsDealer, UINT16 usItemIndex, BOOLEA // WDS - Improve Tony's and Devin's inventory like BR's // Tony has the better stuff sooner (than Bobby R's) if (bArmsDealer >= 0) { - ubMinCoolness += armsDealerInfo[bArmsDealer].addToCoolness; - ubMaxCoolness += armsDealerInfo[bArmsDealer].addToCoolness; + ubMinCoolness += armsDealerInfo[bArmsDealer].addToCoolness + RebelCommand::GetMerchantCoolnessBonus(); + ubMaxCoolness += armsDealerInfo[bArmsDealer].addToCoolness + RebelCommand::GetMerchantCoolnessBonus(); ubMinCoolness = max( armsDealerInfo[bArmsDealer].minCoolness, min( 9, ubMinCoolness ) ); // silversurfer: max coolness should never be lower than min coolness! //ubMaxCoolness = max( 2, min( armsDealerInfo[bArmsDealer].maxCoolness, ubMaxCoolness ) ); diff --git a/Tactical/DisplayCover.cpp b/Tactical/DisplayCover.cpp index 82a42c0de..32832e706 100644 --- a/Tactical/DisplayCover.cpp +++ b/Tactical/DisplayCover.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "AI All.h" #include "DisplayCover.h" @@ -34,6 +35,7 @@ #include "UI Cursors.h" #include "soldier profile type.h" #include "Interface Cursors.h" // added by Flugente for UICursorDefines +#include "Rebel Command.h" #endif //forward declarations of common classes to eliminate includes @@ -759,7 +761,7 @@ void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetG { const UINT8& ubStance = animArr[i]; - INT32 usAdjustedSight; + INT32 usAdjustedSight = 0; if (pToSoldier == NULL) { usAdjustedSight = usSightLimit; @@ -767,6 +769,8 @@ void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetG usAdjustedSight = usSightLimit + usSightLimit * GetSightAdjustment( pToSoldier, GetStealth(pToSoldier), GetSightAdjustmentBasedOnLBE(pToSoldier), sTargetGridNo, (INT8) fRoof, ubStance ) /100; } + RebelCommand::ApplyVisionModifier(pFromSoldier, usAdjustedSight); + if ( SoldierToVirtualSoldierLineOfSightTest( pFromSoldier, sTargetGridNo, (INT8) fRoof, ubStance, FALSE, usAdjustedSight ) != 0 ) { if ( bOverlayType > i ) bOverlayType = i; @@ -784,7 +788,7 @@ static void CalculateCoverFromEnemySoldier(SOLDIERTYPE* pFromSoldier, const INT3 { const UINT8& ubStance = animArr[i]; - INT32 usAdjustedSight; + INT32 usAdjustedSight = 0; if (pToSoldier == nullptr) { usAdjustedSight = usSightLimit; @@ -793,6 +797,8 @@ static void CalculateCoverFromEnemySoldier(SOLDIERTYPE* pFromSoldier, const INT3 usAdjustedSight = usSightLimit + usSightLimit * GetSightAdjustment(pToSoldier, ToSoldierStealth, ToSoldierLBeSightAdjustment, sTargetGridNo, (INT8)fRoof, ubStance) / 100; } + RebelCommand::ApplyVisionModifier(pFromSoldier, usAdjustedSight); + if (SoldierToVirtualSoldierLineOfSightTest(pFromSoldier, sTargetGridNo, (INT8)fRoof, ubStance, FALSE, usAdjustedSight) != 0) { if (bOverlayType > i) bOverlayType = i; diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index f552825e4..ff88ef95a 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -20,6 +20,7 @@ #include "message.h" #include "Tactical Save.h" // added by Flugente #include "Soldier macros.h" // added by Flugente + #include "Rebel Command.h" #endif extern WorldItems gAllWorldItems; @@ -276,6 +277,10 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 // SANDRO - new behaviour of progress setting bEquipmentModifier = bEquipmentRating + ( ( CalcDifficultyModifier( bSoldierClass ) / 10 ) - 5 ); + + if (bSoldierClass >= SOLDIER_CLASS_ADMINISTRATOR && bSoldierClass <= SOLDIER_CLASS_ARMY) + bEquipmentModifier += RebelCommand::GetEnemyEquipmentCoolnessModifier(); + switch( gGameOptions.ubProgressSpeedOfItemsChoices ) { case ITEM_PROGRESS_VERY_SLOW: @@ -943,6 +948,8 @@ void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponC // don't allow it to be lower than marksmanship, we don't want it to affect their chances of hitting bStatus = (INT8)max( pp->bMarksmanship, bStatus ); + // ... unless we've done something to ruin their gear + bStatus = RebelCommand::GetEnemyEquipmentStatusModifier(bStatus); CreateItem( usGunIndex, bStatus, &(pp->Inv[ HANDPOS ]) ); pp->Inv[ HANDPOS ].fFlags |= OBJECT_UNDROPPABLE; @@ -1457,6 +1464,7 @@ void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetC //INVTYPE *pItem; //UINT16 usRandom; UINT16 usItem = 0, usHelmetItem = 0, usVestItem = 0, usLeggingsItem = 0; + INT8 bStatus = 0; //UINT16 usNumMatches; //INT8 bOrigVestClass = bVestClass; @@ -1494,7 +1502,8 @@ void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetC if(!gGameExternalOptions.fSoldiersWearAnyArmour) usHelmetItem = PickARandomItem(HELMET, pp->ubSoldierClass, bHelmetClass ); if ( usHelmetItem > 0 && Item[usHelmetItem].usItemClass == IC_ARMOUR && !(pp->Inv[ HELMETPOS ].fFlags & OBJECT_NO_OVERWRITE) && Armour[ Item[usHelmetItem].ubClassIndex ].ubArmourClass == ARMOURCLASS_HELMET ) { - CreateItem( usHelmetItem, (INT8)(70+Random(31)), &(pp->Inv[ HELMETPOS ]) ); + bStatus = RebelCommand::GetEnemyEquipmentStatusModifier(70 + Random(31)); + CreateItem( usHelmetItem, bStatus, &(pp->Inv[ HELMETPOS ]) ); pp->Inv[ HELMETPOS ].fFlags |= OBJECT_UNDROPPABLE; // roll to see if he gets an attachment, too. Higher chance the higher his entitled helmet class is @@ -1503,7 +1512,8 @@ void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetC UINT16 usAttachment = PickARandomAttachment(ARMOURATTACHMENT, pp->ubSoldierClass, usHelmetItem, bHelmetClass, FALSE); if ( usAttachment > 0 ) { - CreateItem( usAttachment, (INT8)(70+Random(31)), &gTempObject ); + bStatus = RebelCommand::GetEnemyEquipmentStatusModifier(70 + Random(31)); + CreateItem( usAttachment, bStatus, &gTempObject ); gTempObject.fFlags |= OBJECT_UNDROPPABLE; pp->Inv[ HELMETPOS ].AttachObject( NULL, &gTempObject, FALSE ); } @@ -1567,7 +1577,8 @@ void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetC if(!gGameExternalOptions.fSoldiersWearAnyArmour) usVestItem = PickARandomItem(VEST, pp->ubSoldierClass, bVestClass ); if ( usVestItem > 0 && Item[usVestItem].usItemClass == IC_ARMOUR && !(pp->Inv[ VESTPOS ].fFlags & OBJECT_NO_OVERWRITE) && Armour[ Item[usVestItem].ubClassIndex ].ubArmourClass == ARMOURCLASS_VEST ) { - CreateItem( usVestItem, (INT8)(70+Random(31)), &(pp->Inv[ VESTPOS ]) ); + bStatus = RebelCommand::GetEnemyEquipmentStatusModifier(70 + Random(31)); + CreateItem( usVestItem, bStatus, &(pp->Inv[ VESTPOS ]) ); pp->Inv[ VESTPOS ].fFlags |= OBJECT_UNDROPPABLE; // roll to see if he gets a CERAMIC PLATES, too. Higher chance the higher his entitled vest class is @@ -1576,7 +1587,8 @@ void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetC UINT16 usAttachment = PickARandomAttachment(ARMOURATTACHMENT, pp->ubSoldierClass, usVestItem, bVestClass, FALSE); if ( usAttachment > 0 ) { - CreateItem( usAttachment, (INT8)(70+Random(31)), &gTempObject ); + bStatus = RebelCommand::GetEnemyEquipmentStatusModifier(70 + Random(31)); + CreateItem( usAttachment, bStatus, &gTempObject ); gTempObject.fFlags |= OBJECT_UNDROPPABLE; pp->Inv[ VESTPOS ].AttachObject( NULL, &gTempObject, FALSE ); } @@ -1661,7 +1673,8 @@ void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetC if(!gGameExternalOptions.fSoldiersWearAnyArmour) usLeggingsItem = PickARandomItem(LEGS, pp->ubSoldierClass, bLeggingsClass ); if ( usLeggingsItem > 0 && Item[usLeggingsItem].usItemClass == IC_ARMOUR && !(pp->Inv[ LEGPOS ].fFlags & OBJECT_NO_OVERWRITE) && Armour[ Item[usLeggingsItem].ubClassIndex ].ubArmourClass == ARMOURCLASS_LEGGINGS ) { - CreateItem( usLeggingsItem, (INT8)(70+Random(31)), &(pp->Inv[ LEGPOS ]) ); + bStatus = RebelCommand::GetEnemyEquipmentStatusModifier(70 + Random(31)); + CreateItem( usLeggingsItem, bStatus, &(pp->Inv[ LEGPOS ]) ); pp->Inv[ LEGPOS ].fFlags |= OBJECT_UNDROPPABLE; // roll to see if he gets an attachment, too. Higher chance the higher his entitled Leggings class is @@ -1670,7 +1683,8 @@ void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetC UINT16 usAttachment = PickARandomAttachment(ARMOURATTACHMENT, pp->ubSoldierClass, usLeggingsItem, bLeggingsClass, FALSE); if ( usAttachment > 0 ) { - CreateItem( usAttachment, (INT8)(70+Random(31)), &gTempObject ); + bStatus = RebelCommand::GetEnemyEquipmentStatusModifier(70 + Random(31)); + CreateItem( usAttachment, bStatus, &gTempObject ); gTempObject.fFlags |= OBJECT_UNDROPPABLE; pp->Inv[ LEGPOS ].AttachObject( NULL, &gTempObject, FALSE); } diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index 192b82a08..fc5c6839c 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -1837,6 +1837,8 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT RebelCommand::ApplyMilitiaBonuses(pSoldier); if ((SOLDIER_CLASS_ENEMY(pSoldier->ubSoldierClass) || pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT)) RebelCommand::ApplyEnemyPenalties(pSoldier); + if (pCreateStruct->bTeam == ENEMY_TEAM && (ENEMYROBOT(pCreateStruct) || ARMED_VEHICLE(pCreateStruct))) + RebelCommand::ApplyEnemyMechanicalUnitPenalties(pSoldier); // Flugente: enemy roles if ( gGameExternalOptions.fEnemyRoles && gGameExternalOptions.fEnemyOfficers && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) ) @@ -3223,6 +3225,8 @@ SOLDIERTYPE* TacticalCreateEnemyTank() // Flugente: why would a vehicle's armour depend on game progress? Always give them 100 HP pSoldier->stats.bLifeMax = 100; pSoldier->stats.bLife = pSoldier->stats.bLifeMax; + + RebelCommand::ApplyEnemyMechanicalUnitPenalties(pSoldier); } return( pSoldier ); @@ -3263,6 +3267,8 @@ SOLDIERTYPE* TacticalCreateEnemyJeep( ) // Flugente: why would a vehicle's armour depend on game progress? Always give them 100 HP pSoldier->stats.bLifeMax = 100; pSoldier->stats.bLife = pSoldier->stats.bLifeMax; + + RebelCommand::ApplyEnemyMechanicalUnitPenalties(pSoldier); } return(pSoldier); @@ -3303,6 +3309,8 @@ SOLDIERTYPE* TacticalCreateEnemyRobot() pSoldier->stats.bLifeMax = 80; pSoldier->stats.bLife = pSoldier->stats.bLifeMax; + + RebelCommand::ApplyEnemyMechanicalUnitPenalties(pSoldier); } return(pSoldier); diff --git a/TileEngine/Map Edgepoints.cpp b/TileEngine/Map Edgepoints.cpp index f2ef426b6..afd3c2512 100644 --- a/TileEngine/Map Edgepoints.cpp +++ b/TileEngine/Map Edgepoints.cpp @@ -14,6 +14,7 @@ #include "strategicmap.h" #include "worldman.h" #include "PreBattle Interface.h" // added by Flugente + #include "Rebel Command.h" #endif #include "connect.h" @@ -1401,7 +1402,7 @@ INT32 SearchForClosestPrimaryMapEdgepoint(INT32 sGridNo, UINT8 ubInsertionCode, break; } // WANNE - MP: Center - if ( ( (is_networked || GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE ) && ubInsertionCode == INSERTION_CODE_CENTER) || ubInsertionCode == INSERTION_CODE_CHOPPER ) + if ( ( (is_networked || GetEnemyEncounterCode() == ENEMY_AMBUSH_DEPLOYMENT_CODE ) && ubInsertionCode == INSERTION_CODE_CENTER) || ubInsertionCode == INSERTION_CODE_CHOPPER || (RebelCommand::GetAdditionalDeployRange(ubInsertionCode) > 0) ) { InitCenterEdgepoint( ubInsertionCode == INSERTION_CODE_CENTER ); psArray = gps1stCenterEdgepointArray; diff --git a/TileEngine/Tactical Placement GUI.cpp b/TileEngine/Tactical Placement GUI.cpp index a14b27dd4..8c897f8e1 100644 --- a/TileEngine/Tactical Placement GUI.cpp +++ b/TileEngine/Tactical Placement GUI.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #include "builddefines.h" // WANNE 2 @@ -41,6 +42,7 @@ #include "renderworld.h"//dnl ch45 051009 #include "merc entering.h" #include "CampaignStats.h" // added by Flugente +#include "Rebel Command.h" typedef struct MERCPLACEMENT { @@ -910,6 +912,7 @@ void RenderTacticalPlacementGUI() if(sWorldScreenY <= PLACEMENT_OFFSET) { sY = (PLACEMENT_OFFSET - sWorldScreenY) / 5; + sY += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_NORTH)/5; gTPClipRect.iTop += sY; } break; @@ -917,6 +920,7 @@ void RenderTacticalPlacementGUI() if((sWorldScreenX + NORMAL_MAP_SCREEN_WIDTH) >= (MAPWIDTH - PLACEMENT_OFFSET)) { sX = ((sWorldScreenX + NORMAL_MAP_SCREEN_WIDTH) - (MAPWIDTH - PLACEMENT_OFFSET)) / 5; + sX += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_EAST)/5; gTPClipRect.iRight -= sX; } break; @@ -924,6 +928,7 @@ void RenderTacticalPlacementGUI() if((sWorldScreenY + NORMAL_MAP_SCREEN_HEIGHT) >= (MAPHEIGHT - PLACEMENT_OFFSET)) { sY = ((sWorldScreenY + NORMAL_MAP_SCREEN_HEIGHT) - (MAPHEIGHT - PLACEMENT_OFFSET)) / 5; + sY += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_SOUTH)/5; gTPClipRect.iBottom -= sY; } break; @@ -931,6 +936,7 @@ void RenderTacticalPlacementGUI() if(sWorldScreenX <= PLACEMENT_OFFSET) { sX = (PLACEMENT_OFFSET - sWorldScreenX) / 5; + sX += RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_WEST)/5; gTPClipRect.iLeft += sX; } break; @@ -1234,19 +1240,19 @@ void TacticalPlacementHandle() switch(gMercPlacement[gbCursorMercID].ubStrategicInsertionCode) { case INSERTION_CODE_NORTH: - if(sWorldScreenY <= PLACEMENT_OFFSET) + if(sWorldScreenY <= (PLACEMENT_OFFSET + RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_NORTH))) gfValidCursor = TRUE; break; case INSERTION_CODE_EAST: - if(sWorldScreenX >= (MAPWIDTH - PLACEMENT_OFFSET)) + if(sWorldScreenX >= ((MAPWIDTH - PLACEMENT_OFFSET - RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_EAST)))) gfValidCursor = TRUE; break; case INSERTION_CODE_SOUTH: - if(sWorldScreenY >= (MAPHEIGHT - PLACEMENT_OFFSET)) + if(sWorldScreenY >= ((MAPHEIGHT - PLACEMENT_OFFSET - RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_SOUTH)))) gfValidCursor = TRUE; break; case INSERTION_CODE_WEST: - if(sWorldScreenX <= PLACEMENT_OFFSET) + if(sWorldScreenX <= (PLACEMENT_OFFSET + RebelCommand::GetAdditionalDeployRange(INSERTION_CODE_WEST))) gfValidCursor = TRUE; break; } diff --git a/Utils/Text.h b/Utils/Text.h index b5fcd1e9d..2ed7ca035 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -3138,6 +3138,7 @@ extern STR16 szRebelCommandText[]; extern STR16 szRebelCommandHelpText[]; extern STR16 szRebelCommandAdminActionsText[]; extern STR16 szRebelCommandDirectivesText[]; +extern STR16 szRebelCommandAgentMissionsText[]; extern STR16 szRobotText[]; enum { diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 0a730a333..1dbae02ec 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -290,7 +290,7 @@ STR16 pEncyclopediaFilterCharText[] = {//major char filter button text //..L"------v" L"全部",//All - L"A.I.M", + L"A.I.M.", L"MERC", L"RPC", L"NPC", @@ -4218,7 +4218,7 @@ STR16 pHelicopterEtaStrings[] = L"Skyrider", L"着陆点", L"直升机严重受损,必须降落在敌军领地!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> - L"直升机将直接返回基地,你希望在此之前放下乘客吗?", + L"直升机将直接返回基地,你希望在此之前丢下乘客吗?", L"剩余燃料:", L"到加油站距离:", }; @@ -5097,7 +5097,7 @@ STR16 pLaptopIcons[] = STR16 pBookMarkStrings[] = { - L"A.I.M", + L"A.I.M.", L"Bobby Ray's", L"I.M.P", L"M.E.R.C", @@ -7030,7 +7030,7 @@ STR16 pMessageStrings[] = L"磁盘空间不足。只有%sMB可用空间,《铁血联盟2》需要%sMB。", L"从AIM雇佣了%s。", //"Hired %s from AIM", L"%s抓住了%s。", //"%s has caught %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. - L"%s使用了(拾取)%s。", //L"%s has taken %s。", + L"%s使用了%s。", //L"%s has taken %s。", L"%s没有医疗技能", //"%s has no medical skill",//'Merc name' has no medical skill. //CDRom errors (such as ejecting CD while attempting to read the CD) @@ -11369,19 +11369,19 @@ STR16 szIMPGearPocketText[] = L"选择背心", // L"Select vest", L"选择裤子", //L"Select pants", L"选择头部装备", //L"Select face gear", - L"选择头部装备", //L"Select face gear", + L"选择头部装备", // L"Select face gear", - L"选择主武器", //L"Select main gun", - L"选择副武器", //L"Select sidearm", + L"选择主枪", // L"Select main gun", + L"选择手枪", //L"Select sidearm", L"选择LBE背心", //L"Select LBE vest", - L"选择左LBE枪套", //L"Select left LBE holster", - L"选择右LBE枪套", //L"Select right LBE holster", + L"选择LBE皮套", //L"Select left LBE holster", + L"选择LBE皮套", //L"Select right LBE holster", L"选择LBE战斗包", //L"Select LBE combat pack", L"选择LBE背包", //L"Select LBE backpack", - L"选择发射器/步枪", //L"Select launcher / rifle", - L"选择近战武器", //L"Select melee weapon", + L"Select launcher / rifle", + L"选择武器", //L"Select melee weapon", L"选择附加物品", //L"Select additional items", //BIGPOCK1POS L"选择附加物品", //L"Select additional items", @@ -11390,28 +11390,28 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", - L"选择医疗套件", //L"Select medkit",MEDPOCK1POS - L"选择医疗套件", //L"Select medkit", - L"选择医疗套件", //L"Select medkit", - L"选择医疗套件", //L"Select medkit", - L"选择主武器弹药", //L"Select main gun ammo",SMALLPOCK1POS - L"选择主武器弹药", //L"Select main gun ammo", - L"选择主武器弹药", //L"Select main gun ammo", - L"选择主武器弹药", //L"Select main gun ammo", - L"选择主武器弹药", //L"Select main gun ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo",SMALLPOCK6POS - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择配枪弹药", //L"Select sidearm ammo",SMALLPOCK11POS - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", + L"Select medkit", //MEDPOCK1POS + L"Select medkit", + L"Select medkit", + L"Select medkit", + L"Select main gun ammo", //SMALLPOCK1POS + L"Select main gun ammo", + L"Select main gun ammo", + L"Select main gun ammo", + L"Select main gun ammo", + L"Select launcher / rifle ammo", //SMALLPOCK6POS + L"Select launcher / rifle ammo", + L"Select launcher / rifle ammo", + L"Select launcher / rifle ammo", + L"Select launcher / rifle ammo", + L"Select sidearm ammo", //SMALLPOCK11POS + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", L"选择附加物品", //L"Select additional items", //SMALLPOCK19POS L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", @@ -11424,7 +11424,7 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", //SMALLPOCK30POS - L"左键单击选择项目/右键单击关闭窗口", //L"Left click to select item / Right click to close window", + L"Left click to select item / Right click to close window", }; STR16 szMilitiaStrategicMovementText[] = @@ -11966,7 +11966,7 @@ STR16 szRebelCommandAdminActionsText[] = L"民兵武器库", //L"Militia Warehouses", L"在偏远地区建造仓库,让反抗军为民兵储备武器。提供每日民兵资源。", //L"Construct warehouses in remote areas, allowing the rebels to stockpile weapons for the militia. Provides daily militia resources.", L"税务局", //L"Regional Taxes", - L"从当地人那里筹集资金来帮助你。这是一种永久的行为。增加每日收入,但地区忠诚度会逐日下降。", //L"Collect money from the locals to assist your efforts. This is a permanent action. Increases daily income, but regional loyalty falls daily.", + L"从当地人那里筹集资金来帮助你。增加每日收入,但地区忠诚度会逐日下降。", //L"Collect money from the locals to assist your efforts. Increases daily income, but regional loyalty falls daily.", L"民间援助", //L"Civilian Aid", L"指派一些反抗军直接协助和支持该地区的平民。增加每天志愿者的总数。", //L"Assign some rebels to directly assist and support civilians in the area. Increases daily volunteer pool growth.", L"私人佣兵团", //L"Merc Support", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index f842d6618..ddb901a17 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11976,7 +11976,7 @@ STR16 szRebelCommandAdminActionsText[] = // TODO.Translate 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"Collect money from the locals to assist your efforts. 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", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 9f37ce44b..2c27afb75 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11864,12 +11864,16 @@ STR16 gLbeStatsDesc[14] = 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"National Overview", + L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"Regional (2)", + L"National (1)", + L"Mission (3)", L"Supplies:", L"Incoming Supplies", + L"Intel:", L"/day", L"Current Directive", L"Improve Directive ($%d)", @@ -11932,12 +11936,11 @@ STR16 szRebelCommandText[] = 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"|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.\n \n+%d (Base income)", 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"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", 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.", - L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"This Admin Action applies its bonus to town sectors only.", L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -11966,7 +11969,7 @@ STR16 szRebelCommandAdminActionsText[] = 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"Collect money from the locals to assist your efforts. 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", @@ -12030,6 +12033,28 @@ STR16 szRebelCommandDirectivesText[] = L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"New missions will be available every 48 hours.", + L"A mission is currently active.", + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = { L"The robot's installed weapon cannot be changed.", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index b645769e7..291985904 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11958,7 +11958,7 @@ STR16 szRebelCommandAdminActionsText[] = // TODO.Translate 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"Collect money from the locals to assist your efforts. 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", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index fe934da13..554781897 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11880,7 +11880,7 @@ STR16 szRebelCommandAdminActionsText[] = // TODO.Translate 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"Collect money from the locals to assist your efforts. 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", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 8dd97fc07..658de32f2 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11967,7 +11967,7 @@ STR16 szRebelCommandAdminActionsText[] = // TODO.Translate 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"Collect money from the locals to assist your efforts. 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", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index b66a93eb8..97513cf87 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11980,7 +11980,7 @@ STR16 szRebelCommandAdminActionsText[] = // TODO.Translate 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"Collect money from the locals to assist your efforts. 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", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 92a8e8abb..5d0ee7cfe 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11961,7 +11961,7 @@ STR16 szRebelCommandAdminActionsText[] = // TODO.Translate 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"Collect money from the locals to assist your efforts. 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", From 8858559a10cee5cca7a96e69bff8e869c9cb2e20 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 12 Oct 2022 00:58:30 -0700 Subject: [PATCH 02/52] Add checks before enabling Start Mission button Minor UI adjustments --- GameSettings.cpp | 2 ++ GameSettings.h | 2 ++ Strategic/Rebel Command.cpp | 61 +++++++++++++++++++++++++------------ Strategic/Rebel Command.h | 1 + 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 3a7629833..f1251c61c 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4158,6 +4158,8 @@ void LoadRebelCommandSettings() gRebelCommandSettings.iFortificationsBonus = iniReader.ReadInteger("Rebel Command Settings", "FORTIFICATIONS_BONUS", 10, 0, 100); // agent missions + gRebelCommandSettings.iMinLoyaltyForMission = iniReader.ReadInteger("Rebel Command Settings", "MIN_LOYALTY_FOR_MISSION", 51, 0, 100); + gRebelCommandSettings.iDeepDeploymentSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_SUCCESS_CHANCE", 50, 0, 100); gRebelCommandSettings.iDeepDeploymentRangeNS = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_NS", 200, 0, 1000); gRebelCommandSettings.iDeepDeploymentRangeEW = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_RANGE_EW", 350, 0, 1000); diff --git a/GameSettings.h b/GameSettings.h index 117fcf069..f28fdd7c8 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1843,6 +1843,8 @@ typedef struct INT16 iFortificationsBonus; // agent missions + INT8 iMinLoyaltyForMission; + INT8 iDeepDeploymentSuccessChance; INT16 iDeepDeploymentRangeNS; INT16 iDeepDeploymentRangeEW; diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 737a89e09..681bf9053 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -15,7 +15,7 @@ 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. -Missions were added later and provide powerful temporary bonuses. To enable these bonuses, Supplies must be spent as well as sending +Missions provide powerful temporary bonuses. To enable these bonuses, Supplies must be spent as well as sending either a generic rebel agent or one of their own mercenaries, the latter providing better mission bonuses. @@ -2111,13 +2111,13 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) LineDraw(FALSE, x, y, x+230, y, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); // bottom horizontal line - LineDraw(FALSE, x, y+300, x+230, y+300, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + LineDraw(FALSE, x, y+310, x+230, y+310, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); // left vertical line - LineDraw(FALSE, x, y, x, y+300, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + LineDraw(FALSE, x, y, x, y+310, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); // right vertical line - LineDraw(FALSE, x+230, y, x+230, y+300, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); + LineDraw(FALSE, x+230, y, x+230, y+310, Get16BPPColor(FROMRGB(0, 0, 0)), pDestBuf); UnLockVideoSurface( FRAME_BUFFER ); @@ -2198,8 +2198,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } DisplayWrappedString(x+5, y+45, 220, 2, FONT10ARIAL, FONT_MCOLOR_BLACK, sText, FONT_MCOLOR_BLACK, FALSE, 0); - // draw agent portrait - if (agentIndex[index] == mercs.size()) + if (agentIndex[index] == mercs.size()) // generic rebel agent { // draw black box for face ColorFillVideoSurfaceArea(FRAME_BUFFER, x+5, y+150+10, x+5+48, y+150+10+43, Get16BPPColor(FROMRGB(64, 64, 64))); @@ -2221,7 +2220,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) // draw contract DrawTextToScreen(L"Contract: ---", x+55, y+150+46, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } - else + else // one of the player's mercs { // draw face vObjDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE; @@ -2407,17 +2406,32 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } } - // draw "start mission" btn - swprintf(sText, L"Start Mission (%d supplies)", GetMissionCost()); - btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x, y+290, 231, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) - { - const INT8 index = MSYS_GetBtnUserData(btn, 0); - ButtonHelper(btn, reason, [btn, index]() { - StartMission(index); + // draw "start mission" button + const UINT8 townId = GetTownIdForSector(mercs[agentIndex[index]]->sSectorX, mercs[agentIndex[index]]->sSectorY); + const UINT8 townLoyalty = GetRegionLoyalty(townId); + if ((agentIndex[index] < static_cast(mercs.size())) && (townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission)) + { + swprintf(sText, L"Agent not in loyal town"); + DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + } + else if ((gTacticalStatus.uiFlags & INCOMBAT) || gTacticalStatus.fEnemyInSector) + { + swprintf(sText, L"Battle in progress"); + DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + } + else // ok to start mission + { + swprintf(sText, L"Start Mission (%d supplies)", GetMissionCost()); + btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x, y+290, 231, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + const INT8 index = MSYS_GetBtnUserData(btn, 0); + ButtonHelper(btn, reason, [btn, index]() { + StartMission(index); + }); }); - }); - MSYS_SetBtnUserData(btnId, 0, index); - btnIds.push_back(btnId); + MSYS_SetBtnUserData(btnId, 0, index); + btnIds.push_back(btnId); + } return TRUE; } @@ -2487,7 +2501,7 @@ void RenderMissionOverview() } // "new missions every X hours" text - DrawTextToScreen(szRebelCommandAgentMissionsText[RCAMT_NEW_MISSIONS_AVAILABLE_TIME], WEBSITE_LEFT + 22, WEBSITE_TOP + WEBSITE_HEIGHT - 17, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + DrawTextToScreen(szRebelCommandAgentMissionsText[RCAMT_NEW_MISSIONS_AVAILABLE_TIME], WEBSITE_LEFT + 22, WEBSITE_TOP + WEBSITE_HEIGHT - 14, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } void StartMission(INT8 index) @@ -2599,7 +2613,7 @@ void StartMission(INT8 index) missionSuccessChance += GetMissionSuccessChanceBonus(&merc); - if (Random(100) > missionSuccessChance) + if (Random(100) > static_cast(missionSuccessChance)) { // mission failed! missionDuration = 0; @@ -2639,7 +2653,14 @@ void StartMission(INT8 index) if (pSoldier->ubProfile != evt.mercProfileId) continue; - // rftr todo: send selected merc on assignment, like mini event adventure + //TakeSoldierOutOfVehicle(pSoldier); + //RemoveCharacterFromSquads(pSoldier); + //pSoldier->ubHoursRemainingOnMiniEvent = hoursOnMiniEvent; + //pSoldier->bSectorZ += MINI_EVENT_Z_OFFSET; + //pSoldier->bBleeding = 0; + //SetTimeOfAssignmentChangeForMerc(pSoldier); + //ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); + for (INT8 i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) { if (evt.missionId == rebelCommandSaveInfo.availableMissions[i]) diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index f3b56d953..314eaa7f3 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -5,6 +5,7 @@ #include "Soldier Control.h" #include "Types.h" +#define REBEL_COMMAND_Z_OFFSET 9 #define REBEL_COMMAND_MAX_ACTIONS_PER_REGION 6 #define NUM_ARC_AGENT_SLOTS 2 From feaf9827c9176279161c60f47da96552c40a8e97 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Thu, 13 Oct 2022 01:18:44 -0700 Subject: [PATCH 03/52] Set up ASSIGNMENT_REBELCOMMAND Hook up Start Mission button --- Strategic/Assignments.cpp | 18 +++-- Strategic/Hourly Update.cpp | 2 + Strategic/Map Screen Interface Bottom.cpp | 1 + Strategic/Map Screen Interface Map.cpp | 2 + Strategic/Map Screen Interface.cpp | 8 +- Strategic/PreBattle Interface.cpp | 1 + Strategic/Queen Command.cpp | 7 +- Strategic/Rebel Command.cpp | 99 +++++++++++++++-------- Strategic/Strategic Movement.cpp | 3 +- Strategic/mapscreen.cpp | 23 ++++-- Strategic/strategicmap.cpp | 4 +- Tactical/Dialogue Control.cpp | 20 ++++- Tactical/DynamicDialogue.cpp | 5 +- Tactical/Food.cpp | 2 +- Tactical/Soldier Control.cpp | 2 +- Tactical/Squads.cpp | 5 ++ Tactical/Strategic Exit GUI.cpp | 2 +- Tactical/opplist.cpp | 2 +- TileEngine/Tactical Placement GUI.cpp | 2 + Utils/_EnglishText.cpp | 3 +- 20 files changed, 151 insertions(+), 60 deletions(-) diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 2b5faccee..b9949f327 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -814,6 +814,11 @@ BOOLEAN BasicCanCharacterAssignment( SOLDIERTYPE * pSoldier, BOOLEAN fNotInComba return( FALSE ); } + if (pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + { + return( FALSE ); + } + return( TRUE ); } @@ -2501,7 +2506,7 @@ BOOLEAN CanCharacterSleep( SOLDIERTYPE *pSoldier, BOOLEAN fExplainWhyNot ) } // POW? - if( pSoldier->bAssignment == ASSIGNMENT_POW || pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) + if( pSoldier->bAssignment == ASSIGNMENT_POW || pSoldier->bAssignment == ASSIGNMENT_MINIEVENT || pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) { return( FALSE ); } @@ -2719,7 +2724,7 @@ INT8 CanCharacterSquad( SOLDIERTYPE *pSoldier, INT8 bSquadValue ) return ( CHARACTER_CANT_JOIN_SQUAD ); } - if ( pSoldier->bAssignment == ASSIGNMENT_POW || (pSoldier->bAssignment == ASSIGNMENT_MINIEVENT && pSoldier->ubHoursRemainingOnMiniEvent > 0)) + if ( pSoldier->bAssignment == ASSIGNMENT_POW || (pSoldier->bAssignment == ASSIGNMENT_MINIEVENT && pSoldier->ubHoursRemainingOnMiniEvent > 0) || (pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) ) { // not allowed to be put on a squad return( CHARACTER_CANT_JOIN_SQUAD ); @@ -5840,7 +5845,7 @@ void FatigueCharacter( SOLDIERTYPE *pSoldier ) } // POW? - if( pSoldier->bAssignment == ASSIGNMENT_POW || pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) + if( pSoldier->bAssignment == ASSIGNMENT_POW || pSoldier->bAssignment == ASSIGNMENT_MINIEVENT || pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) { return; } @@ -16323,7 +16328,7 @@ void HandleRestFatigueAndSleepStatus( void ) continue; } - if( ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) ) + if( ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { continue; } @@ -16472,7 +16477,7 @@ void HandleRestFatigueAndSleepStatus( void ) continue; } - if( ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) ) + if( ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { continue; } @@ -19453,7 +19458,8 @@ BOOLEAN CanCharacterRepairAnotherSoldiersStuff( SOLDIERTYPE *pSoldier, SOLDIERTY ( AM_A_ROBOT( pSoldier ) ) || ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC ) || ( pOtherSoldier->bAssignment == ASSIGNMENT_DEAD ) || - ( pOtherSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) ) + ( pOtherSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || + ( pOtherSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { return( FALSE ); } diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index 800e5603e..876211ad6 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -712,6 +712,7 @@ void HourlyStealUpdate() && pSoldier->bAssignment != IN_TRANSIT && pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT + && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND && !( ( ( gWorldSectorX == pSoldier->sSectorX ) && ( gWorldSectorY == pSoldier->sSectorY ) && ( gbWorldSectorZ == pSoldier->bSectorZ ) ) && ( gTacticalStatus.fEnemyInSector || guiCurrentScreen == GAME_SCREEN ) ) ) { UINT8 ubSectorId = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ); @@ -741,6 +742,7 @@ void HourlyStealUpdate() && pOtherSoldier->bAssignment != IN_TRANSIT && pOtherSoldier->bAssignment != ASSIGNMENT_POW && pOtherSoldier->bAssignment != ASSIGNMENT_MINIEVENT + && pOtherSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND && !SPY_LOCATION( pOtherSoldier->bAssignment ) && pOtherSoldier->bActive && !pOtherSoldier->flags.fMercAsleep diff --git a/Strategic/Map Screen Interface Bottom.cpp b/Strategic/Map Screen Interface Bottom.cpp index f1a730c4d..004a67e4c 100644 --- a/Strategic/Map Screen Interface Bottom.cpp +++ b/Strategic/Map Screen Interface Bottom.cpp @@ -1795,6 +1795,7 @@ BOOLEAN AnyUsableRealMercenariesOnTeam( void ) ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_DEAD ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && + ( pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) && ( pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__EPC ) ) { return( TRUE ); diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 580419138..39cca58a2 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -1366,6 +1366,7 @@ INT32 ShowAssignedTeam(INT16 sMapX, INT16 sMapY, INT32 iCount) ( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && + ( pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) && ( pSoldier->stats.bLife > 0 ) && ( !PlayerIDGroupInMotion( pSoldier->ubGroupID ) ) ) { @@ -6976,6 +6977,7 @@ BOOLEAN CanMercsScoutThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || + ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || ( pSoldier->flags.fMercAsleep == TRUE ) || ( pSoldier->stats.bLife < OKLIFE ) ) { diff --git a/Strategic/Map Screen Interface.cpp b/Strategic/Map Screen Interface.cpp index 409747576..41111229f 100644 --- a/Strategic/Map Screen Interface.cpp +++ b/Strategic/Map Screen Interface.cpp @@ -1938,7 +1938,7 @@ void UpdateCharRegionHelpText( void ) pSoldier = MercPtrs[ gCharactersList[ bSelectedInfoChar ].usSolID ]; // health/energy/morale - if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) + if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) { if ( pSoldier->stats.bLife != 0 ) { @@ -3713,7 +3713,7 @@ void SetUpMovingListsForSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ]; if( ( pSoldier->bActive ) && - ( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && !SPY_LOCATION( pSoldier->bAssignment ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && + ( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && !SPY_LOCATION( pSoldier->bAssignment ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) && ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == sSectorZ ) ) { if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) @@ -6063,8 +6063,8 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber return( FALSE ); } - // mini event? - if ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) + // mini event/rebel command? + if ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT || pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) { *pbErrorNumber = 29; return( FALSE ); diff --git a/Strategic/PreBattle Interface.cpp b/Strategic/PreBattle Interface.cpp index f285cd2e6..d27d0654b 100644 --- a/Strategic/PreBattle Interface.cpp +++ b/Strategic/PreBattle Interface.cpp @@ -2376,6 +2376,7 @@ BOOLEAN PlayerMercInvolvedInThisCombat( SOLDIERTYPE *pSoldier ) pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_DEAD && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && + pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && // Robot is involved if it has a valid controller with it, uninvolved otherwise ( !AM_A_ROBOT( pSoldier ) || ( pSoldier->ubRobotRemoteHolderID != NOBODY ) ) && diff --git a/Strategic/Queen Command.cpp b/Strategic/Queen Command.cpp index eb32fe440..497d71b58 100644 --- a/Strategic/Queen Command.cpp +++ b/Strategic/Queen Command.cpp @@ -299,7 +299,7 @@ UINT16 NumPlayerTeamMembersInSector( INT16 sSectorX, INT16 sSectorY, INT8 sSecto // we test several conditions before we allow adding an opinion // other merc must be active, have a profile, be someone else and not be in transit or dead if ( pTeamSoldier->bActive && !pTeamSoldier->flags.fBetweenSectors && pTeamSoldier->stats.bLife > 0 && !(pTeamSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) && - !(pTeamSoldier->bAssignment == IN_TRANSIT || pTeamSoldier->bAssignment == ASSIGNMENT_DEAD || pTeamSoldier->bAssignment == ASSIGNMENT_POW || pTeamSoldier->bAssignment == ASSIGNMENT_MINIEVENT) && + !(pTeamSoldier->bAssignment == IN_TRANSIT || pTeamSoldier->bAssignment == ASSIGNMENT_DEAD || pTeamSoldier->bAssignment == ASSIGNMENT_POW || pTeamSoldier->bAssignment == ASSIGNMENT_MINIEVENT || pTeamSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) && (pTeamSoldier->sSectorX == sSectorX && pTeamSoldier->sSectorY == sSectorY && pTeamSoldier->bSectorZ == sSectorZ) ) { ++teammemberspresent; @@ -2795,6 +2795,11 @@ void EnemyCapturesPlayerSoldier( SOLDIERTYPE *pSoldier ) return; } + if (pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + { + return; + } + if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { return; diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 681bf9053..d1ea51653 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -87,6 +87,7 @@ Points of interest: #include "Queen Command.h" #include "random.h" #include "SaveLoadGame.h" +#include "Squads.h" #include "strategic.h" #include "strategicmap.h" #include "Strategic Mines.h" @@ -95,6 +96,7 @@ Points of interest: #include "Text.h" #include "Town Militia.h" #include "Utilities.h" +#include "Vehicles.h" #include "WCheck.h" #include "WordWrap.h" #endif @@ -171,6 +173,9 @@ void GetMissionInfo(RebelCommandAgentMissions mission, const MERCPROFILESTRUCT* intModifierSkill = 0; extraBits = 0; + if (mission == RCAM_NONE) + return; + const std::vector* skills = gGameOptions.fNewTraitSystem ? &missionInfo[mission].newSkills : &missionInfo[mission].oldSkills; for (int i = 0; i < sizeof(merc->bSkillTraits) / sizeof(merc->bSkillTraits[0]); ++i) @@ -2128,6 +2133,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) if (agentIndex[index] < 0) agentIndex[index] = static_cast(mercs.size()); else if (agentIndex[index] > static_cast(mercs.size())) agentIndex[index] = 0; + // rftr todo: handle RCAM_NONE (ie, mission prep in progress!) + // draw mission title switch (rebelCommandSaveInfo.availableMissions[index]) { @@ -2407,19 +2414,27 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } // draw "start mission" button - const UINT8 townId = GetTownIdForSector(mercs[agentIndex[index]]->sSectorX, mercs[agentIndex[index]]->sSectorY); - const UINT8 townLoyalty = GetRegionLoyalty(townId); - if ((agentIndex[index] < static_cast(mercs.size())) && (townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission)) + BOOLEAN canStartMission = TRUE; + if (agentIndex[index] < static_cast(mercs.size())) { - swprintf(sText, L"Agent not in loyal town"); - DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + const UINT8 townId = GetTownIdForSector(mercs[agentIndex[index]]->sSectorX, mercs[agentIndex[index]]->sSectorY); + const UINT8 townLoyalty = GetRegionLoyalty(townId); + + if (townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission) + { + canStartMission = FALSE; + swprintf(sText, L"Agent not in loyal town"); + DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + } } else if ((gTacticalStatus.uiFlags & INCOMBAT) || gTacticalStatus.fEnemyInSector) { + canStartMission = FALSE; swprintf(sText, L"Battle in progress"); DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); } - else // ok to start mission + + if (canStartMission) { swprintf(sText, L"Start Mission (%d supplies)", GetMissionCost()); btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x, y+290, 231, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) @@ -2646,37 +2661,42 @@ void StartMission(INT8 index) MissionFirstEvent evt; DeserialiseMissionFirstEvent(MissionHelpers::missionParam, evt); - for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + if (!evt.sentGenericRebelAgent) { - SOLDIERTYPE* pSoldier = MercPtrs[i]; + //for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[evt.mercProfileId]; - if (pSoldier->ubProfile != evt.mercProfileId) - continue; + //if (pSoldier->ubProfile != evt.mercProfileId) + // continue; - //TakeSoldierOutOfVehicle(pSoldier); - //RemoveCharacterFromSquads(pSoldier); - //pSoldier->ubHoursRemainingOnMiniEvent = hoursOnMiniEvent; - //pSoldier->bSectorZ += MINI_EVENT_Z_OFFSET; - //pSoldier->bBleeding = 0; - //SetTimeOfAssignmentChangeForMerc(pSoldier); - //ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); + TakeSoldierOutOfVehicle(pSoldier); + RemoveCharacterFromSquads(pSoldier); + pSoldier->bSectorZ += REBEL_COMMAND_Z_OFFSET; + pSoldier->bBleeding = 0; + SetTimeOfAssignmentChangeForMerc(pSoldier); + ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); - for (INT8 i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) - { - if (evt.missionId == rebelCommandSaveInfo.availableMissions[i]) - { - rebelCommandSaveInfo.availableMissions[i] = RCAM_NONE; - break; - } + //break; } + } - // actually start the mission - AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, MissionHelpers::missionParam); - missionMap[static_cast(evt.missionId)] = MissionHelpers::missionParam; - - return; + for (INT8 i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + if (evt.missionId == rebelCommandSaveInfo.availableMissions[i]) + { + rebelCommandSaveInfo.availableMissions[i] = RCAM_NONE; + break; + } } + + // actually start the mission + //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, MissionHelpers::missionParam); + AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60, MissionHelpers::missionParam); // rftr todo: DELETE ME + missionMap[static_cast(evt.missionId)] = MissionHelpers::missionParam; } + + RenderWebsite(); }); } // end website @@ -4291,8 +4311,6 @@ void HandleStrategicEvent(const UINT32 eventParam) { const RebelCommandAgentMissions mission = static_cast(evt1.missionId); const MERCPROFILESTRUCT merc = gMercProfiles[evt1.mercProfileId]; - - // rftr todo: mission successful! give some experience pts // what mission did we do? apply bonuses here, and don't forget to check them later when checking to see if a mission bonus should be applied UINT32 durationBonus = 0; @@ -4332,7 +4350,24 @@ void HandleStrategicEvent(const UINT32 eventParam) AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, SerialiseMissionSecondEvent(evt1.sentGenericRebelAgent, evt1.mercProfileId, mission, extraBits)); - // rftr todo: tell the player that the mission has started. popupbox or screenmsg? + if (!evt1.sentGenericRebelAgent) + { + //for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[evt1.mercProfileId]; + + //if (pSoldier->ubProfile != evt1.mercProfileId) + // continue; + + // rftr todo: tell the player that the mission has started. popupbox or screenmsg? + // rftr todo: mission successful! give some experience pts + pSoldier->bSectorZ -= REBEL_COMMAND_Z_OFFSET; + pSoldier->ubInsertionDirection = DIRECTION_IRRELEVANT; + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CENTER; + AssignmentDone(pSoldier, TRUE, FALSE); + AddCharacterToAnySquad(pSoldier); + } + } } missionMap[mission] = eventParam; diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index 67d0e69db..e06685456 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -5475,7 +5475,7 @@ BOOLEAN TestForBloodcatAmbush( GROUP *pGroup ) { if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) { - if ( MercPtrs[ i ]->sSectorX == pGroup->ubSectorX && MercPtrs[ i ]->sSectorY == pGroup->ubSectorY && MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW && MercPtrs[ i ]->bAssignment != ASSIGNMENT_MINIEVENT && MercPtrs[ i ]->stats.bLife >= OKLIFE ) + if ( MercPtrs[ i ]->sSectorX == pGroup->ubSectorX && MercPtrs[ i ]->sSectorY == pGroup->ubSectorY && MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW && MercPtrs[ i ]->bAssignment != ASSIGNMENT_MINIEVENT && MercPtrs[i]->bAssignment != ASSIGNMENT_REBELCOMMAND && MercPtrs[ i ]->stats.bLife >= OKLIFE ) { if( HAS_SKILL_TRAIT( MercPtrs[ i ], SCOUTING_NT ) && MercPtrs[ i ]->ubProfile != NO_PROFILE ) { @@ -5880,6 +5880,7 @@ BOOLEAN GroupHasInTransitDeadOrPOWMercs( GROUP *pGroup ) if( ( pPlayer->pSoldier->bAssignment == IN_TRANSIT ) || ( pPlayer->pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pPlayer->pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || + ( pPlayer->pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || SPY_LOCATION( pPlayer->pSoldier->bAssignment ) || ( pPlayer->pSoldier->bAssignment == ASSIGNMENT_DEAD ) ) { diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index e9798e15b..325f557be 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -2411,7 +2411,8 @@ void DrawCharBars( void ) if( ( pSoldier->stats.bLife == 0 ) || ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || - ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) ) + ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || + ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { return; } @@ -2829,7 +2830,7 @@ void DrawCharHealth( INT16 sCharNum ) pSoldier = &Menptr[gCharactersList[sCharNum].usSolID]; - if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) + if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) { // find starting X coordinate by centering all 3 substrings together, then print them separately (different colors)! swprintf( sString, L"%d/%d", pSoldier->stats.bLife, pSoldier->stats.bLifeMax ); @@ -11328,7 +11329,7 @@ void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) fPlotForMilitia = FALSE; // if not dead or POW, select his sector - if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ))//&& !SPY_LOCATION( pSoldier->bAssignment ) ) + if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) )//&& !SPY_LOCATION( pSoldier->bAssignment ) ) { ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); } @@ -11384,7 +11385,7 @@ void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) fPlotForMilitia = FALSE; // if not dead or POW, select his sector - if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && !SPY_LOCATION( pSoldier->bAssignment ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) ) + if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && !SPY_LOCATION( pSoldier->bAssignment ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); } @@ -11567,7 +11568,7 @@ void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) fShownAssignmentMenu = FALSE; // if not dead or POW, select his sector - if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) ) + if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); } @@ -15115,6 +15116,7 @@ BOOLEAN MapCharacterHasAccessibleInventory( INT8 bCharNumber ) if( ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || + ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || // Kaiden: Vehicle Inventory change - Commented the following line // ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || // And added this instead: @@ -15303,7 +15305,7 @@ BOOLEAN CanChangeSleepStatusForSoldier( SOLDIERTYPE *pSoldier ) // if a vehicle, robot, in transit, or a POW if( ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || AM_A_ROBOT( pSoldier ) || - ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) ) + ( pSoldier->bAssignment == IN_TRANSIT ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) ) { // can't change the sleep status of such mercs return ( FALSE ); @@ -15856,7 +15858,7 @@ INT16 CalcLocationValueForChar( INT32 iCounter ) pSoldier = MercPtrs[ gCharactersList[ iCounter ].usSolID ]; // don't reveal location of POWs! - if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) + if( pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) { sLocValue = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ); // underground: add 1000 per sublevel @@ -15950,6 +15952,7 @@ BOOLEAN AnyMovableCharsInOrBetweenThisSector( INT16 sSectorX, INT16 sSectorY, IN SPY_LOCATION( pSoldier->bAssignment ) || ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || + ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || ( pSoldier->stats.bLife == 0 ) ) { continue; @@ -16554,6 +16557,11 @@ void GetMapscreenMercLocationString( SOLDIERTYPE *pSoldier, CHAR16 sString[] ) // mini event - unknown location, use the same string as POWs swprintf( sString, L"%s", pPOWStrings[ 1 ] ); } + else if (pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + { + // on a rebel command mission + swprintf( sString, L"%s%s*", pMapVertIndex[pSoldier->sSectorY], pMapHortIndex[pSoldier->sSectorX] ); + } else if ( SPY_LOCATION( pSoldier->bAssignment ) ) { swprintf( pTempString, L"%s%s%s", @@ -16594,6 +16602,7 @@ void GetMapscreenMercDestinationString( SOLDIERTYPE *pSoldier, CHAR16 sString[] if( ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) || ( pSoldier->bAssignment == ASSIGNMENT_POW ) || ( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) || + ( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) || SPY_LOCATION( pSoldier->bAssignment ) || ( pSoldier->stats.bLife == 0 ) ) { diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index 03a881c76..dda550d93 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -5229,7 +5229,7 @@ BOOLEAN CanGoToTacticalInSector( INT16 sX, INT16 sY, UINT8 ubZ ) { // ARM: now allows loading of sector with all mercs below OKLIFE as long as they're alive if( ( pSoldier->bActive && pSoldier->stats.bLife ) && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && - ( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && + ( pSoldier->bAssignment != IN_TRANSIT ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != ASSIGNMENT_MINIEVENT ) && ( pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND ) && ( pSoldier->bAssignment != ASSIGNMENT_DEAD ) && !SoldierAboardAirborneHeli( pSoldier ) ) @@ -6402,7 +6402,7 @@ void HandleSlayDailyEvent( void ) } // valid soldier? - if ( (pSoldier->bActive == FALSE) || (pSoldier->stats.bLife == 0) || (pSoldier->bAssignment == IN_TRANSIT) || (pSoldier->bAssignment == ASSIGNMENT_POW) || (pSoldier->bAssignment == ASSIGNMENT_MINIEVENT) ) + if ( (pSoldier->bActive == FALSE) || (pSoldier->stats.bLife == 0) || (pSoldier->bAssignment == IN_TRANSIT) || (pSoldier->bAssignment == ASSIGNMENT_POW) || (pSoldier->bAssignment == ASSIGNMENT_MINIEVENT) || (pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) ) { // no return; diff --git a/Tactical/Dialogue Control.cpp b/Tactical/Dialogue Control.cpp index 2d2efb528..1c95d70ec 100644 --- a/Tactical/Dialogue Control.cpp +++ b/Tactical/Dialogue Control.cpp @@ -1515,6 +1515,9 @@ BOOLEAN DelayedTacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteN if( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) return( FALSE ); + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + return( FALSE ); + return( CharacterDialogue( pSoldier->ubProfile, usQuoteNum, pSoldier->iFaceIndex, DIALOGUE_TACTICAL_UI, TRUE, TRUE ) ); } @@ -1574,6 +1577,9 @@ BOOLEAN TacticalCharacterDialogueWithSpecialEventEx( SOLDIERTYPE *pSoldier, UINT if( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) return( FALSE ); + + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + return( FALSE ); } return( CharacterDialogueWithSpecialEventEx( pSoldier->ubProfile, usQuoteNum, pSoldier->iFaceIndex, DIALOGUE_TACTICAL_UI, TRUE, FALSE, uiFlag, uiData1, uiData2, uiData3 ) ); @@ -1625,6 +1631,9 @@ BOOLEAN TacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum ) if( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) return( FALSE ); + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + return( FALSE ); + // OK, let's check if this is the exact one we just played, if so, skip. if ( pSoldier->ubProfile == gTacticalStatus.ubLastQuoteProfileNUm && usQuoteNum == gTacticalStatus.ubLastQuoteSaid ) @@ -1717,6 +1726,9 @@ BOOLEAN SnitchTacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNu if( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) return( FALSE ); + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + return( FALSE ); + // OK, let's check if this is the exact one we just played, if so, skip. //if ( pSoldier->ubProfile == gTacticalStatus.ubLastQuoteProfileNUm && // usQuoteNum == gTacticalStatus.ubLastQuoteSaid ) @@ -1774,6 +1786,9 @@ BOOLEAN AdditionalTacticalCharacterDialogue_CallsLua( SOLDIERTYPE *pSoldier, UIN if( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) return( FALSE ); + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + return( FALSE ); + if ( AM_AN_EPC( pSoldier ) && !( gMercProfiles[pSoldier->ubProfile].ubMiscFlags & PROFILE_MISC_FLAG_FORCENPCQUOTE ) ) return( FALSE ); @@ -1802,7 +1817,7 @@ void AdditionalTacticalCharacterDialogue_AllInSector(INT16 aSectorX, INT16 aSect if ( pSoldier->stats.bLife >= OKLIFE && pSoldier->bActive && pSoldier->ubProfile != ausIgnoreProfile && pSoldier->sSectorX == aSectorX && pSoldier->sSectorY == aSectorY && pSoldier->bSectorZ == aSectorZ && - pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != IN_TRANSIT && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && + pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != IN_TRANSIT && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND && (aAroundGridno == NOWHERE || PythSpacesAway( pSoldier->sGridNo, aAroundGridno ) <= aRadius ) && !pSoldier->flags.fBetweenSectors ) { @@ -2105,6 +2120,9 @@ BOOLEAN ExecuteCharacterDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 if( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) return( FALSE ); + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + return( FALSE ); + // sleeping guys don't talk.. go to standby to talk if( pSoldier->flags.fMercAsleep == TRUE ) { diff --git a/Tactical/DynamicDialogue.cpp b/Tactical/DynamicDialogue.cpp index 68b69b1d1..ac6e5f951 100644 --- a/Tactical/DynamicDialogue.cpp +++ b/Tactical/DynamicDialogue.cpp @@ -960,6 +960,9 @@ BOOLEAN DynamicOpinionTacticalCharacterDialogue( DynamicOpinionSpeechEvent& aEve if( pSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) return( FALSE ); + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + return( FALSE ); + CHAR16 gzQuoteStr[500]; // remove old box, in case that still exists @@ -2020,7 +2023,7 @@ UINT8 GetFittingInterjectorProfile( UINT8 usEvent, UINT8 usProfileVictim, UINT8 for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ ) { // only people that are here - if ( !pTeamSoldier->bActive || pTeamSoldier->bAssignment == IN_TRANSIT || pTeamSoldier->bAssignment == ASSIGNMENT_DEAD || pTeamSoldier->bAssignment == ASSIGNMENT_POW || pTeamSoldier->bAssignment == ASSIGNMENT_MINIEVENT ) + if ( !pTeamSoldier->bActive || pTeamSoldier->bAssignment == IN_TRANSIT || pTeamSoldier->bAssignment == ASSIGNMENT_DEAD || pTeamSoldier->bAssignment == ASSIGNMENT_POW || pTeamSoldier->bAssignment == ASSIGNMENT_MINIEVENT || pTeamSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND ) continue; // if fSameSector is TRUE then the teammate must be in the same sector diff --git a/Tactical/Food.cpp b/Tactical/Food.cpp index 071721918..2d1e6399d 100644 --- a/Tactical/Food.cpp +++ b/Tactical/Food.cpp @@ -606,7 +606,7 @@ void HourlyFoodAutoDigestion( SOLDIERTYPE *pSoldier ) AddFoodpoints(pSoldier->bFoodLevel, powfoodadd); } // while on a minievent, assume that we can feed ourselves.. somehow - else if (pSoldier->bAssignment == ASSIGNMENT_MINIEVENT) + else if (pSoldier->bAssignment == ASSIGNMENT_MINIEVENT || pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) { const INT16 water = gGameExternalOptions.usFoodDigestionHourlyBaseDrink * gGameExternalOptions.sFoodDigestionAssignment; const INT16 foodadd = water * gGameExternalOptions.usFoodDigestionHourlyBaseFood / max(1, gGameExternalOptions.usFoodDigestionHourlyBaseDrink); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index e3fe1d3a8..dbdea3f84 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -6311,7 +6311,7 @@ void SOLDIERTYPE::EVENT_SoldierGotHit( UINT16 usWeaponIndex, INT16 sDamage, INT1 // If anything other than on a squad or guard, make them guard.... if ( this->bTeam == gbPlayerNum ) { - if ( this->bAssignment >= ON_DUTY && this->bAssignment != ASSIGNMENT_POW && this->bAssignment != ASSIGNMENT_MINIEVENT ) + if ( this->bAssignment >= ON_DUTY && this->bAssignment != ASSIGNMENT_POW && this->bAssignment != ASSIGNMENT_MINIEVENT && this->bAssignment != ASSIGNMENT_REBELCOMMAND) { if ( this->flags.fMercAsleep ) { diff --git a/Tactical/Squads.cpp b/Tactical/Squads.cpp index dc6176c9c..91ef17775 100644 --- a/Tactical/Squads.cpp +++ b/Tactical/Squads.cpp @@ -1389,6 +1389,11 @@ BOOLEAN IsSquadInSector( SOLDIERTYPE *pSoldier, UINT8 ubSquad ) return( FALSE ); } + if( pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) + { + return( FALSE ); + } + if( SquadIsEmpty( ubSquad ) == TRUE ) { return( TRUE ); diff --git a/Tactical/Strategic Exit GUI.cpp b/Tactical/Strategic Exit GUI.cpp index b56531d07..00274713e 100644 --- a/Tactical/Strategic Exit GUI.cpp +++ b/Tactical/Strategic Exit GUI.cpp @@ -238,7 +238,7 @@ BOOLEAN InternalInitSectorExitMenu( UINT8 ubDirection, INT32 sAdditionalData )// pSoldier->stats.bLife >= OKLIFE && ( pSoldier->bAssignment != MercPtrs[ gusSelectedSoldier ]->bAssignment || ( pSoldier->bAssignment == VEHICLE && pSoldier->iVehicleId != MercPtrs[ gusSelectedSoldier ]->iVehicleId ) ) && - pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != IN_TRANSIT && pSoldier->bAssignment != ASSIGNMENT_DEAD && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT + pSoldier->bAssignment != ASSIGNMENT_POW && pSoldier->bAssignment != IN_TRANSIT && pSoldier->bAssignment != ASSIGNMENT_DEAD && pSoldier->bAssignment != ASSIGNMENT_MINIEVENT && pSoldier->bAssignment != ASSIGNMENT_REBELCOMMAND && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE) ) { //KM: We need to determine if there are more than one squad (meaning other concious mercs in a different squad or assignment) // These conditions were done to the best of my knowledge, so if there are other situations that require modification, diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index 8f6db0d01..a4fb07cba 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -6001,7 +6001,7 @@ void ProcessNoise(UINT8 ubNoiseMaker, INT32 sGridNo, INT8 bLevel, UINT8 ubTerrTy continue; // skip } - if ( bTeam == gbPlayerNum && (pSoldier->bAssignment == ASSIGNMENT_POW || pSoldier->bAssignment == ASSIGNMENT_MINIEVENT) ) + if ( bTeam == gbPlayerNum && (pSoldier->bAssignment == ASSIGNMENT_POW || pSoldier->bAssignment == ASSIGNMENT_MINIEVENT || pSoldier->bAssignment == ASSIGNMENT_REBELCOMMAND) ) { // POWs should not be processed for noise continue; diff --git a/TileEngine/Tactical Placement GUI.cpp b/TileEngine/Tactical Placement GUI.cpp index 8c897f8e1..3a8523d66 100644 --- a/TileEngine/Tactical Placement GUI.cpp +++ b/TileEngine/Tactical Placement GUI.cpp @@ -340,6 +340,7 @@ void InitTacticalPlacementGUI() !( MercPtrs[ i ]->flags.uiStatusFlags & ( SOLDIER_VEHICLE ) ) && // ATE Ignore vehicles MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW && MercPtrs[ i ]->bAssignment != ASSIGNMENT_MINIEVENT && + MercPtrs[ i ]->bAssignment != ASSIGNMENT_REBELCOMMAND && !( MercPtrs[i]->usSoldierFlagMask2 & SOLDIER_CONCEALINSERTION ) && MercPtrs[ i ]->bAssignment != IN_TRANSIT ) { @@ -357,6 +358,7 @@ void InitTacticalPlacementGUI() CurrentBattleSectorIs( MercPtrs[i]->sSectorX, MercPtrs[i]->sSectorY, MercPtrs[i]->bSectorZ ) && MercPtrs[ i ]->bAssignment != ASSIGNMENT_POW && MercPtrs[ i ]->bAssignment != ASSIGNMENT_MINIEVENT && + MercPtrs[ i ]->bAssignment != ASSIGNMENT_REBELCOMMAND && !( MercPtrs[i]->usSoldierFlagMask2 & SOLDIER_CONCEALINSERTION ) && MercPtrs[ i ]->bAssignment != IN_TRANSIT && !( MercPtrs[ i ]->flags.uiStatusFlags & ( SOLDIER_VEHICLE ) ) ) // ATE Ignore vehicles diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 2c27afb75..e4f8d35a2 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -2480,7 +2480,8 @@ STR16 pAssignmentStrings[] = L"Burial", L"Admin", L"Explore", - L"Event"// rftr: merc is on a mini event + L"Event", // rftr: merc is on a mini event + L"Mission", // rftr: rebel command }; From dea5da5fc6828bfe7d10d26a00c1a28079865803 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 14 Oct 2022 00:26:38 -0700 Subject: [PATCH 04/52] Implement "Train Militia Anywhere" Subtract supplies when starting mission Fix second stage mission strategic event --- Strategic/Assignments.cpp | 4 ++-- Strategic/Rebel Command.cpp | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index b9949f327..0afaa74dc 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -1980,7 +1980,7 @@ BOOLEAN CanCharacterTrainMilitia( SOLDIERTYPE *pSoldier ) } } - if (RebelCommand::CanTrainMilitiaAnywhere()) + if (RebelCommand::CanTrainMilitiaAnywhere() && GetTownIdForSector(pSoldier->sSectorX, pSoldier->sSectorY) == BLANK_SECTOR) ubFacilityTrainersAllowed = RebelCommand::GetMaxTrainersForTrainMilitiaAnywhere(); // Count number of trainers already operating here @@ -20182,7 +20182,7 @@ BOOLEAN CanCharacterTrainMilitiaWithErrorReport( SOLDIERTYPE *pSoldier ) } } - if (RebelCommand::CanTrainMilitiaAnywhere()) + if (RebelCommand::CanTrainMilitiaAnywhere() && GetTownIdForSector(pSoldier->sSectorX, pSoldier->sSectorY) == BLANK_SECTOR) ubFacilityTrainersAllowed = RebelCommand::GetMaxTrainersForTrainMilitiaAnywhere(); // If we are here, then TrainersAllowed > 0. diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index d1ea51653..e6bafc436 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2527,6 +2527,8 @@ void StartMission(INT8 index) DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, szRebelCommandText[RCT_INSUFFICIENT_FUNDS], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); return; } + + rebelCommandSaveInfo.iSupplies -= cost; // todo do something with agentIndex[index] and missionIndex[index] (rebelCommandSaveInfo.availableMissions[index]) // confirmation popup @@ -2693,7 +2695,7 @@ void StartMission(INT8 index) // actually start the mission //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, MissionHelpers::missionParam); AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60, MissionHelpers::missionParam); // rftr todo: DELETE ME - missionMap[static_cast(evt.missionId)] = MissionHelpers::missionParam; + missionMap.insert(std::make_pair(static_cast(evt.missionId), MissionHelpers::missionParam)); } RenderWebsite(); @@ -4139,12 +4141,26 @@ BOOLEAN CanTrainMilitiaAnywhere() return FALSE; // rftr todo: check bitmask - return TRUE; + const UINT32 param = missionMap[RCAM_TRAIN_MILITIA_ANYWHERE]; + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(param, evt); + + return evt.isSecondEvent; } UINT8 GetMaxTrainersForTrainMilitiaAnywhere() { - return 1; + const UINT32 param = missionMap[RCAM_TRAIN_MILITIA_ANYWHERE]; + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(param, evt); + + if (!evt.isSecondEvent) + return 0; + + if (evt.extraBits == MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING) + return gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching; + + return gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers; } INT16 GetAdditionalDeployRange(const UINT8 insertionCode) @@ -4347,8 +4363,8 @@ void HandleStrategicEvent(const UINT32 eventParam) if (validMission) { - AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, - SerialiseMissionSecondEvent(evt1.sentGenericRebelAgent, evt1.mercProfileId, mission, extraBits)); + const UINT32 activatedMissionParam = SerialiseMissionSecondEvent(evt1.sentGenericRebelAgent, evt1.mercProfileId, mission, extraBits); + AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, activatedMissionParam); if (!evt1.sentGenericRebelAgent) { @@ -4368,9 +4384,9 @@ void HandleStrategicEvent(const UINT32 eventParam) AddCharacterToAnySquad(pSoldier); } } - } - missionMap[mission] = eventParam; + missionMap.insert(std::make_pair(mission, activatedMissionParam)); + } } else { From 0485aa230ef302113190e1684188e78b02be7e97 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 14 Oct 2022 00:56:44 -0700 Subject: [PATCH 05/52] A bit of cleanup --- Strategic/Rebel Command.cpp | 160 ++++++++++++------------------------ 1 file changed, 53 insertions(+), 107 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index e6bafc436..05ae5b0c9 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -1309,7 +1309,6 @@ void RenderHeader(RebelCommandText titleText) // line at the bottom of the header usPosX = WEBSITE_LEFT - 1; usPosY = WEBSITE_TOP + 35; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1422,7 +1421,6 @@ void RenderNationalOverview() // line between incoming supplies and directive usPosX = WEBSITE_LEFT - 1; usPosY += 43; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1488,7 +1486,6 @@ void RenderNationalOverview() // line between directive and militia usPosX = WEBSITE_LEFT - 1; usPosY += 10; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1547,7 +1544,6 @@ void RenderNationalOverview() // draw vertical line usPosX += 75; usPosY = militiaY - 3; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1580,7 +1576,6 @@ void RenderNationalOverview() // draw vertical line usPosX += 75; usPosY = militiaY - 3; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1619,7 +1614,6 @@ void RenderNationalOverview() // line usPosX = WEBSITE_LEFT + 25; usPosY = militiaY + 50; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1640,7 +1634,6 @@ void RenderNationalOverview() // draw vertical line usPosX += 120; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY - 2, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1695,7 +1688,6 @@ void RenderNationalOverview() // line usPosX = WEBSITE_LEFT + 25; usPosY += 30; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + 450, usPosY, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1730,7 +1722,6 @@ void RenderNationalOverview() // draw vertical line usPosX = WEBSITE_LEFT + 130; usPosY -= 12; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 38, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1824,7 +1815,6 @@ void RenderRegionalOverview() // line between region info and admin info usPosX = WEBSITE_LEFT - 1; usPosY += 15; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1874,7 +1864,6 @@ void RenderRegionalOverview() // vertical line between admin team and loyalty usPosX = WEBSITE_LEFT + 105; usPosY += 5; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1917,7 +1906,6 @@ void RenderRegionalOverview() // vertical line between loyalty and max loyalty usPosX = WEBSITE_LEFT + 195; usPosY += 5; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -1960,7 +1948,6 @@ void RenderRegionalOverview() // vertical line between max loyalty usPosX = WEBSITE_LEFT + 325; usPosY += 5; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX, usPosY + 15, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -2046,7 +2033,6 @@ void RenderRegionalOverview() // line between admin info and admin actions usPosX = WEBSITE_LEFT - 1; usPosY += 25; - //DisplaySmallColouredLineWithShadow(usPosX, usPosY, usPosX + WEBSITE_WIDTH, usPosY, FROMRGB(240, 240, 240)); { UINT32 uiDestPitchBYTES; UINT8 *pDestBuf; @@ -2127,8 +2113,6 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) UnLockVideoSurface( FRAME_BUFFER ); // clamp indices - //if (missionIndex[index] < 0) missionIndex[index] = RCAM_NUM_MISSIONS - 1; - //else if (missionIndex[index] >= RCAM_NUM_MISSIONS) missionIndex[index] = 0; // we're reserving an index for the generic rebel agent, so no need to subtract 1 from size here if (agentIndex[index] < 0) agentIndex[index] = static_cast(mercs.size()); else if (agentIndex[index] > static_cast(mercs.size())) agentIndex[index] = 0; @@ -2453,14 +2437,6 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) void RenderMissionOverview() { - // randomised missions - preserved in bitarray (24h refresh if none selected) - // only 1 active mission? allow multiple? - // increase cost based on num active missions? - // need a ui toggle between active missions and mission select - // need to convey that different folks can go on different missions, skills provide different bonuses - // we can probably store a lot of info in the strategic event int64 since we don't need to query it that often - on load, on mission start (send event)/end (receive event) - // 24 hours to find out if success/fail, then hold agent for a few days? - // don't need to save active missions - on load game, check strategic events (I have confirmed that strategic events are loaded before rebelcommandsaveinfo) CHAR16 sText[800]; INT32 btnId; @@ -2665,22 +2641,14 @@ void StartMission(INT8 index) if (!evt.sentGenericRebelAgent) { - //for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) - { - SOLDIERTYPE* pSoldier = MercPtrs[evt.mercProfileId]; - - //if (pSoldier->ubProfile != evt.mercProfileId) - // continue; - - TakeSoldierOutOfVehicle(pSoldier); - RemoveCharacterFromSquads(pSoldier); - pSoldier->bSectorZ += REBEL_COMMAND_Z_OFFSET; - pSoldier->bBleeding = 0; - SetTimeOfAssignmentChangeForMerc(pSoldier); - ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); - - //break; - } + SOLDIERTYPE* pSoldier = MercPtrs[evt.mercProfileId]; + + TakeSoldierOutOfVehicle(pSoldier); + RemoveCharacterFromSquads(pSoldier); + pSoldier->bSectorZ += REBEL_COMMAND_Z_OFFSET; + pSoldier->bBleeding = 0; + SetTimeOfAssignmentChangeForMerc(pSoldier); + ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); } for (INT8 i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) @@ -3783,32 +3751,17 @@ BOOLEAN Load(HWFILE file) Init(); } - // rftr TEST it works hooray, assuming I don't change the layout of the bitflag - //const UINT32 param1 = SerialiseMissionFirstEvent(FALSE, 8, RCAM_DEEP_DEPLOYMENT, 200, 0x0F); - //const UINT32 param2 = SerialiseMissionSecondEvent(FALSE, 10, RCAM_GET_ENEMY_MOVEMENT_TARGETS, 0xFF); - //MissionFirstEvent evt1; - //MissionSecondEvent evt2; - //DeserialiseMissionFirstEvent(param1, evt1); - //DeserialiseMissionSecondEvent(param2, evt2); - // go through every strategic event to find active agent missions std::vector> missions = GetAllStrategicEventsOfType(EVENT_REBELCOMMAND); missionMap.clear(); // example is EVENT_BLOODCAT_ATTACK for (std::vector>::iterator it = missions.begin(); it != missions.end(); ++it) { - // FIRST EVENT EXAMPLE - //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, my32bitparam); - // SECOND EVENT EXAMPLE - //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * durationInHours, my32bitparam); - //const UINT32 first = it->first; // timestamp - when this event will be fired - //const UINT32 second = it->second; // uiParam - MissionFirstEvent evt1; DeserialiseMissionFirstEvent(it->second, evt1); if (evt1.isFirstEvent) { - missionMap[static_cast(evt1.missionId)] = it->second; + missionMap.insert(std::make_pair(static_cast(evt1.missionId), it->second)); } MissionSecondEvent evt2; @@ -3816,7 +3769,7 @@ BOOLEAN Load(HWFILE file) if (evt2.isSecondEvent) { - missionMap[static_cast(evt2.missionId)] = it->second; + missionMap.insert(std::make_pair(static_cast(evt2.missionId), it->second)); } } return TRUE; @@ -4140,27 +4093,35 @@ BOOLEAN CanTrainMilitiaAnywhere() if (!gGameExternalOptions.fRebelCommandEnabled) return FALSE; - // rftr todo: check bitmask - const UINT32 param = missionMap[RCAM_TRAIN_MILITIA_ANYWHERE]; + const std::unordered_map::iterator iter = missionMap.find(RCAM_TRAIN_MILITIA_ANYWHERE); + + if (iter == missionMap.end()) + return FALSE; + MissionSecondEvent evt; - DeserialiseMissionSecondEvent(param, evt); + DeserialiseMissionSecondEvent(iter->second, evt); return evt.isSecondEvent; } UINT8 GetMaxTrainersForTrainMilitiaAnywhere() { - const UINT32 param = missionMap[RCAM_TRAIN_MILITIA_ANYWHERE]; + const std::unordered_map::iterator iter = missionMap.find(RCAM_TRAIN_MILITIA_ANYWHERE); + + if (iter == missionMap.end()) + return FALSE; + MissionSecondEvent evt; - DeserialiseMissionSecondEvent(param, evt); + DeserialiseMissionSecondEvent(iter->second, evt); if (!evt.isSecondEvent) return 0; - if (evt.extraBits == MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING) - return gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching; - - return gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers; + switch (evt.extraBits) + { + case MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING: return gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching; + default: return gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers; + } } INT16 GetAdditionalDeployRange(const UINT8 insertionCode) @@ -4175,18 +4136,18 @@ INT16 GetAdditionalDeployRange(const UINT8 insertionCode) // rftr todo: check bitmask - switch (insertionCode) - { - case INSERTION_CODE_NORTH: - case INSERTION_CODE_SOUTH: - { - INT16 range = 0; + INT16 range = 0; - MissionSecondEvent evt; - DeserialiseMissionSecondEvent(iter->second, evt); + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); - // we only get a range bonus if the mission is active! - if (evt.isSecondEvent) + // we only get a range bonus if the mission is active! + if (evt.isSecondEvent) + { + switch (insertionCode) + { + case INSERTION_CODE_NORTH: + case INSERTION_CODE_SOUTH: { range = gRebelCommandSettings.iDeepDeploymentRangeNS; @@ -4200,21 +4161,12 @@ INT16 GetAdditionalDeployRange(const UINT8 insertionCode) default: break; } - } - - return range; - } - - case INSERTION_CODE_WEST: - case INSERTION_CODE_EAST: - { - INT16 range = 0; - MissionSecondEvent evt; - DeserialiseMissionSecondEvent(iter->second, evt); + return range; + } - // we only get a range bonus if the mission is active! - if (evt.isSecondEvent) + case INSERTION_CODE_WEST: + case INSERTION_CODE_EAST: { range = gRebelCommandSettings.iDeepDeploymentRangeEW; @@ -4227,10 +4179,10 @@ INT16 GetAdditionalDeployRange(const UINT8 insertionCode) default: break; } - } - return range; - } + return range; + } + } } return 0; @@ -4368,21 +4320,15 @@ void HandleStrategicEvent(const UINT32 eventParam) if (!evt1.sentGenericRebelAgent) { - //for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) - { - SOLDIERTYPE* pSoldier = MercPtrs[evt1.mercProfileId]; - - //if (pSoldier->ubProfile != evt1.mercProfileId) - // continue; - - // rftr todo: tell the player that the mission has started. popupbox or screenmsg? - // rftr todo: mission successful! give some experience pts - pSoldier->bSectorZ -= REBEL_COMMAND_Z_OFFSET; - pSoldier->ubInsertionDirection = DIRECTION_IRRELEVANT; - pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CENTER; - AssignmentDone(pSoldier, TRUE, FALSE); - AddCharacterToAnySquad(pSoldier); - } + SOLDIERTYPE* pSoldier = MercPtrs[evt1.mercProfileId]; + + // rftr todo: tell the player that the mission has started. popupbox or screenmsg? + // rftr todo: mission successful! give some experience pts + pSoldier->bSectorZ -= REBEL_COMMAND_Z_OFFSET; + pSoldier->ubInsertionDirection = DIRECTION_IRRELEVANT; + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CENTER; + AssignmentDone(pSoldier, TRUE, FALSE); + AddCharacterToAnySquad(pSoldier); } missionMap.insert(std::make_pair(mission, activatedMissionParam)); From c8465baee2c4ef438944190dbfef1879e5826e30 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 14 Oct 2022 01:02:46 -0700 Subject: [PATCH 06/52] Add POW/MiniEvent/RebelCommand assignment check for StartMission --- Strategic/Rebel Command.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 05ae5b0c9..2af9520f8 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2408,6 +2408,15 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) { canStartMission = FALSE; swprintf(sText, L"Agent not in loyal town"); + } + else if (mercs[agentIndex[index]]->bAssignment == ASSIGNMENT_POW || mercs[agentIndex[index]]->bAssignment == ASSIGNMENT_MINIEVENT || mercs[agentIndex[index]]->bAssignment == ASSIGNMENT_REBELCOMMAND) + { + canStartMission = FALSE; + swprintf(sText, L"Agent unavailable"); + } + + if (!canStartMission) + { DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); } } From 2e17b4ff14c2d1fe93d91042d879c0ea767c7fd2 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 14 Oct 2022 17:31:07 -0700 Subject: [PATCH 07/52] Show "No mission available" after starting a mission Consume supplies after mission starts --- Strategic/Rebel Command.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 2af9520f8..9a772a1cd 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2118,6 +2118,12 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) else if (agentIndex[index] > static_cast(mercs.size())) agentIndex[index] = 0; // rftr todo: handle RCAM_NONE (ie, mission prep in progress!) + if (rebelCommandSaveInfo.availableMissions[index] == RCAM_NONE) + { + swprintf(sText, L"No mission available"); + DrawTextToScreen(sText, x, y+155, 230, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + return FALSE; + } // draw mission title switch (rebelCommandSaveInfo.availableMissions[index]) @@ -2513,8 +2519,6 @@ void StartMission(INT8 index) return; } - rebelCommandSaveInfo.iSupplies -= cost; - // todo do something with agentIndex[index] and missionIndex[index] (rebelCommandSaveInfo.availableMissions[index]) // confirmation popup std::vector mercs; @@ -2673,9 +2677,12 @@ void StartMission(INT8 index) //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, MissionHelpers::missionParam); AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60, MissionHelpers::missionParam); // rftr todo: DELETE ME missionMap.insert(std::make_pair(static_cast(evt.missionId), MissionHelpers::missionParam)); + + rebelCommandSaveInfo.iSupplies -= GetMissionCost(); } - RenderWebsite(); + // update the mission list to show that we've started + redraw = TRUE; }); } // end website From b0b26d8ef2b72ecc05a9a45ce9cfec4975dbdcf9 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 14 Oct 2022 23:43:43 -0700 Subject: [PATCH 08/52] Fix being able to assign Radio Scan in specific cases --- Strategic/Assignments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 0afaa74dc..027d5afc1 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -10724,7 +10724,7 @@ void HandleShadingOfLinesForAssignmentMenus( void ) } // radio scan - if( pSoldier->CanUseRadio() ) + if( BasicCanCharacterAssignment( pSoldier, TRUE ) && pSoldier->CanUseRadio() ) { // unshade line UnShadeStringInBox( ghAssignmentBox, ASSIGN_MENU_RADIO_SCAN ); From e9c4b09de5e5e814bcd5b6eb23ea85bb39f475db Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sat, 15 Oct 2022 00:05:52 -0700 Subject: [PATCH 09/52] Manually align mission prep completion to top of the hour (xx:00) --- Strategic/Rebel Command.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 9a772a1cd..21a088bd0 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2673,9 +2673,10 @@ void StartMission(INT8 index) } } - // actually start the mission - //AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * 24, MissionHelpers::missionParam); - AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60, MissionHelpers::missionParam); // rftr todo: DELETE ME + // queue up the mission start event. make sure we use the top of the hour because I'm lazy and we're handling the assignment here instead of Assignments.cpp + const UINT32 time = GetWorldTotalMin(); + //AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60 * 24, MissionHelpers::missionParam); + AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60, MissionHelpers::missionParam); // rftr todo: DELETE ME missionMap.insert(std::make_pair(static_cast(evt.missionId), MissionHelpers::missionParam)); rebelCommandSaveInfo.iSupplies -= GetMissionCost(); From 2b88fac8701ae708989ae9a3a0fd463bd6f77dc4 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sun, 16 Oct 2022 20:43:21 -0700 Subject: [PATCH 10/52] Award exp to mercs who prep a mission, regardless of whether they succeed or not --- Strategic/Rebel Command.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 21a088bd0..238a2610d 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -4339,8 +4339,9 @@ void HandleStrategicEvent(const UINT32 eventParam) { SOLDIERTYPE* pSoldier = MercPtrs[evt1.mercProfileId]; - // rftr todo: tell the player that the mission has started. popupbox or screenmsg? - // rftr todo: mission successful! give some experience pts + // mission successful! give some experience pts + StatChange(pSoldier, LDRAMT, 20, FROM_SUCCESS); + StatChange(pSoldier, WISDOMAMT, 15, FROM_SUCCESS); pSoldier->bSectorZ -= REBEL_COMMAND_Z_OFFSET; pSoldier->ubInsertionDirection = DIRECTION_IRRELEVANT; pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CENTER; @@ -4348,12 +4349,20 @@ void HandleStrategicEvent(const UINT32 eventParam) AddCharacterToAnySquad(pSoldier); } + // rftr todo: tell the player that the mission has started. popupbox or screenmsg? missionMap.insert(std::make_pair(mission, activatedMissionParam)); } } else { // rftr todo: tell the player that the mission prep failed. some popup box blurb or somesuch. + if (!evt1.sentGenericRebelAgent) + { + // mission failed! we tried, have some pity exp + SOLDIERTYPE* pSoldier = MercPtrs[evt1.mercProfileId]; + StatChange(pSoldier, LDRAMT, 20, FROM_FAILURE); + StatChange(pSoldier, WISDOMAMT, 15, FROM_FAILURE); + } } } else if (evt2.isSecondEvent) From 983aa24b1b94d0f1b8783f05182ca6fc468ec27e Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 17 Oct 2022 00:31:07 -0700 Subject: [PATCH 11/52] Add settings variable for mission refresh time Fix nullptr derefence when starting a mission with a generic agent Limit missions to one per batch Add popup box and screenmsg when a mission activates, fails to activates, and expires --- GameSettings.cpp | 1 + GameSettings.h | 1 + Strategic/Rebel Command.cpp | 118 +++++++++++++++++++++++------------- Utils/_EnglishText.cpp | 2 +- 4 files changed, 78 insertions(+), 44 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index f1251c61c..6af2140e4 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4158,6 +4158,7 @@ void LoadRebelCommandSettings() gRebelCommandSettings.iFortificationsBonus = iniReader.ReadInteger("Rebel Command Settings", "FORTIFICATIONS_BONUS", 10, 0, 100); // agent missions + gRebelCommandSettings.iMissionRefreshTimeDays = iniReader.ReadInteger("Rebel Command Settings", "MISSION_REFRESH_TIME_DAYS", 2, 1, 7); gRebelCommandSettings.iMinLoyaltyForMission = iniReader.ReadInteger("Rebel Command Settings", "MIN_LOYALTY_FOR_MISSION", 51, 0, 100); gRebelCommandSettings.iDeepDeploymentSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_SUCCESS_CHANCE", 50, 0, 100); diff --git a/GameSettings.h b/GameSettings.h index f28fdd7c8..e80b41894 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1843,6 +1843,7 @@ typedef struct INT16 iFortificationsBonus; // agent missions + INT8 iMissionRefreshTimeDays; INT8 iMinLoyaltyForMission; INT8 iDeepDeploymentSuccessChance; diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 238a2610d..02f94bd65 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -173,6 +173,9 @@ void GetMissionInfo(RebelCommandAgentMissions mission, const MERCPROFILESTRUCT* intModifierSkill = 0; extraBits = 0; + if (merc == nullptr) + return; + if (mission == RCAM_NONE) return; @@ -2120,7 +2123,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) // rftr todo: handle RCAM_NONE (ie, mission prep in progress!) if (rebelCommandSaveInfo.availableMissions[index] == RCAM_NONE) { - swprintf(sText, L"No mission available"); + // we shouldn't even reach this point, but leaving this here for safety + swprintf(sText, L"Mission preparations in progress."); DrawTextToScreen(sText, x, y+155, 230, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); return FALSE; } @@ -2492,9 +2496,23 @@ void RenderMissionOverview() switch (missionOverviewSubview) { case MOS_MISSION_LIST: - for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + if (rebelCommandSaveInfo.availableMissions[0] == RCAM_NONE) + { + UINT32 nextMissionAvailableDay = GetWorldDay(); + const INT8 interval = gRebelCommandSettings.iMissionRefreshTimeDays; + nextMissionAvailableDay += (interval - (nextMissionAvailableDay % interval)); + + swprintf(sText, L"Mission preparations in progress."); + DrawTextToScreen(sText, WEBSITE_LEFT + 15, WEBSITE_TOP + 155, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + swprintf(sText, L"New missions will be available on Day %d at 00:00.", nextMissionAvailableDay); + DrawTextToScreen(sText, WEBSITE_LEFT + 15, WEBSITE_TOP + 175, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + } + else { - SetupMissionAgentBox(WEBSITE_LEFT + 15 + 240 * i, WEBSITE_TOP + 65, i); + for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + SetupMissionAgentBox(WEBSITE_LEFT + 15 + 240 * i, WEBSITE_TOP + 65, i); + } } break; @@ -2507,7 +2525,8 @@ void RenderMissionOverview() } // "new missions every X hours" text - DrawTextToScreen(szRebelCommandAgentMissionsText[RCAMT_NEW_MISSIONS_AVAILABLE_TIME], WEBSITE_LEFT + 22, WEBSITE_TOP + WEBSITE_HEIGHT - 14, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_NEW_MISSIONS_AVAILABLE_TIME], gRebelCommandSettings.iMissionRefreshTimeDays * 24); + DrawTextToScreen(sText, WEBSITE_LEFT + 22, WEBSITE_TOP + WEBSITE_HEIGHT - 14, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } void StartMission(INT8 index) @@ -2534,7 +2553,7 @@ void StartMission(INT8 index) } } - const MERCPROFILESTRUCT merc = gMercProfiles[mercs[agentIndex[index]]->ubProfile]; + const MERCPROFILESTRUCT* merc = agentIndex[index] == mercs.size() ? nullptr : &gMercProfiles[mercs[agentIndex[index]]->ubProfile]; CHAR16 text[400]; RebelCommandAgentMissionsText missionTitle; INT8 missionSuccessChance; @@ -2547,7 +2566,7 @@ void StartMission(INT8 index) int intSkill; UINT16 extraBits; - MissionHelpers::GetMissionInfo(static_cast(rebelCommandSaveInfo.availableMissions[index]), &merc, durationBonus, floatModifier, intModifier, durSkill, floatSkill, intSkill, extraBits); + MissionHelpers::GetMissionInfo(static_cast(rebelCommandSaveInfo.availableMissions[index]), merc, durationBonus, floatModifier, intModifier, durSkill, floatSkill, intSkill, extraBits); switch (rebelCommandSaveInfo.availableMissions[index]) { case RCAM_DEEP_DEPLOYMENT: @@ -2617,7 +2636,7 @@ void StartMission(INT8 index) default: break; } - missionSuccessChance += GetMissionSuccessChanceBonus(&merc); + missionSuccessChance += GetMissionSuccessChanceBonus(merc); if (Random(100) > static_cast(missionSuccessChance)) { @@ -2640,10 +2659,10 @@ void StartMission(INT8 index) else { MissionHelpers::missionParam = SerialiseMissionFirstEvent(FALSE, agentIndex[index], static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, static_cast(extraBits)); - if (merc.bSex == MALE) - swprintf(text, L"%s Send %s to prepare this mission? He will return in 24 hours.", text, merc.zNickname); + if (merc->bSex == MALE) + swprintf(text, L"%s Send %s to prepare this mission? He will return in 24 hours.", text, merc->zNickname); else - swprintf(text, L"%s Send %s to prepare this mission? She will return in 24 hours.", text, merc.zNickname); + swprintf(text, L"%s Send %s to prepare this mission? She will return in 24 hours.", text, merc->zNickname); } DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, text, LAPTOP_SCREEN, MSG_BOX_FLAG_YESNO, [](UINT8 exitValue) { @@ -2664,13 +2683,10 @@ void StartMission(INT8 index) ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); } + // disable missions until next refresh for (INT8 i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) { - if (evt.missionId == rebelCommandSaveInfo.availableMissions[i]) - { - rebelCommandSaveInfo.availableMissions[i] = RCAM_NONE; - break; - } + rebelCommandSaveInfo.availableMissions[i] = RCAM_NONE; } // queue up the mission start event. make sure we use the top of the hour because I'm lazy and we're handling the assignment here instead of Assignments.cpp @@ -3595,41 +3611,43 @@ void DailyUpdate() // update missions // rftr todo: test me - // rftr todo: don't do this every day! - std::unordered_set validMissions; - for (int i = 0; i < RCAM_NUM_MISSIONS; ++i) - { - validMissions.insert(static_cast(i)); - } - - for (const auto& pair : missionMap) - { - const RebelCommandAgentMissions mission = pair.first; - validMissions.erase(mission); - } - - if (validMissions.size() >= NUM_ARC_AGENT_SLOTS) + if (GetWorldDay() % gRebelCommandSettings.iMissionRefreshTimeDays == 0) { - for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + std::unordered_set validMissions; + for (int i = 0; i < RCAM_NUM_MISSIONS; ++i) { - const INT8 mission = static_cast(Random(validMissions.size())); - rebelCommandSaveInfo.availableMissions[i] = mission; - validMissions.erase(static_cast(mission)); + validMissions.insert(static_cast(i)); } - } - else - { - int idx = 0; - for (auto iter = validMissions.cbegin(); iter != validMissions.cend(); ++iter) + + for (const auto& pair : missionMap) { - rebelCommandSaveInfo.availableMissions[idx] = *iter; - idx++; + const RebelCommandAgentMissions mission = pair.first; + validMissions.erase(mission); } - while (idx < NUM_ARC_AGENT_SLOTS) + if (validMissions.size() >= NUM_ARC_AGENT_SLOTS) + { + for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + const INT8 mission = static_cast(Random(validMissions.size())); + rebelCommandSaveInfo.availableMissions[i] = mission; + validMissions.erase(static_cast(mission)); + } + } + else // 1 mission available { - rebelCommandSaveInfo.availableMissions[idx] = RCAM_NONE; - idx++; + int idx = 0; + for (auto iter = validMissions.cbegin(); iter != validMissions.cend(); ++iter) + { + rebelCommandSaveInfo.availableMissions[idx] = *iter; + idx++; + } + + while (idx < NUM_ARC_AGENT_SLOTS) + { + rebelCommandSaveInfo.availableMissions[idx] = RCAM_NONE; + idx++; + } } } } @@ -4284,6 +4302,8 @@ void HandleStrategicEvent(const UINT32 eventParam) MissionSecondEvent evt2; DeserialiseMissionFirstEvent(eventParam, evt1); DeserialiseMissionSecondEvent(eventParam, evt2); + CHAR16 msgBoxText[200]; + CHAR16 screenMsgText[200]; if (evt1.isFirstEvent) { @@ -4351,6 +4371,9 @@ void HandleStrategicEvent(const UINT32 eventParam) // rftr todo: tell the player that the mission has started. popupbox or screenmsg? missionMap.insert(std::make_pair(mission, activatedMissionParam)); + swprintf(msgBoxText, L"Mission prep success! %s", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + swprintf(screenMsgText, L"Mission \"%s\" is now in effect.", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, screenMsgText); } } else @@ -4363,13 +4386,22 @@ void HandleStrategicEvent(const UINT32 eventParam) StatChange(pSoldier, LDRAMT, 20, FROM_FAILURE); StatChange(pSoldier, WISDOMAMT, 15, FROM_FAILURE); } + + swprintf(msgBoxText, L"Mission prep failed... %s", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + swprintf(screenMsgText, L"Preparations for mission \"%s\" failed.", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); } } else if (evt2.isSecondEvent) { // mission duration is over. deactivate the mission missionMap.erase(static_cast(evt2.missionId)); + swprintf(msgBoxText, L"Mission duration complete! %s", szRebelCommandAgentMissionsText[2 + evt2.missionId * 2]); + swprintf(screenMsgText, L"Mission \"%s\" has expired and is no longer in effect.", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); } + + DoMessageBox(MSG_BOX_BASIC_STYLE, msgBoxText, guiCurrentScreen, MSG_BOX_FLAG_OK, NULL, NULL); } BOOLEAN ShowEnemyMovementTargets() diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index e4f8d35a2..e1efffb26 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -12036,7 +12036,7 @@ STR16 szRebelCommandDirectivesText[] = STR16 szRebelCommandAgentMissionsText[] = { - L"New missions will be available every 48 hours.", + L"New missions will be available every %d hours.", L"A mission is currently active.", L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", From d9697e900b37a80a04119fc299a53bba1f0239fe Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 17 Oct 2022 00:39:32 -0700 Subject: [PATCH 12/52] Add merc contract check to StartMission Fail mission prep if the agent is no longer in the player's employ --- Strategic/Rebel Command.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 02f94bd65..b1c4b32c3 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2413,6 +2413,9 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) { const UINT8 townId = GetTownIdForSector(mercs[agentIndex[index]]->sSectorX, mercs[agentIndex[index]]->sSectorY); const UINT8 townLoyalty = GetRegionLoyalty(townId); + const INT32 endTime = mercs[agentIndex[index]]->iEndofContractTime; + const INT32 worldMin = GetWorldTotalMin(); + const INT32 remaining = endTime - worldMin; if (townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission) { @@ -2424,6 +2427,11 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) canStartMission = FALSE; swprintf(sText, L"Agent unavailable"); } + else if (mercs[agentIndex[index]]->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC && remaining < 24 * 60) + { + canStartMission = FALSE; + swprintf(sText, L"Agent contract expiring"); + } if (!canStartMission) { @@ -4310,13 +4318,27 @@ void HandleStrategicEvent(const UINT32 eventParam) // mission prep is over. see if we can activate the mission missionMap.erase(static_cast(evt1.missionId)); - // rftr todo: end the merc's assignment (like mini event adventures) - if (evt1.isMissionSuccess) { const RebelCommandAgentMissions mission = static_cast(evt1.missionId); const MERCPROFILESTRUCT merc = gMercProfiles[evt1.mercProfileId]; + // make sure the merc's still on our team + BOOLEAN foundMerc = FALSE; + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + const SOLDIERTYPE* pSoldier = MercPtrs[i]; + + if (pSoldier->ubProfile == evt1.mercProfileId) + { + foundMerc = TRUE; + break; + } + } + + if (!foundMerc) + goto MissionFailed_MercNoLongerOnTeam; + // what mission did we do? apply bonuses here, and don't forget to check them later when checking to see if a mission bonus should be applied UINT32 durationBonus = 0; int durationBonusSkill = 0; @@ -4387,6 +4409,7 @@ void HandleStrategicEvent(const UINT32 eventParam) StatChange(pSoldier, WISDOMAMT, 15, FROM_FAILURE); } + MissionFailed_MercNoLongerOnTeam: swprintf(msgBoxText, L"Mission prep failed... %s", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); swprintf(screenMsgText, L"Preparations for mission \"%s\" failed.", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); From 61858e472a02245d0b34a7b9765a79c7b4cdbca5 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 17 Oct 2022 13:56:45 -0700 Subject: [PATCH 13/52] Move some text around --- Strategic/Rebel Command.cpp | 18 ++++++++---------- Utils/_EnglishText.cpp | 3 +-- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index b1c4b32c3..536deafe1 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -292,6 +292,7 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_PREV_ARROW, RCT_NEXT_ARROW, RCT_CONFIRM_CHANGE_ADMIN_ACTION_PROMPT, + RCT_NEW_MISSIONS_AVAILABLE_TIME, }; enum RebelCommandHelpText // keep this synced with szRebelCommandHelpText in the text files @@ -326,9 +327,6 @@ enum RebelCommandDirectivesText // keep this synced with szRebelCommandDirective enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentMissionsText in the text files { - //RCAMT_NOTIFY_MISSIONS_AVAILABLE, - RCAMT_NEW_MISSIONS_AVAILABLE_TIME, - RCAMT_MISSION_ACTIVE, MISSION_TEXT(DEEP_DEPLOYMENT) MISSION_TEXT(GET_ENEMY_MOVEMENT_TARGETS) MISSION_TEXT(IMPROVE_LOCAL_SHOPS) @@ -2533,7 +2531,7 @@ void RenderMissionOverview() } // "new missions every X hours" text - swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_NEW_MISSIONS_AVAILABLE_TIME], gRebelCommandSettings.iMissionRefreshTimeDays * 24); + swprintf(sText, szRebelCommandText[RCT_NEW_MISSIONS_AVAILABLE_TIME], gRebelCommandSettings.iMissionRefreshTimeDays * 24); DrawTextToScreen(sText, WEBSITE_LEFT + 22, WEBSITE_TOP + WEBSITE_HEIGHT - 14, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } @@ -4393,8 +4391,8 @@ void HandleStrategicEvent(const UINT32 eventParam) // rftr todo: tell the player that the mission has started. popupbox or screenmsg? missionMap.insert(std::make_pair(mission, activatedMissionParam)); - swprintf(msgBoxText, L"Mission prep success! %s", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); - swprintf(screenMsgText, L"Mission \"%s\" is now in effect.", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + swprintf(msgBoxText, L"Mission prep success! %s", szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(screenMsgText, L"Mission \"%s\" is now in effect.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, screenMsgText); } } @@ -4410,8 +4408,8 @@ void HandleStrategicEvent(const UINT32 eventParam) } MissionFailed_MercNoLongerOnTeam: - swprintf(msgBoxText, L"Mission prep failed... %s", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); - swprintf(screenMsgText, L"Preparations for mission \"%s\" failed.", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + swprintf(msgBoxText, L"Mission prep failed... %s", szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(screenMsgText, L"Preparations for mission \"%s\" failed.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); } } @@ -4419,8 +4417,8 @@ void HandleStrategicEvent(const UINT32 eventParam) { // mission duration is over. deactivate the mission missionMap.erase(static_cast(evt2.missionId)); - swprintf(msgBoxText, L"Mission duration complete! %s", szRebelCommandAgentMissionsText[2 + evt2.missionId * 2]); - swprintf(screenMsgText, L"Mission \"%s\" has expired and is no longer in effect.", szRebelCommandAgentMissionsText[2 + evt1.missionId * 2]); + swprintf(msgBoxText, L"Mission duration complete! %s", szRebelCommandAgentMissionsText[evt2.missionId * 2]); + swprintf(screenMsgText, L"Mission \"%s\" has expired and is no longer in effect.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); } diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index e1efffb26..11da10987 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11932,6 +11932,7 @@ STR16 szRebelCommandText[] = L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"New missions will be available every %d hours.", }; STR16 szRebelCommandHelpText[] = @@ -12036,8 +12037,6 @@ STR16 szRebelCommandDirectivesText[] = STR16 szRebelCommandAgentMissionsText[] = { - L"New missions will be available every %d hours.", - L"A mission is currently active.", L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", L"Strategic Intel", From 3724de92991cb800cb7be0cfaf2be40fa9563f98 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 17 Oct 2022 14:38:51 -0700 Subject: [PATCH 14/52] Properly reset merc assignment when mission prep completes, regardless of success or failure Fix use of merc profile id in first mission event param --- Strategic/Rebel Command.cpp | 107 +++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 37 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 536deafe1..d4ecf3489 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2664,7 +2664,7 @@ void StartMission(INT8 index) } else { - MissionHelpers::missionParam = SerialiseMissionFirstEvent(FALSE, agentIndex[index], static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, static_cast(extraBits)); + MissionHelpers::missionParam = SerialiseMissionFirstEvent(FALSE, mercs[agentIndex[index]]->ubProfile, static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, static_cast(extraBits)); if (merc->bSex == MALE) swprintf(text, L"%s Send %s to prepare this mission? He will return in 24 hours.", text, merc->zNickname); else @@ -2679,14 +2679,20 @@ void StartMission(INT8 index) if (!evt.sentGenericRebelAgent) { - SOLDIERTYPE* pSoldier = MercPtrs[evt.mercProfileId]; - - TakeSoldierOutOfVehicle(pSoldier); - RemoveCharacterFromSquads(pSoldier); - pSoldier->bSectorZ += REBEL_COMMAND_Z_OFFSET; - pSoldier->bBleeding = 0; - SetTimeOfAssignmentChangeForMerc(pSoldier); - ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[i]; + if (pSoldier->ubProfile == evt.mercProfileId) + { + TakeSoldierOutOfVehicle(pSoldier); + RemoveCharacterFromSquads(pSoldier); + pSoldier->bSectorZ += REBEL_COMMAND_Z_OFFSET; + pSoldier->bBleeding = 0; + SetTimeOfAssignmentChangeForMerc(pSoldier); + ChangeSoldiersAssignment(pSoldier, ASSIGNMENT_REBELCOMMAND); + break; + } + } } // disable missions until next refresh @@ -4316,24 +4322,24 @@ void HandleStrategicEvent(const UINT32 eventParam) // mission prep is over. see if we can activate the mission missionMap.erase(static_cast(evt1.missionId)); + // make sure the merc's still on our team + BOOLEAN foundMerc = FALSE; + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + const SOLDIERTYPE* pSoldier = MercPtrs[i]; + + if (pSoldier->ubProfile == evt1.mercProfileId && pSoldier->bActive) + { + foundMerc = TRUE; + break; + } + } + if (evt1.isMissionSuccess) { const RebelCommandAgentMissions mission = static_cast(evt1.missionId); const MERCPROFILESTRUCT merc = gMercProfiles[evt1.mercProfileId]; - // make sure the merc's still on our team - BOOLEAN foundMerc = FALSE; - for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) - { - const SOLDIERTYPE* pSoldier = MercPtrs[i]; - - if (pSoldier->ubProfile == evt1.mercProfileId) - { - foundMerc = TRUE; - break; - } - } - if (!foundMerc) goto MissionFailed_MercNoLongerOnTeam; @@ -4377,16 +4383,17 @@ void HandleStrategicEvent(const UINT32 eventParam) if (!evt1.sentGenericRebelAgent) { - SOLDIERTYPE* pSoldier = MercPtrs[evt1.mercProfileId]; - - // mission successful! give some experience pts - StatChange(pSoldier, LDRAMT, 20, FROM_SUCCESS); - StatChange(pSoldier, WISDOMAMT, 15, FROM_SUCCESS); - pSoldier->bSectorZ -= REBEL_COMMAND_Z_OFFSET; - pSoldier->ubInsertionDirection = DIRECTION_IRRELEVANT; - pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CENTER; - AssignmentDone(pSoldier, TRUE, FALSE); - AddCharacterToAnySquad(pSoldier); + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[i]; + if (pSoldier->ubProfile == evt1.mercProfileId) + { + // mission successful! give some experience pts + StatChange(pSoldier, LDRAMT, 20, FROM_SUCCESS); + StatChange(pSoldier, WISDOMAMT, 15, FROM_SUCCESS); + break; + } + } } // rftr todo: tell the player that the mission has started. popupbox or screenmsg? @@ -4399,12 +4406,19 @@ void HandleStrategicEvent(const UINT32 eventParam) else { // rftr todo: tell the player that the mission prep failed. some popup box blurb or somesuch. - if (!evt1.sentGenericRebelAgent) + if (!evt1.sentGenericRebelAgent && foundMerc) { - // mission failed! we tried, have some pity exp - SOLDIERTYPE* pSoldier = MercPtrs[evt1.mercProfileId]; - StatChange(pSoldier, LDRAMT, 20, FROM_FAILURE); - StatChange(pSoldier, WISDOMAMT, 15, FROM_FAILURE); + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[i]; + if (pSoldier->ubProfile == evt1.mercProfileId) + { + // mission failed! we tried, give some pity exp + StatChange(pSoldier, LDRAMT, 20, FROM_FAILURE); + StatChange(pSoldier, WISDOMAMT, 15, FROM_FAILURE); + break; + } + } } MissionFailed_MercNoLongerOnTeam: @@ -4412,6 +4426,25 @@ void HandleStrategicEvent(const UINT32 eventParam) swprintf(screenMsgText, L"Preparations for mission \"%s\" failed.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); } + + if (!evt1.sentGenericRebelAgent && foundMerc) + { + for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) + { + SOLDIERTYPE* pSoldier = MercPtrs[i]; + if (pSoldier->ubProfile == evt1.mercProfileId) + { + // merc ready for reassignment + pSoldier->bSectorZ -= REBEL_COMMAND_Z_OFFSET; + pSoldier->ubInsertionDirection = DIRECTION_IRRELEVANT; + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CENTER; + AssignmentDone(pSoldier, TRUE, FALSE); + AddCharacterToAnySquad(pSoldier); + break; + } + } + + } } else if (evt2.isSecondEvent) { From 572933e359015ff421e80dc9abb8a1c0ad7c9e14 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 17 Oct 2022 19:37:12 -0700 Subject: [PATCH 15/52] Display missions, both active and under preparation --- Strategic/Rebel Command.cpp | 59 +++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index d4ecf3489..8f371ba07 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2292,7 +2292,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) // draw agent bonus text UINT32 durationBonus = 0; int durationBonusSkill = 0; - std::vector agentBonusText; + std::vector agentBonusText; if (agentIndex[index] < static_cast(mercs.size())) { const MERCPROFILESTRUCT merc = gMercProfiles[mercs[agentIndex[index]]->ubProfile]; @@ -2400,7 +2400,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) for (UINT8 i = 0; i < agentBonusText.size(); ++i) { // the percent sign here is a hack to get it to display properly for string that need a percent sign - swprintf(sText, agentBonusText[i], L"%%"); + swprintf(sText, agentBonusText[i].c_str(), L"%%"); DrawTextToScreen(sText, x+10, y+150+54+20+2+11*(i+1), 0, FONT10ARIAL, FONT_GREEN, FONT_MCOLOR_BLACK, FALSE, 0); } } @@ -2523,10 +2523,57 @@ void RenderMissionOverview() break; case MOS_ACTIVE_MISSION_EFFECTS: - // rftr todo: run through active mission list (missionMap) and show a one-line description for each. - // need a scroll or pagination if several missions active - // otherwise, no active effects - DrawTextToScreen(L"No active missions.", WEBSITE_LEFT + 25, WEBSITE_TOP + 75, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + { + DrawTextToScreen(L"Active missions:", WEBSITE_LEFT + 25, WEBSITE_TOP + 75, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + if (missionMap.size() == 0) + { + DrawTextToScreen(L"None", WEBSITE_LEFT + 35, WEBSITE_TOP + 90, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + } + else + { + // rftr todo: run through active mission list (missionMap) and show a one-line description for each. + std::vector evt1Strings; + std::vector evt2Strings; + std::vector> missions = GetAllStrategicEventsOfType(EVENT_REBELCOMMAND); + for (std::vector>::iterator it = missions.begin(); it != missions.end(); ++it) + { + const UINT32 eventTime = it->first; + const UINT32 day = eventTime / 60 / 60 / 24; + const UINT32 hour = (eventTime % (24 * 60 * 60)) / 60 / 60; + const UINT32 minute = (eventTime % (24 * 60 * 60)) % (60 * 60); + MissionFirstEvent evt1; + MissionSecondEvent evt2; + DeserialiseMissionFirstEvent(it->second, evt1); + DeserialiseMissionSecondEvent(it->second, evt2); + + if (evt1.isFirstEvent) + { + CHAR16 prepText[200]; + swprintf(prepText, L"%s - Preparing - Ready on Day %d, %02d:%02d", szRebelCommandAgentMissionsText[evt1.missionId * 2], day, hour, minute); + evt1Strings.push_back(prepText); + } + else if (evt2.isSecondEvent) + { + CHAR16 missionText[200]; + swprintf(missionText, L"%s - Active - Expires on Day %d, %02d:%02d", szRebelCommandAgentMissionsText[evt2.missionId * 2], day, hour, minute); + evt2Strings.push_back(missionText); + } + } + + UINT16 y = WEBSITE_TOP + 90; + for (int 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) + { + DrawTextToScreen(const_cast(evt2Strings[i].c_str()), WEBSITE_LEFT + 35, y, 0, FONT12ARIAL, FONT_DKGREEN, FONT_MCOLOR_BLACK, FALSE, 0); + y += 15; + } + } + } break; } From 1e189c54ac0927d404fc4a4bbb53c8b1013c14c8 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 17 Oct 2022 22:40:47 -0700 Subject: [PATCH 16/52] Add mission cost settings --- GameSettings.cpp | 2 ++ GameSettings.h | 2 ++ Strategic/Rebel Command.cpp | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 6af2140e4..33734547d 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4158,6 +4158,8 @@ void LoadRebelCommandSettings() gRebelCommandSettings.iFortificationsBonus = iniReader.ReadInteger("Rebel Command Settings", "FORTIFICATIONS_BONUS", 10, 0, 100); // agent missions + gRebelCommandSettings.iMissionBaseCost = iniReader.ReadInteger("Rebel Command Settings", "MISSION_BASE_COST", 500, 100, 10000); + gRebelCommandSettings.iMissionAdditionalCost = iniReader.ReadInteger("Rebel Command Settings", "MISSION_ADDITIONAL_COST", 250, 0, 10000); gRebelCommandSettings.iMissionRefreshTimeDays = iniReader.ReadInteger("Rebel Command Settings", "MISSION_REFRESH_TIME_DAYS", 2, 1, 7); gRebelCommandSettings.iMinLoyaltyForMission = iniReader.ReadInteger("Rebel Command Settings", "MIN_LOYALTY_FOR_MISSION", 51, 0, 100); diff --git a/GameSettings.h b/GameSettings.h index e80b41894..b4c46b194 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1843,6 +1843,8 @@ typedef struct INT16 iFortificationsBonus; // agent missions + INT32 iMissionBaseCost; + INT32 iMissionAdditionalCost; INT8 iMissionRefreshTimeDays; INT8 iMinLoyaltyForMission; diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 8f371ba07..a11ee6bc4 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -719,8 +719,8 @@ INT32 GetDirectiveImprovementCost(const RebelCommandDirectives directive) INT32 GetMissionCost() { - const INT32 additionalCost = missionMap.size() * 250; - return 500 + additionalCost; + const INT32 additionalCost = missionMap.size() * gRebelCommandSettings.iMissionAdditionalCost; + return gRebelCommandSettings.iMissionBaseCost + additionalCost; } INT8 GetMissionSuccessChanceBonus(const MERCPROFILESTRUCT* merc) From 3807b7fed4b3e71da92cf08927e93280abdea9ef Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 17 Oct 2022 23:28:21 -0700 Subject: [PATCH 17/52] Add proper checks and bonuses for active missions --- Strategic/Rebel Command.cpp | 123 ++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 35 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index a11ee6bc4..381be3c98 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -3848,7 +3848,6 @@ BOOLEAN Load(HWFILE file) // go through every strategic event to find active agent missions std::vector> missions = GetAllStrategicEventsOfType(EVENT_REBELCOMMAND); missionMap.clear(); - // example is EVENT_BLOODCAT_ATTACK for (std::vector>::iterator it = missions.begin(); it != missions.end(); ++it) { MissionFirstEvent evt1; @@ -4134,21 +4133,39 @@ void ApplyEnemyMechanicalUnitPenalties(SOLDIERTYPE* pSoldier) if (!gGameExternalOptions.fRebelCommandEnabled) return; - // rftr todo: check agent mission bitmask - - pSoldier->stats.bLife -= 40; - pSoldier->stats.bLifeMax = pSoldier->stats.bLife; - pSoldier->stats.bAgility -= 40; - pSoldier->stats.bDexterity -= 40; - pSoldier->stats.bStrength -= 40; - pSoldier->stats.bMarksmanship -= 40; - - pSoldier->stats.bLife = max(33, pSoldier->stats.bLife); - pSoldier->stats.bLifeMax = max(33, pSoldier->stats.bLifeMax); - pSoldier->stats.bAgility = max(33, pSoldier->stats.bAgility); - pSoldier->stats.bDexterity = max(33, pSoldier->stats.bDexterity); - pSoldier->stats.bStrength = max(33, pSoldier->stats.bStrength); - pSoldier->stats.bMarksmanship = max(33, pSoldier->stats.bMarksmanship); + const std::unordered_map::iterator iter = missionMap.find(RCAM_SABOTAGE_MECHANICAL_UNITS); + + if (iter == missionMap.end()) + return; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + if (evt.isSecondEvent) + { + INT8 statLoss = 0; + switch (evt.extraBits) + { + case MissionHelpers::SABOTAGE_MECHANICAL_UNITS_COVERT: statLoss = gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Covert; break; + case MissionHelpers::SABOTAGE_MECHANICAL_UNITS_DEMOLITIONS: statLoss = gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Demolitions; break; + case MissionHelpers::SABOTAGE_MECHANICAL_UNITS_HEAVY_WEAPONS: statLoss = gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Heavy_Weapons; break; + default: statLoss = gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss; break; + } + + pSoldier->stats.bLife -= statLoss; + pSoldier->stats.bLifeMax = pSoldier->stats.bLife; + pSoldier->stats.bAgility -= statLoss; + pSoldier->stats.bDexterity -= statLoss; + pSoldier->stats.bStrength -= statLoss; + pSoldier->stats.bMarksmanship -= statLoss; + + pSoldier->stats.bLife = max(33, pSoldier->stats.bLife); + pSoldier->stats.bLifeMax = max(33, pSoldier->stats.bLifeMax); + pSoldier->stats.bAgility = max(33, pSoldier->stats.bAgility); + pSoldier->stats.bDexterity = max(33, pSoldier->stats.bDexterity); + pSoldier->stats.bStrength = max(33, pSoldier->stats.bStrength); + pSoldier->stats.bMarksmanship = max(33, pSoldier->stats.bMarksmanship); + } } void ApplyMilitiaTraits(SOLDIERTYPE* pSoldier) @@ -4164,11 +4181,29 @@ void ApplyVisionModifier(const SOLDIERTYPE* pSoldier, INT32& sight) if (!gGameExternalOptions.fRebelCommandEnabled) return; - // rftr todo: check bitmask + const std::unordered_map::iterator iter = missionMap.find(RCAM_REDUCE_UNALERTED_ENEMY_VISION); - if (pSoldier->bTeam == ENEMY_TEAM && pSoldier->aiData.bAlertStatus == STATUS_GREEN) + if (iter == missionMap.end()) + return; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + if (evt.isSecondEvent) { - sight = static_cast(sight * (1.f - 0.15f)); + FLOAT modifier = 0.f; + switch (evt.extraBits) + { + case MissionHelpers::REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_COVERT: modifier = gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Covert; break; + case MissionHelpers::REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_RADIO: modifier = gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Radio; break; + case MissionHelpers::REDUCE_UNALERTED_ENEMY_VISION_MODIFIER_STEALTHY: modifier = gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier_Stealthy; break; + default: modifier = gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier; break; + } + + if (pSoldier->bTeam == ENEMY_TEAM && pSoldier->aiData.bAlertStatus == STATUS_GREEN) + { + sight = static_cast(sight * (1.f - modifier)); + } } } @@ -4228,8 +4263,6 @@ INT16 GetAdditionalDeployRange(const UINT8 insertionCode) if (iter == missionMap.end()) return 0; - // rftr todo: check bitmask - INT16 range = 0; MissionSecondEvent evt; @@ -4287,9 +4320,15 @@ INT8 GetEnemyEquipmentCoolnessModifier() if (!gGameExternalOptions.fRebelCommandEnabled) return 0; - // rftr todo: check bitmask + const std::unordered_map::iterator iter = missionMap.find(RCAM_SABOTAGE_INFANTRY_EQUIPMENT); - return -1; + if (iter == missionMap.end()) + return 0; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + return evt.isSecondEvent ? -1 : 0; } INT8 GetEnemyEquipmentStatusModifier(const INT8 initialStatus) @@ -4297,13 +4336,31 @@ INT8 GetEnemyEquipmentStatusModifier(const INT8 initialStatus) if (!gGameExternalOptions.fRebelCommandEnabled) return initialStatus; - // rftr todo: check bitmask + const std::unordered_map::iterator iter = missionMap.find(RCAM_SABOTAGE_INFANTRY_EQUIPMENT); + + if (iter == missionMap.end()) + return initialStatus; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); - INT8 newStatus = initialStatus; - newStatus -= 10; + if (evt.isSecondEvent) + { + INT8 modifier = 0; + switch (evt.extraBits) + { + case MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_AUTO_WEAPONS: modifier = gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Auto_Weapons; break; + case MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_COVERT: modifier = gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Covert; break; + case MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_DEMOLITIONS: modifier = gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Demolitions; break; + case MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_GUNSLINGER: modifier = gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Gunslinger; break; + case MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_RANGER: modifier = gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Ranger; break; + case MissionHelpers::SABOTAGE_ENEMY_INFANTRY_EQUIPMENT_MODIFIER_SNIPER: modifier = gRebelCommandSettings.iSabotageInfantryEquipmentModifier_Sniper; break; + } + + return max(1, min(initialStatus - modifier, 100)); + } - newStatus = max(1, min(newStatus, 100)); - return newStatus; + return initialStatus; } UINT8 GetMerchantCoolnessBonus() @@ -4319,8 +4376,6 @@ UINT8 GetMerchantCoolnessBonus() MissionSecondEvent evt; DeserialiseMissionSecondEvent(iter->second, evt); - // rftr todo: check bitmask - return evt.isSecondEvent ? 1 : 0; } @@ -4332,13 +4387,11 @@ FLOAT GetStrategicDecisionSpeedModifier() const std::unordered_map::iterator iter = missionMap.find(RCAM_REDUCE_STRATEGIC_DECISION_SPEED); if (iter == missionMap.end()) - return 0; + return 1.f; MissionSecondEvent evt; DeserialiseMissionSecondEvent(iter->second, evt); - // rftr todo: check bitmask - FLOAT modifier = 1.f; if (evt.isSecondEvent) @@ -4346,6 +4399,8 @@ FLOAT GetStrategicDecisionSpeedModifier() switch (evt.extraBits) { case MissionHelpers::REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_COVERT: modifier = gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Covert; break; + case MissionHelpers::REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_DEPUTY: modifier = gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Deputy; break; + case MissionHelpers::REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_SNITCH: modifier = gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier_Snitch; break; default: modifier = gRebelCommandSettings.fReduceStrategicDecisionSpeedModifier; break; } } @@ -4515,8 +4570,6 @@ BOOLEAN ShowEnemyMovementTargets() if (iter == missionMap.end()) return FALSE; - // rftr todo: check bitmask - MissionSecondEvent evt; DeserialiseMissionSecondEvent(iter->second, evt); From 7e55488b40835079989366790918067a0559d990 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 18 Oct 2022 17:27:05 -0700 Subject: [PATCH 18/52] Clean up some todos --- Strategic/Rebel Command.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 381be3c98..686b04b36 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2118,7 +2118,6 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) if (agentIndex[index] < 0) agentIndex[index] = static_cast(mercs.size()); else if (agentIndex[index] > static_cast(mercs.size())) agentIndex[index] = 0; - // rftr todo: handle RCAM_NONE (ie, mission prep in progress!) if (rebelCommandSaveInfo.availableMissions[index] == RCAM_NONE) { // we shouldn't even reach this point, but leaving this here for safety @@ -2531,7 +2530,6 @@ void RenderMissionOverview() } else { - // rftr todo: run through active mission list (missionMap) and show a one-line description for each. std::vector evt1Strings; std::vector evt2Strings; std::vector> missions = GetAllStrategicEventsOfType(EVENT_REBELCOMMAND); @@ -2591,7 +2589,6 @@ void StartMission(INT8 index) return; } - // todo do something with agentIndex[index] and missionIndex[index] (rebelCommandSaveInfo.availableMissions[index]) // confirmation popup std::vector mercs; for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) @@ -3669,7 +3666,6 @@ void DailyUpdate() } // update missions - // rftr todo: test me if (GetWorldDay() % gRebelCommandSettings.iMissionRefreshTimeDays == 0) { std::unordered_set validMissions; @@ -4278,7 +4274,6 @@ INT16 GetAdditionalDeployRange(const UINT8 insertionCode) { range = gRebelCommandSettings.iDeepDeploymentRangeNS; - // rftr todo: bitmagic to get bonus range switch (evt.extraBits) { case MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_COVERT: range += gRebelCommandSettings.iDeepDeploymentRangeNS_Bonus_Covert; break; @@ -4411,7 +4406,6 @@ FLOAT GetStrategicDecisionSpeedModifier() void HandleStrategicEvent(const UINT32 eventParam) { // this handles the transition from "mission prep" (first event) to "mission active" (second event), which happens 24 hours after the player clicks on "start mission" - // rftr todo: update agent mission bitmask MissionFirstEvent evt1; MissionSecondEvent evt2; DeserialiseMissionFirstEvent(eventParam, evt1); @@ -4498,7 +4492,6 @@ void HandleStrategicEvent(const UINT32 eventParam) } } - // rftr todo: tell the player that the mission has started. popupbox or screenmsg? missionMap.insert(std::make_pair(mission, activatedMissionParam)); swprintf(msgBoxText, L"Mission prep success! %s", szRebelCommandAgentMissionsText[evt1.missionId * 2]); swprintf(screenMsgText, L"Mission \"%s\" is now in effect.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); @@ -4507,7 +4500,6 @@ void HandleStrategicEvent(const UINT32 eventParam) } else { - // rftr todo: tell the player that the mission prep failed. some popup box blurb or somesuch. if (!evt1.sentGenericRebelAgent && foundMerc) { for (UINT8 i = gTacticalStatus.Team[OUR_TEAM].bFirstID; i <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++i) From fcd7ed5ef6356a93cd0817b8bbb30e1530679cef Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 18 Oct 2022 22:08:09 -0700 Subject: [PATCH 19/52] Move text to _EnglishText --- Strategic/Rebel Command.cpp | 135 +++++++++++++++++++++++------------- Utils/_EnglishText.cpp | 41 +++++++++++ 2 files changed, 128 insertions(+), 48 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 686b04b36..9aab43f7a 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -293,6 +293,44 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_NEXT_ARROW, RCT_CONFIRM_CHANGE_ADMIN_ACTION_PROMPT, RCT_NEW_MISSIONS_AVAILABLE_TIME, + RCT_MISSION_PREP_IN_PROGRESS, + RCT_MISSION_DURATION_DAYS, + RCT_MISSION_SUCCESS_CHANCE, + RCT_MISSION_AGENT_REDACTED, + RCT_MISSION_AGENT_NAME, + RCT_MISSION_AGENT_LOCATION, + RCT_MISSION_AGENT_ASSIGNMENT, + RCT_MISSION_AGENT_CONTRACT_DAYS, + RCT_MISSION_AGENT_CONTRACT_HOURS, + RCT_MISSION_AGENT_CONTRACT_NONE, + RCT_MISSION_AGENT_BONUS, + RCT_MISSION_BONUS_SUCCESS_CHANCE, + RCT_MISSION_BONUS_DEPLOY_RANGE, + RCT_MISSION_BONUS_DECISION_TIME, + RCT_MISSION_BONUS_UNALERTED_VISION_PENALTY, + RCT_MISSION_BONUS_INFANTRY_GEAR_QUALITY, + RCT_MISSION_BONUS_MECHANICAL_STAT_LOSS, + RCT_MISSION_BONUS_MAX_TRAINERS, + RCT_MISSION_BONUS_DURATION, + RCT_MISSION_CANT_START_LOW_LOYALTY, + RCT_MISSION_CANT_START_AGENT_UNAVAILABLE, + RCT_MISSION_CANT_START_CONTRACT_EXPIRING, + RCT_MISSION_CANT_START_BATTLE_IN_PROGRESS, + RCT_MISSION_START_BUTTON, + RCT_MISSION_VIEW_ACTIVE, + RCT_MISSION_VIEW_LIST, + RCT_MISSION_NEXT_AVAILABILITY, + RCT_MISSION_ACTIVE_MISSIONS, + RCT_MISSION_LIST_PREPARING, + RCT_MISSION_LIST_ACTIVE, + RCT_MISSION_POPUP_PART1, + RCT_MISSION_POPUP_PART2_GENERIC, + RCT_MISSION_POPUP_PART2_MALE, + RCT_MISSION_POPUP_PART2_FEMALE, + RCT_MISSION_SUCCESS, + RCT_MISSION_FAILURE, + RCT_MISSION_EXPIRED, + }; enum RebelCommandHelpText // keep this synced with szRebelCommandHelpText in the text files @@ -2121,8 +2159,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) if (rebelCommandSaveInfo.availableMissions[index] == RCAM_NONE) { // we shouldn't even reach this point, but leaving this here for safety - swprintf(sText, L"Mission preparations in progress."); - DrawTextToScreen(sText, x, y+155, 230, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + DrawTextToScreen(szRebelCommandText[RCT_MISSION_PREP_IN_PROGRESS], x, y+155, 230, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); return FALSE; } @@ -2159,7 +2196,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } // convert from hours missionDurationBase /= 24; - swprintf(sText, L"Mission duration: %d days", missionDurationBase); + swprintf(sText, szRebelCommandText[RCT_MISSION_DURATION_DAYS], missionDurationBase); DrawTextToScreen(sText, x+5, y+21, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw mission base success chance @@ -2177,7 +2214,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) default: break; } - swprintf(sText, L"Chance of success: %d%s", missionSuccessChanceBase, L"%%"); + swprintf(sText, szRebelCommandText[RCT_MISSION_SUCCESS_CHANCE], missionSuccessChanceBase, L"%%"); DrawTextToScreen(sText, x+5, y+33, 0, FONT10ARIALBOLD, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw mission description @@ -2207,16 +2244,19 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) SetFontShadow(FONT_GRAY1); // draw name - DrawTextToScreen(L"Name: [REDACTED]", x+55, y+150+10, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_NAME], szRebelCommandText[RCT_MISSION_AGENT_REDACTED]); + DrawTextToScreen(sText, x+55, y+150+10, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw location - DrawTextToScreen(L"Location: [REDACTED]", x+55, y+150+22, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_LOCATION], szRebelCommandText[RCT_MISSION_AGENT_REDACTED]); + DrawTextToScreen(sText, x+55, y+150+22, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw assignment - DrawTextToScreen(L"Assignment: None", x+55, y+150+34, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_ASSIGNMENT], szRebelCommandText[RCT_NONE]); + DrawTextToScreen(sText, x+55, y+150+34, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw contract - DrawTextToScreen(L"Contract: ---", x+55, y+150+46, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + DrawTextToScreen(szRebelCommandText[RCT_MISSION_AGENT_CONTRACT_NONE], x+55, y+150+46, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } else // one of the player's mercs { @@ -2229,17 +2269,17 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) BltVideoObject(FRAME_BUFFER, hvObj, 0, x+5, y+150+10, VO_BLT_SRCTRANSPARENCY, NULL); // draw name - swprintf(sText, L"Name: %s", gMercProfiles[mercs[agentIndex[index]]->ubProfile].zName); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_NAME], gMercProfiles[mercs[agentIndex[index]]->ubProfile].zName); DrawTextToScreen(sText, x+55, y+150+10, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw location CHAR16 locationStr[128]; GetSectorIDString(mercs[agentIndex[index]]->sSectorX, mercs[agentIndex[index]]->sSectorY, 0, locationStr, TRUE); - swprintf(sText, L"Location: %s", locationStr); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_LOCATION], locationStr); DrawTextToScreen(sText, x+55, y+150+22, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw assignment - swprintf( sText, L"Assignment: %s", pAssignmentStrings[mercs[agentIndex[index]]->bAssignment]); + swprintf( sText, szRebelCommandText[RCT_MISSION_AGENT_ASSIGNMENT], pAssignmentStrings[mercs[agentIndex[index]]->bAssignment]); DrawTextToScreen(sText, x+55, y+150+34, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw contract @@ -2253,16 +2293,16 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) if (remaining >= 24 * 60) { - swprintf(sText, L"Contract: %d days", remaining / (24 * 60)); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_CONTRACT_DAYS], remaining / (24 * 60)); } else { - swprintf(sText, L"Contract: %d hours", remaining / 60); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_CONTRACT_HOURS], remaining / 60); } } else { - swprintf(sText, L"Contract: ---"); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_CONTRACT_NONE]); } DrawTextToScreen(sText, x+55, y+150+46, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } @@ -2285,7 +2325,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) btnIds.push_back(btnId); // draw agent bonus header text - swprintf(sText, L"Agent bonus:"); + swprintf(sText, szRebelCommandText[RCT_MISSION_AGENT_BONUS]); DrawTextToScreen(sText, x+5, y+150+54+20+2, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); // draw agent bonus text @@ -2298,7 +2338,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) const INT8 successBonus_expLevel = GetMissionSuccessChanceBonus(&merc); CHAR16 successText[100]; // stupid string hack to get the percent sign to display correctly - swprintf(successText, L"Chance of success +%d%s (%s)", successBonus_expLevel, L"%s", pShortAttributeStrings[5]); // "Lvl" + swprintf(successText, szRebelCommandText[RCT_MISSION_BONUS_SUCCESS_CHANCE], successBonus_expLevel, L"%s", pShortAttributeStrings[5]); // "Lvl" agentBonusText.push_back(successText); const STR16* locSkillText = gGameOptions.fNewTraitSystem ? gzMercSkillTextNew : gzMercSkillText; @@ -2314,7 +2354,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) { intModifier = max(intModifier, gRebelCommandSettings.iDeepDeploymentRangeEW); CHAR16 rangeText[100]; - swprintf(rangeText, L"Deployment range +%d (%s)", intModifier, locSkillText[intModifierSkill]); + swprintf(rangeText, szRebelCommandText[RCT_MISSION_BONUS_DEPLOY_RANGE], intModifier, locSkillText[intModifierSkill]); agentBonusText.push_back(rangeText); } break; @@ -2337,7 +2377,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) floatModifier -= 1.f; floatModifier *= 100.f; CHAR16 rangeText[100]; - swprintf(rangeText, L"Time +%2.0f%s (%s)", floatModifier, L"%s", locSkillText[floatModifierSkill]); + swprintf(rangeText, szRebelCommandText[RCT_MISSION_BONUS_DECISION_TIME], floatModifier, L"%s", locSkillText[floatModifierSkill]); agentBonusText.push_back(rangeText); } break; @@ -2347,7 +2387,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) floatModifier = max(floatModifier, gRebelCommandSettings.fReduceUnlaertedEnemyVisionModifier); floatModifier *= 100.f; CHAR16 text[100]; - swprintf(text, L"Vision -%2.0f%s (%s)", floatModifier, L"%s", locSkillText[floatModifierSkill]); + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_UNALERTED_VISION_PENALTY], floatModifier, L"%s", locSkillText[floatModifierSkill]); agentBonusText.push_back(text); } break; @@ -2356,7 +2396,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) { intModifier = max(intModifier, gRebelCommandSettings.iSabotageInfantryEquipmentModifier); CHAR16 text[100]; - swprintf(text, L"Gear quality -%d (%s)", intModifier, locSkillText[intModifierSkill]); + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_INFANTRY_GEAR_QUALITY], intModifier, locSkillText[intModifierSkill]); agentBonusText.push_back(text); } break; @@ -2365,7 +2405,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) { intModifier = max(intModifier, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss); CHAR16 text[100]; - swprintf(text, L"Overall stats -%d (%s)", intModifier, locSkillText[intModifierSkill]); + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_MECHANICAL_STAT_LOSS], intModifier, locSkillText[intModifierSkill]); agentBonusText.push_back(text); } break; @@ -2374,7 +2414,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) { intModifier = max(intModifier, 1); CHAR16 text[100]; - swprintf(text, L"Max trainers: %d (%s)", intModifier, locSkillText[intModifierSkill]); + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_MAX_TRAINERS], intModifier, locSkillText[intModifierSkill]); agentBonusText.push_back(text); } break; @@ -2385,14 +2425,14 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) if (durationBonus > 0) { CHAR16 durationText[100]; - swprintf(durationText, L"Duration +%d hours (%s)", durationBonus, locSkillText[durationBonusSkill]); + swprintf(durationText, szRebelCommandText[RCT_MISSION_BONUS_DURATION], durationBonus, locSkillText[durationBonusSkill]); agentBonusText.push_back(durationText); } } if (agentBonusText.size() == 0) { - DrawTextToScreen(L"None", x+10, y+150+54+20+2+11, 0, FONT10ARIAL, FONT_MCOLOR_RED, FONT_MCOLOR_BLACK, FALSE, 0); + DrawTextToScreen(szRebelCommandText[RCT_NONE], x+10, y+150+54+20+2+11, 0, FONT10ARIAL, FONT_MCOLOR_RED, FONT_MCOLOR_BLACK, FALSE, 0); } else { @@ -2417,17 +2457,17 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) if (townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission) { canStartMission = FALSE; - swprintf(sText, L"Agent not in loyal town"); + swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_LOW_LOYALTY]); } else if (mercs[agentIndex[index]]->bAssignment == ASSIGNMENT_POW || mercs[agentIndex[index]]->bAssignment == ASSIGNMENT_MINIEVENT || mercs[agentIndex[index]]->bAssignment == ASSIGNMENT_REBELCOMMAND) { canStartMission = FALSE; - swprintf(sText, L"Agent unavailable"); + swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_AGENT_UNAVAILABLE]); } else if (mercs[agentIndex[index]]->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC && remaining < 24 * 60) { canStartMission = FALSE; - swprintf(sText, L"Agent contract expiring"); + swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_CONTRACT_EXPIRING]); } if (!canStartMission) @@ -2438,13 +2478,13 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) else if ((gTacticalStatus.uiFlags & INCOMBAT) || gTacticalStatus.fEnemyInSector) { canStartMission = FALSE; - swprintf(sText, L"Battle in progress"); + swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_BATTLE_IN_PROGRESS]); DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); } if (canStartMission) { - swprintf(sText, L"Start Mission (%d supplies)", GetMissionCost()); + swprintf(sText, szRebelCommandText[RCT_MISSION_START_BUTTON], GetMissionCost()); btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, x, y+290, 231, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) { const INT8 index = MSYS_GetBtnUserData(btn, 0); @@ -2471,11 +2511,11 @@ void RenderMissionOverview() switch (missionOverviewSubview) { case MOS_MISSION_LIST: - swprintf(sText, L"View active mission effects"); + swprintf(sText, szRebelCommandText[RCT_MISSION_VIEW_ACTIVE]); break; case MOS_ACTIVE_MISSION_EFFECTS: - swprintf(sText, L"View available mission list"); + swprintf(sText, szRebelCommandText[RCT_MISSION_VIEW_LIST]); break; } btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, WEBSITE_LEFT + 15, WEBSITE_TOP + 40, 470, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) @@ -2507,9 +2547,8 @@ void RenderMissionOverview() const INT8 interval = gRebelCommandSettings.iMissionRefreshTimeDays; nextMissionAvailableDay += (interval - (nextMissionAvailableDay % interval)); - swprintf(sText, L"Mission preparations in progress."); - DrawTextToScreen(sText, WEBSITE_LEFT + 15, WEBSITE_TOP + 155, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); - swprintf(sText, L"New missions will be available on Day %d at 00:00.", nextMissionAvailableDay); + DrawTextToScreen(szRebelCommandText[RCT_MISSION_PREP_IN_PROGRESS], WEBSITE_LEFT + 15, WEBSITE_TOP + 155, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + swprintf(sText, szRebelCommandText[RCT_MISSION_NEXT_AVAILABILITY], nextMissionAvailableDay); DrawTextToScreen(sText, WEBSITE_LEFT + 15, WEBSITE_TOP + 175, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); } else @@ -2523,10 +2562,10 @@ void RenderMissionOverview() case MOS_ACTIVE_MISSION_EFFECTS: { - DrawTextToScreen(L"Active missions:", WEBSITE_LEFT + 25, WEBSITE_TOP + 75, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + DrawTextToScreen(szRebelCommandText[RCT_MISSION_ACTIVE_MISSIONS], WEBSITE_LEFT + 25, WEBSITE_TOP + 75, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); if (missionMap.size() == 0) { - DrawTextToScreen(L"None", WEBSITE_LEFT + 35, WEBSITE_TOP + 90, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); + DrawTextToScreen(szRebelCommandText[RCT_NONE], WEBSITE_LEFT + 35, WEBSITE_TOP + 90, 0, FONT12ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } else { @@ -2547,13 +2586,13 @@ void RenderMissionOverview() if (evt1.isFirstEvent) { CHAR16 prepText[200]; - swprintf(prepText, L"%s - Preparing - Ready on Day %d, %02d:%02d", szRebelCommandAgentMissionsText[evt1.missionId * 2], day, hour, minute); + swprintf(prepText, szRebelCommandText[RCT_MISSION_LIST_PREPARING], szRebelCommandAgentMissionsText[evt1.missionId * 2], day, hour, minute); evt1Strings.push_back(prepText); } else if (evt2.isSecondEvent) { CHAR16 missionText[200]; - swprintf(missionText, L"%s - Active - Expires on Day %d, %02d:%02d", szRebelCommandAgentMissionsText[evt2.missionId * 2], day, hour, minute); + swprintf(missionText, szRebelCommandText[RCT_MISSION_LIST_ACTIVE], szRebelCommandAgentMissionsText[evt2.missionId * 2], day, hour, minute); evt2Strings.push_back(missionText); } } @@ -2698,21 +2737,21 @@ void StartMission(INT8 index) missionDuration += durationBonus; } - swprintf(text, L"[%s (%d supplies)]", szRebelCommandAgentMissionsText[missionTitle], cost); + swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART1], szRebelCommandAgentMissionsText[missionTitle], cost); if (agentIndex[index] == mercs.size()) { // sent a generic rebel MissionHelpers::missionParam = SerialiseMissionFirstEvent(TRUE, 0 /* no profile needed */, static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, 0 /* no extra data */); - swprintf(text, L"%s Send a rebel agent to prepare this mission?", text); + swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART2_GENERIC], text); } else { MissionHelpers::missionParam = SerialiseMissionFirstEvent(FALSE, mercs[agentIndex[index]]->ubProfile, static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, static_cast(extraBits)); if (merc->bSex == MALE) - swprintf(text, L"%s Send %s to prepare this mission? He will return in 24 hours.", text, merc->zNickname); + swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART2_MALE], text, merc->zNickname); else - swprintf(text, L"%s Send %s to prepare this mission? She will return in 24 hours.", text, merc->zNickname); + swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART2_FEMALE], text, merc->zNickname); } DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, text, LAPTOP_SCREEN, MSG_BOX_FLAG_YESNO, [](UINT8 exitValue) { @@ -4493,8 +4532,8 @@ void HandleStrategicEvent(const UINT32 eventParam) } missionMap.insert(std::make_pair(mission, activatedMissionParam)); - swprintf(msgBoxText, L"Mission prep success! %s", szRebelCommandAgentMissionsText[evt1.missionId * 2]); - swprintf(screenMsgText, L"Mission \"%s\" is now in effect.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(msgBoxText, szRebelCommandText[RCT_MISSION_SUCCESS], szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_SUCCESS], szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, screenMsgText); } } @@ -4516,8 +4555,8 @@ void HandleStrategicEvent(const UINT32 eventParam) } MissionFailed_MercNoLongerOnTeam: - swprintf(msgBoxText, L"Mission prep failed... %s", szRebelCommandAgentMissionsText[evt1.missionId * 2]); - swprintf(screenMsgText, L"Preparations for mission \"%s\" failed.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(msgBoxText, szRebelCommandText[RCT_MISSION_FAILURE], szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_FAILURE], szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); } @@ -4544,8 +4583,8 @@ void HandleStrategicEvent(const UINT32 eventParam) { // mission duration is over. deactivate the mission missionMap.erase(static_cast(evt2.missionId)); - swprintf(msgBoxText, L"Mission duration complete! %s", szRebelCommandAgentMissionsText[evt2.missionId * 2]); - swprintf(screenMsgText, L"Mission \"%s\" has expired and is no longer in effect.", szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(msgBoxText, szRebelCommandText[RCT_MISSION_EXPIRED], szRebelCommandAgentMissionsText[evt2.missionId * 2]); + swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_EXPIRED], szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); } diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 11da10987..d49c2c284 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11933,6 +11933,47 @@ STR16 szRebelCommandText[] = L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect." + + + + }; STR16 szRebelCommandHelpText[] = From c9421215e0f50f8fea8f8ce70d0954cd45d88a70 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 18 Oct 2022 22:34:18 -0700 Subject: [PATCH 20/52] Toggle admin actions off if the player can't pay upkeep --- Strategic/Rebel Command.cpp | 115 +++++++++++++++--------------------- Utils/_EnglishText.cpp | 1 + 2 files changed, 50 insertions(+), 66 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 9aab43f7a..f5de19bc2 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -292,6 +292,7 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_PREV_ARROW, RCT_NEXT_ARROW, RCT_CONFIRM_CHANGE_ADMIN_ACTION_PROMPT, + RCT_INSUFFICIENT_SUPPLIES_ADMIN_ACTIONS_DISABLED, RCT_NEW_MISSIONS_AVAILABLE_TIME, RCT_MISSION_PREP_IN_PROGRESS, RCT_MISSION_DURATION_DAYS, @@ -511,7 +512,6 @@ ChangeAdminActionState adminActionChangeState; MOUSE_REGION adminActionActiveTextRegion[5]; MOUSE_REGION adminActionHelpTextRegion[6]; MOUSE_REGION adminTeamHelpTextRegion; -//MOUSE_REGION agentNotifyToggleTextRegion; MOUSE_REGION directiveDescriptionHelpTextRegion; MOUSE_REGION loyaltyHelpTextRegion; MOUSE_REGION maxLoyaltyHelpTextRegion; @@ -587,7 +587,6 @@ void ClearAllHelpTextRegions() for (int a = 0; a < 6; a++) MSYS_RemoveRegion(&adminActionHelpTextRegion[a]); MSYS_RemoveRegion(&adminTeamHelpTextRegion); - //MSYS_RemoveRegion(&agentNotifyToggleTextRegion); MSYS_RemoveRegion(&directiveDescriptionHelpTextRegion); MSYS_RemoveRegion(&loyaltyHelpTextRegion); MSYS_RemoveRegion(&maxLoyaltyHelpTextRegion); @@ -3605,84 +3604,68 @@ void DailyUpdate() if (CanAdminActionBeToggled(rebelCommandSaveInfo.regions[a].actions[b]) && !rebelCommandSaveInfo.regions[a].IsActive(b)) continue; - switch (static_cast(rebelCommandSaveInfo.regions[a].actions[b])) - { - case RCAA_SUPPLY_LINE: - case RCAA_SUPPLY_DISRUPTION: - case RCAA_SCOUTS: - case RCAA_MERC_SUPPORT: - case RCAA_PATHFINDERS: - case RCAA_FORTIFICATIONS: - // no daily bonuses - break; + // toggle admin action off on a negative supply balance + if (rebelCommandSaveInfo.iSupplies <= 0) + rebelCommandSaveInfo.regions[a].SetInactive(b); - case RCAA_HARRIERS: - case RCAA_MINING_POLICY: - case RCAA_SAFEHOUSES: - // no daily bonuses, but gotta pay upkeep - if (rebelCommandSaveInfo.iSupplies > supplyUpkeep) - { - // what to do on success? - } - else + if (rebelCommandSaveInfo.regions[a].IsActive(b)) + { + switch (static_cast(rebelCommandSaveInfo.regions[a].actions[b])) { - swprintf(text, L"Not enough supplies for harriers/miningpolicy/safehouses!"); - ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); - } - break; + case RCAA_SUPPLY_LINE: + case RCAA_SUPPLY_DISRUPTION: + case RCAA_SCOUTS: + case RCAA_MERC_SUPPORT: + case RCAA_PATHFINDERS: + case RCAA_FORTIFICATIONS: + case RCAA_HARRIERS: + case RCAA_MINING_POLICY: + case RCAA_SAFEHOUSES: + // no daily bonuses + break; - case RCAA_REBEL_RADIO: - IncrementTownLoyalty(a, static_cast(info.adminActions[RCAA_REBEL_RADIO].fValue1 * level)); - break; + case RCAA_REBEL_RADIO: + IncrementTownLoyalty(a, static_cast(info.adminActions[RCAA_REBEL_RADIO].fValue1 * level)); + break; - case RCAA_DEAD_DROPS: - if (rebelCommandSaveInfo.iSupplies > supplyUpkeep) - { + case RCAA_DEAD_DROPS: intelGain += Random(static_cast(info.adminActions[RCAA_DEAD_DROPS].fValue1 * level * loyalty / 100.f)); - } - else - { - swprintf(text, L"Not enough supplies for dead drops"); - ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); - } - break; - - case RCAA_SMUGGLERS: - supplyGain += Random(static_cast(info.adminActions[RCAA_SMUGGLERS].fValue1 * level * loyalty / 100.f)); - break; + break; + + case RCAA_SMUGGLERS: + supplyGain += Random(static_cast(info.adminActions[RCAA_SMUGGLERS].fValue1 * level * loyalty / 100.f)); + break; - case RCAA_WAREHOUSES: - if (rebelCommandSaveInfo.iSupplies > supplyUpkeep) - { - AddResources( - static_cast(info.adminActions[RCAA_WAREHOUSES].fValue1 * level * Random(100) * loyalty / 10000.f), - static_cast(info.adminActions[RCAA_WAREHOUSES].fValue2 * level * Random(100) * loyalty / 10000.f), - static_cast(info.adminActions[RCAA_WAREHOUSES].fValue3 * level * Random(100) * loyalty / 10000.f)); - } - else - { - swprintf(text, L"Not enough supplies for warehouses"); - ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s", text); - } - break; + case RCAA_WAREHOUSES: + AddResources( + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue1 * level * Random(100) * loyalty / 10000.f), + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue2 * level * Random(100) * loyalty / 10000.f), + static_cast(info.adminActions[RCAA_WAREHOUSES].fValue3 * level * Random(100) * loyalty / 10000.f)); + break; - case RCAA_TAXES: - moneyGain += static_cast(info.adminActions[RCAA_TAXES].fValue1 * coolness * level * loyalty * (75.f + Random(26))/ 10000.f); - DecrementTownLoyalty(a, static_cast(info.adminActions[RCAA_TAXES].fValue2 * level)); - break; + case RCAA_TAXES: + moneyGain += static_cast(info.adminActions[RCAA_TAXES].fValue1 * coolness * level * loyalty * (75.f + Random(26))/ 10000.f); + 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 * loyalty / 100.f)); - break; + case RCAA_ASSIST_CIVILIANS: + AddVolunteers(static_cast(info.adminActions[RCAA_ASSIST_CIVILIANS].fValue1 * level * loyalty / 100.f)); + break; - default: - AssertMsg(false, "Unknown Admin Action"); - break; + default: + AssertMsg(false, "Unknown Admin Action"); + break; + } } } } + if (rebelCommandSaveInfo.iSupplies <= 0) + { + ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, szRebelCommandText[RCT_INSUFFICIENT_SUPPLIES_ADMIN_ACTIONS_DISABLED]); + } + if (intelGain > 0) { swprintf(text, szRebelCommandText[RCT_DEAD_DROP_INCOME], intelGain); diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index d49c2c284..bb937af4a 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11932,6 +11932,7 @@ STR16 szRebelCommandText[] = L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", L"Mission preparations in progress.", L"Mission duration: %d days", From 1448ee0cbbe12dd94b8b9b7b383f7e7d6120de39 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 19 Oct 2022 11:26:01 -0700 Subject: [PATCH 21/52] Prevent toggling on admin actions when the player has too few supplies Fix toggle check in daily update --- Strategic/Rebel Command.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index f5de19bc2..13de9e879 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -918,6 +918,9 @@ void SetupAdminActionBox(const UINT8 actionIndex, const UINT16 descriptionText, RenderWebsite(); }); + if (rebelCommandSaveInfo.iSupplies <= 0) + DisableButton(btnId); + MSYS_SetBtnUserData( btnId, 0, iCurrentRegionId ); MSYS_SetBtnUserData( btnId, 1, actionIndex ); @@ -3565,7 +3568,6 @@ void DailyUpdate() // what gets subtracted? current balance? daily income? how do we pick? // get regional bonuses - const INT32 supplyUpkeep = static_cast(gRebelCommandSettings.fIncomeModifier + 0.5f); INT16 intelGain = 0; INT16 supplyGain = 0; INT16 moneyGain = 0; @@ -3602,7 +3604,7 @@ void DailyUpdate() const INT8 level = rebelCommandSaveInfo.regions[a].GetLevel(b); if (level == 0) continue; - if (CanAdminActionBeToggled(rebelCommandSaveInfo.regions[a].actions[b]) && !rebelCommandSaveInfo.regions[a].IsActive(b)) continue; + if (!CanAdminActionBeToggled(rebelCommandSaveInfo.regions[a].actions[b]) || !rebelCommandSaveInfo.regions[a].IsActive(b)) continue; // toggle admin action off on a negative supply balance if (rebelCommandSaveInfo.iSupplies <= 0) From 39798ce5073190db206d01097eb86867ab3bb334 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 19 Oct 2022 23:30:23 -0700 Subject: [PATCH 22/52] Copy loc changes from english to other languages --- Utils/_ChineseText.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- Utils/_DutchText.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- Utils/_EnglishText.cpp | 6 +--- Utils/_FrenchText.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- Utils/_GermanText.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- Utils/_ItalianText.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- Utils/_PolishText.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- Utils/_RussianText.cpp | 77 ++++++++++++++++++++++++++++++++++++++---- 8 files changed, 491 insertions(+), 54 deletions(-) diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 1dbae02ec..ac3a36c04 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -2480,7 +2480,8 @@ STR16 pAssignmentStrings[] = L"掩埋尸体", //L"Burial", L"管理", //L"Admin", L"探索", //L"Explore" - L"事件" //L"Event" rftr: merc is on a mini event + L"事件", //L"Event" rftr: merc is on a mini event + L"Mission", // rftr: rebel command }; @@ -11864,12 +11865,16 @@ STR16 gLbeStatsDesc[14] = STR16 szRebelCommandText[] = { - L"Arulco反抗军司令部 - 国家总览", //L"Arulco Rebel Command - National Overview", - L"Arulco反抗军司令部 - 地区总览", //L"Arulco Rebel Command - Regional Overview", - L"点击地区总览", //L"Switch to Regional Overview", - L"点击国家总览", //L"Switch to National Overview", + L"国家总览", //L"National Overview", + L"地区总览", //L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"地区总览 (2)", //L"Regional (2)", + L"国家总览 (1)", //L"National (1)", + L"Mission (3)", L"物资:", //L"Supplies:", L"后勤物资", //L"Incoming Supplies", + L"Intel:", L" /天", //L"/day", L"当前项目", //L"Current Directive", L"升级项目($%d)", //L"Improve Directive ($%d)", @@ -11927,17 +11932,55 @@ STR16 szRebelCommandText[] = L"<", //L"<", L">", //L">", L"更改此指令操作将花费$%d并重置。确认支出?", //L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", + L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect.", }; STR16 szRebelCommandHelpText[] = { L"|物|资\n \n食物、水、医疗用品、武器以及任何\n反抗军认为有用的物资。反抗军会自动收集。", //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"|后|勤|物|资\n \n反抗军每天都会自动收集物资。当你\n占领更多的城镇时,他们每天能够\n找到的物资补给量将会增加。", //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"|后|勤|物|资\n \n反抗军每天都会自动收集物资。当你\n占领更多的城镇时,他们每天能够\n找到的物资补给量将会增加。\n \n+%d (Base income)", //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"|当|前|项|目\n \n你可以选择反抗军优先进行的战略目标。\n当你选定好战略目标时,新的项目指令将生效。", //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"|指|挥|部\n \n指挥部一旦部署,就会负责处理\n该区域内的日常事务。包括支持当地人,制造\n反抗宣传,制定地区政策等等。", //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"|忠|诚|度\n \n许多行政命令的有效性取决于\n该地区的忠诚度,提高忠诚度\n能得到最大利益化。", //L"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", L"|最|高|忠|诚|度\n \n你需要说服当地人完全信任你。这可以\n通过为他们建立物资供应来实现,表明\n你打算改善他们的生活质量。", //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.", - L"|援|助|物|资\n \n将物资送到此处的反抗军手里,并允许\n他们根据需要使用。这将少量增加\n该地区的忠诚度,但是会略微增加制定\n该地区政策的成本。", //L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"该管理行动只会作用到城镇区域。", //L"This Admin Action applies its bonus to town sectors only.", TODO.Translate L"该管理行动会作用到城镇区域。\n和直接相邻的区域。", //L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"该管理行动会作用到城镇区域。\n1级覆盖周边1个区域。\n2级覆盖周边2个区域。", //L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -12030,6 +12073,26 @@ STR16 szRebelCommandDirectivesText[] = L"升级此项将会增加每天志愿者人数。", //L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = { L"已经安装在机器人身上的武器不能替换。", //L"The robot's installed weapon cannot be changed.", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index ddb901a17..af0fe600b 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -2479,7 +2479,8 @@ STR16 pAssignmentStrings[] = L"Burial", L"Admin", // TODO.Translate L"Explore", // TODO.Translate - L"Event"// rftr: merc is on a mini event // TODO: translate + L"Event",// rftr: merc is on a mini event // TODO: translate + L"Mission", // rftr: rebel command }; @@ -11874,12 +11875,16 @@ STR16 gLbeStatsDesc[14] = 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"National Overview", + L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"Regional (2)", + L"National (1)", + L"Mission (3)", L"Supplies:", L"Incoming Supplies", + L"Intel:", L"/day", L"Current Directive", L"Improve Directive ($%d)", @@ -11937,17 +11942,55 @@ STR16 szRebelCommandText[] = // TODO.Translate L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", + L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect.", }; 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"|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.\n \n+%d (Base income)", 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"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", 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.", - L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"This Admin Action applies its bonus to town sectors only.", //TODO.Translate L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -12040,6 +12083,26 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = // TODO: Translate { L"The robot's installed weapon cannot be changed.", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index bb937af4a..93851595f 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11970,11 +11970,7 @@ STR16 szRebelCommandText[] = L"%s Send %s to prepare this mission? She will return in 24 hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", - L"Mission \"%s\" has expired and is no longer in effect." - - - - + L"Mission \"%s\" has expired and is no longer in effect.", }; STR16 szRebelCommandHelpText[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 291985904..d0a3afcdd 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -2488,7 +2488,8 @@ STR16 pAssignmentStrings[] = L"Burial", L"Admin", // TODO.Translate L"Explore", // TODO.Translate - L"Event"// rftr: merc is on a mini event // TODO: translate + L"Event",// rftr: merc is on a mini event // TODO: translate + L"Mission", // rftr: rebel command }; @@ -11856,12 +11857,16 @@ STR16 gLbeStatsDesc[14] = 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"National Overview", + L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"Regional (2)", + L"National (1)", + L"Mission (3)", L"Supplies:", L"Incoming Supplies", + L"Intel:", L"/day", L"Current Directive", L"Improve Directive ($%d)", @@ -11919,17 +11924,55 @@ STR16 szRebelCommandText[] = // TODO.Translate L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", + L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect.", }; 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"|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.\n \n+%d (Base income)", 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"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", 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.", - L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"This Admin Action applies its bonus to town sectors only.", //TODO.Translate L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -12022,6 +12065,26 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = // TODO: Translate { L"The robot's installed weapon cannot be changed.", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 554781897..cbcbdac34 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -2519,7 +2519,8 @@ STR16 pAssignmentStrings[] = L"Burial", L"Admin", // TODO.Translate L"Explore", // TODO.Translate - L"Event"// rftr: merc is on a mini event // TODO: translate + L"Event",// rftr: merc is on a mini event // TODO: translate + L"Mission", // rftr: rebel command }; STR16 pMilitiaString[] = @@ -11778,12 +11779,16 @@ STR16 gLbeStatsDesc[14] = 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"National Overview", + L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"Regional (2)", + L"National (1)", + L"Mission (3)", L"Supplies:", L"Incoming Supplies", + L"Intel:", L"/day", L"Current Directive", L"Improve Directive ($%d)", @@ -11841,17 +11846,55 @@ STR16 szRebelCommandText[] = // TODO.Translate L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", + L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect.", }; 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"|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.\n \n+%d (Base income)", 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"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", 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.", - L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"This Admin Action applies its bonus to town sectors only.", //TODO.Translate L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -11944,6 +11987,26 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = // TODO: Translate { L"The robot's installed weapon cannot be changed.", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 658de32f2..595d1e8ea 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -2474,7 +2474,8 @@ STR16 pAssignmentStrings[] = L"Burial", L"Admin", // TODO.Translate L"Explore", // TODO.Translate - L"Event"// rftr: merc is on a mini event // TODO: translate + L"Event",// rftr: merc is on a mini event // TODO: translate + L"Mission", // rftr: rebel command }; @@ -11865,12 +11866,16 @@ STR16 gLbeStatsDesc[14] = 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"National Overview", + L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"Regional (2)", + L"National (1)", + L"Mission (3)", L"Supplies:", L"Incoming Supplies", + L"Intel:", L"/day", L"Current Directive", L"Improve Directive ($%d)", @@ -11928,17 +11933,55 @@ STR16 szRebelCommandText[] = // TODO.Translate L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", + L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect.", }; 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"|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.\n \n+%d (Base income)", 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"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", 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.", - L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"This Admin Action applies its bonus to town sectors only.", //TODO.Translate L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -12031,6 +12074,26 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = // TODO: Translate { L"The robot's installed weapon cannot be changed.", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 97513cf87..84ab44c3e 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -2486,7 +2486,8 @@ STR16 pAssignmentStrings[] = L"Burial", L"Admin", // TODO.Translate L"Explore", // TODO.Translate - L"Event"// rftr: merc is on a mini event // TODO: translate + L"Event",// rftr: merc is on a mini event // TODO: translate + L"Mission", // rftr: rebel command }; @@ -11878,12 +11879,16 @@ STR16 gLbeStatsDesc[14] = 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"National Overview", + L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"Regional (2)", + L"National (1)", + L"Mission (3)", L"Supplies:", L"Incoming Supplies", + L"Intel:", L"/day", L"Current Directive", L"Improve Directive ($%d)", @@ -11941,17 +11946,55 @@ STR16 szRebelCommandText[] = // TODO.Translate L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", + L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect.", }; 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"|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.\n \n+%d (Base income)", 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"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", 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.", - L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"This Admin Action applies its bonus to town sectors only.", //TODO.Translate L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -12044,6 +12087,26 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = // TODO: Translate { L"The robot's installed weapon cannot be changed.", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 5d0ee7cfe..ea60da77a 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -2480,7 +2480,8 @@ STR16 pAssignmentStrings[] = L"Burial", L"Admin", // TODO.Translate L"Explore", // TODO.Translate - L"Event"// rftr: merc is on a mini event // TODO: translate + L"Event",// rftr: merc is on a mini event // TODO: translate + L"Mission", // rftr: rebel command }; @@ -11859,12 +11860,16 @@ STR16 gLbeStatsDesc[14] = 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"National Overview", + L"Regional Overview", + L"Mission Overview", + L"Select View:", + L"Regional (2)", + L"National (1)", + L"Mission (3)", L"Supplies:", L"Incoming Supplies", + L"Intel:", L"/day", L"Current Directive", L"Improve Directive ($%d)", @@ -11922,17 +11927,55 @@ STR16 szRebelCommandText[] = // TODO.Translate L"<", L">", L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", + L"Insufficient supplies! Admin Actions have been DISABLED.", + L"New missions will be available every %d hours.", + L"Mission preparations in progress.", + L"Mission duration: %d days", + L"Chance of success: %d%s", + L"[REDACTED]", + L"Name: %s", + L"Location: %s", + L"Assignment: %s", + L"Contract: %d days", + L"Contract: %d hours", + L"Contract: ---", + L"Agent bonus:", + L"Chance of success +%d%s (%s)", + L"Deployment range +%d (%s)", + L"Time +%2.0f%s (%s)", + L"Vision -%2.0f%s (%s)", + L"Gear quality -%d (%s)", + L"Overall stats -%d (%s)", + L"Max trainers: %d (%s)", + L"Duration +%d hours (%s)", + L"Agent not in loyal town", + L"Agent unavailable", + L"Agent contract expiring", + L"Battle in progress", + L"Start Mission (%d supplies)", + L"View active mission effects", + L"View available mission list", + L"New missions will be available on Day %d at 00:00.", + L"Active missions:", + L"%s - Preparing - Ready on Day %d, %02d:%02d", + L"%s - Active - Expires on Day %d, %02d:%02d", + L"[%s (%d supplies)]", + L"%s Send a rebel agent to prepare this mission?", + L"%s Send %s to prepare this mission? He will return in 24 hours.", + L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"Mission \"%s\" is now in effect.", + L"Preparations for mission \"%s\" failed.", + L"Mission \"%s\" has expired and is no longer in effect.", }; 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"|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.\n \n+%d (Base income)", 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"|L|o|y|a|l|t|y\n \nThe effectiveness of many Administrative Actions depends on\nthe region's loyalty to your cause. It is in your best interest\nto raise loyalty as high as possible.", 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.", - L"|G|r|a|n|t |S|u|p|p|l|i|e|s\n \nSend supplies to the admin team here and allow them to use them\nas needed. This will increase the region's loyalty by a small amount\neach time you do this. However, doing this will slightly increase\nthe cost of enacting regional policies.", L"This Admin Action applies its bonus to town sectors only.", //TODO.Translate L"This Admin Action applies its bonus to town sectors, and\nsectors immediately adjacent to them.", L"This Admin Action applies its bonus to town sectors, one\nsector away at Tier 1, and up to two sectors away at Tier 2.", @@ -12025,6 +12068,26 @@ STR16 szRebelCommandDirectivesText[] = // TODO.Translate L"Improving this directive will increase the number of volunteers gained per day.", }; +STR16 szRebelCommandAgentMissionsText[] = +{ + L"Deep Deployment", + L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Strategic Intel", + L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", + L"Improve Local Shops", + L"Set up ways for merchants across the country to acquire better goods more easily. Shopkeepers will have better than usual inventories.", + L"Slow Strategic Decisions", + L"Sow confusion and misdirection at the highest levels of enemy command. The enemy takes longer to make decisions at a strategic level.", + L"Lower Readiness", + L"Trick enemy soldiers into letting their guard down. Enemy soldiers have reduced vision range until they are alerted to your mercs' presence.", + L"Sabotage Equipment", + L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", + L"Sabotage Vehicles", + 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.", +}; + STR16 szRobotText[] = // TODO: Translate { L"The robot's installed weapon cannot be changed.", From 5000f965e1d653fae96b45d5b33128197aa8086f Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sat, 22 Oct 2022 17:54:06 -0700 Subject: [PATCH 23/52] Add "Soldier Bounties" mission --- GameSettings.cpp | 26 +++++- GameSettings.h | 18 +++++ Laptop/finances.cpp | 4 + Laptop/finances.h | 1 + Strategic/Rebel Command.cpp | 153 +++++++++++++++++++++++++++++++----- Strategic/Rebel Command.h | 6 +- Tactical/Soldier Ani.cpp | 4 + Utils/_ChineseText.cpp | 7 ++ Utils/_DutchText.cpp | 7 ++ Utils/_EnglishText.cpp | 7 ++ Utils/_FrenchText.cpp | 7 ++ Utils/_GermanText.cpp | 7 ++ Utils/_ItalianText.cpp | 7 ++ Utils/_PolishText.cpp | 7 ++ Utils/_RussianText.cpp | 7 ++ 15 files changed, 242 insertions(+), 26 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 33734547d..a130d2e91 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 b4c46b194..0f302a875 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 261f02a82..a65f22889 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 b617e1980..6c03e4861 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 13de9e879..cbcf5359e 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 314eaa7f3..073349e11 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 431f08b9e..a615b8638 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 ac3a36c04..69766222b 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 af0fe600b..f2557313a 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 93851595f..da759cf23 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 d0a3afcdd..1324f3dcd 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 cbcbdac34..b3eae88a5 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 595d1e8ea..cbf94dc4a 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 84ab44c3e..a50c39820 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 ea60da77a..968940e0c 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 From 89285b49619d78f7a641c85da5cfb6f94a58beff Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sat, 22 Oct 2022 21:54:14 -0700 Subject: [PATCH 24/52] Remove debug mission randomisation General cleanup --- Strategic/Rebel Command.cpp | 14 -------------- Strategic/Rebel Command.h | 3 +-- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index cbcf5359e..4fe88e819 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -1161,16 +1161,6 @@ void UpdateAdminActionChangeList(INT16 regionId) BOOLEAN EnterWebsite() { - // debugging. todo: randomise missions in DailyUpdate and save them in rebelcommandsaveinfo - for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) - { - //missionIndex[i] = Random(RCAM_NUM_MISSIONS-1) + 1; - rebelCommandSaveInfo.availableMissions[i] = Random(RCAM_NUM_MISSIONS); - agentIndex[i] = -1; - } - //missionIndex[0] = RCAM_TRAIN_MILITIA_ANYWHERE; - //missionIndex[1] = RCAM_IMPROVE_LOCAL_SHOPS; - UpdateAdminActionChangeList(iCurrentRegionId); // make sure we have a valid directive @@ -3608,10 +3598,6 @@ void DailyUpdate() iIncomingSuppliesPerDay = CalcIncomingSuppliesPerDay(static_cast(directive)); rebelCommandSaveInfo.iSupplies += iIncomingSuppliesPerDay; - // rftr todo: check bitmask - //if (purchasing supplies through agent mission) - // what gets subtracted? current balance? daily income? how do we pick? - // get regional bonuses INT16 intelGain = 0; INT16 supplyGain = 0; diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index 073349e11..fbd4109d7 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -100,8 +100,7 @@ enum RebelCommandAgentMissions RCAM_NUM_MISSIONS, - // ideas/unimplemented - rename some? - // need to have permanent and temporary boons + // ideas/unimplemented RCAM_SEND_SUPPLIES_TO_TOWN, RCAM_BOOST_TOWN_ADMIN_ACTIONS, RCAM_PROCURE_ITEMS, From 337bb023e3bff5f95cb1e739c9c811f9c46b894b Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sat, 22 Oct 2022 23:17:19 -0700 Subject: [PATCH 25/52] Don't show "Mission prep in progress" if there are none --- Strategic/Rebel Command.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 4fe88e819..ece7f56ec 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2576,7 +2576,11 @@ void RenderMissionOverview() const INT8 interval = gRebelCommandSettings.iMissionRefreshTimeDays; nextMissionAvailableDay += (interval - (nextMissionAvailableDay % interval)); - DrawTextToScreen(szRebelCommandText[RCT_MISSION_PREP_IN_PROGRESS], WEBSITE_LEFT + 15, WEBSITE_TOP + 155, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + if (missionMap.size() > 0) + { + DrawTextToScreen(szRebelCommandText[RCT_MISSION_PREP_IN_PROGRESS], WEBSITE_LEFT + 15, WEBSITE_TOP + 155, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + } + swprintf(sText, szRebelCommandText[RCT_MISSION_NEXT_AVAILABILITY], nextMissionAvailableDay); DrawTextToScreen(sText, WEBSITE_LEFT + 15, WEBSITE_TOP + 175, WEBSITE_WIDTH - 30, FONT14ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); } From affc2aec312a89a485cb7df785bf47b6ea10010e Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sun, 23 Oct 2022 01:27:13 -0700 Subject: [PATCH 26/52] Add mission help screen Initialise missions properly --- Strategic/Rebel Command.cpp | 50 ++++++++++++++++++++++++++++++++++--- Utils/_ChineseText.cpp | 5 +++- Utils/_DutchText.cpp | 5 +++- Utils/_EnglishText.cpp | 5 +++- Utils/_FrenchText.cpp | 5 +++- Utils/_GermanText.cpp | 5 +++- Utils/_ItalianText.cpp | 5 +++- Utils/_PolishText.cpp | 5 +++- Utils/_RussianText.cpp | 5 +++- 9 files changed, 79 insertions(+), 11 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index ece7f56ec..3956b4b26 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -327,6 +327,9 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_MISSION_START_BUTTON, RCT_MISSION_VIEW_ACTIVE, RCT_MISSION_VIEW_LIST, + RCT_MISSION_HELP_1, + RCT_MISSION_HELP_2, + RCT_MISSION_HELP_3, RCT_MISSION_NEXT_AVAILABILITY, RCT_MISSION_ACTIVE_MISSIONS, RCT_MISSION_LIST_PREPARING, @@ -394,6 +397,7 @@ enum MissionOverviewSubview { MOS_MISSION_LIST, MOS_ACTIVE_MISSION_EFFECTS, + MOS_HELP, }; struct MissionFirstEvent @@ -2536,6 +2540,17 @@ void RenderMissionOverview() // title RenderHeader(RCT_AGENT_OVERVIEW); + // display help button + btnId = CreateTextButton(L"?", FONT12ARIAL, FONT_MCOLOR_WHITE, FONT_BLACK, BUTTON_USE_DEFAULT, WEBSITE_LEFT + 15, WEBSITE_TOP + 40, 30, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + { + ButtonHelper(btn, reason, []() + { + missionOverviewSubview = missionOverviewSubview == MOS_HELP ? MOS_MISSION_LIST : MOS_HELP; + }); + }); + + btnIds.push_back(btnId); + // toggle between mission picker and active mission effects switch (missionOverviewSubview) { @@ -2544,10 +2559,11 @@ void RenderMissionOverview() break; case MOS_ACTIVE_MISSION_EFFECTS: + case MOS_HELP: swprintf(sText, szRebelCommandText[RCT_MISSION_VIEW_LIST]); break; } - btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, WEBSITE_LEFT + 15, WEBSITE_TOP + 40, 470, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) + btnId = CreateTextButton(sText, FONT10ARIAL, FONT_MCOLOR_LTYELLOW, FONT_BLACK, BUTTON_USE_DEFAULT, WEBSITE_LEFT + 50, WEBSITE_TOP + 40, 435, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, [](GUI_BUTTON* btn, INT32 reason) { ButtonHelper(btn, reason, []() { @@ -2558,6 +2574,7 @@ void RenderMissionOverview() break; case MOS_ACTIVE_MISSION_EFFECTS: + case MOS_HELP: missionOverviewSubview = MOS_MISSION_LIST; break; } @@ -2645,6 +2662,17 @@ void RenderMissionOverview() } } break; + + case MOS_HELP: + { + UINT16 y = WEBSITE_TOP + 100; + y += DisplayWrappedString(WEBSITE_LEFT + 35, y, 400, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_MISSION_HELP_1], FONT_MCOLOR_BLACK, FALSE, 0); + y += 20; + y += DisplayWrappedString(WEBSITE_LEFT + 35, y, 400, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_MISSION_HELP_2], FONT_MCOLOR_BLACK, FALSE, 0); + y += 20; + DisplayWrappedString(WEBSITE_LEFT + 35, y, 400, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_MISSION_HELP_3], FONT_MCOLOR_BLACK, FALSE, 0); + } + break; } // "new missions every X hours" text @@ -3891,6 +3919,12 @@ void Init() rebelCommandSaveInfo.regions[a].actionLevels[b] = 0; } } + + // init missions + for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + rebelCommandSaveInfo.availableMissions[i] = RCAM_NONE; + } } BOOLEAN Load(HWFILE file) @@ -3908,6 +3942,16 @@ BOOLEAN Load(HWFILE file) Init(); } + // missions update check + if (rebelCommandSaveInfo.availableMissions[0] == rebelCommandSaveInfo.availableMissions[1] && rebelCommandSaveInfo.availableMissions[0] != RCAM_NONE) + { + // init missions + for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) + { + rebelCommandSaveInfo.availableMissions[i] = RCAM_NONE; + } + } + // go through every strategic event to find active agent missions std::vector> missions = GetAllStrategicEventsOfType(EVENT_REBELCOMMAND); missionMap.clear(); @@ -4091,8 +4135,8 @@ void SetupInfo() // { new skill traits to check }, // { old skill traits to check. use -1 to not match against anything }, // { duration bonus for checked trait }, - // { float modifier for checked trait. either this line or the next is zeroed out. }, - // { int modifier for checked trait. either this line or the previous is zeroed out. }, + // { float modifier for checked trait }, + // { int modifier for checked trait }, // { value to place in extra bits, used to determine what bonus is applied. } // } //RCAM_DEEP_DEPLOYMENT diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 69766222b..822eb169f 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11962,9 +11962,12 @@ STR16 szRebelCommandText[] = L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index f2557313a..d5409d804 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11972,9 +11972,12 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index da759cf23..4ff777845 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11962,9 +11962,12 @@ STR16 szRebelCommandText[] = L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 1324f3dcd..0ea13767e 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11954,9 +11954,12 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index b3eae88a5..275ca0d0a 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11876,9 +11876,12 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index cbf94dc4a..ad0d2c355 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11963,9 +11963,12 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index a50c39820..ffe9bbf50 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11976,9 +11976,12 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 968940e0c..35edf34ba 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11957,9 +11957,12 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", - L"Start Mission (%d supplies)", + L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", + L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", L"Active missions:", L"%s - Preparing - Ready on Day %d, %02d:%02d", From 57ae2c69489bd8d9340411aefe152390941befb4 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sun, 23 Oct 2022 01:36:54 -0700 Subject: [PATCH 27/52] Rename StartMission() to PrepareMission() --- Strategic/Rebel Command.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 3956b4b26..e7508f43d 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -46,7 +46,7 @@ How to add a new mission: - add values to MissionHelpers::missionInfo table in SetupInfo() - add to valid check in HandleStrategicEvent() (allows advance from first event/prepare to second event/active effect) - add to SetupMissionAgentBox() (mission description and merc bonus text) -- add to StartMission() +- add to PrepareMission() - add mission-specific functions - rftr todo: ??? @@ -503,7 +503,7 @@ void SetRegionHelpText(INT32 reason, MOUSE_REGION& helpTextRegion, RebelCommandH void SetupAdminActionBox(const UINT8 actionIndex, const UINT16 descriptionText, const UINT16 buttonText); BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index); void SetWebsiteView(WebsiteState newState); -void StartMission(INT8 index); +void PrepareMission(INT8 index); void ToggleWebsiteView(); void UpdateAdminActionChangeList(INT16 regionId); @@ -2522,7 +2522,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) { const INT8 index = MSYS_GetBtnUserData(btn, 0); ButtonHelper(btn, reason, [btn, index]() { - StartMission(index); + PrepareMission(index); }); }); MSYS_SetBtnUserData(btnId, 0, index); @@ -2680,7 +2680,7 @@ void RenderMissionOverview() DrawTextToScreen(sText, WEBSITE_LEFT + 22, WEBSITE_TOP + WEBSITE_HEIGHT - 14, 0, FONT10ARIAL, FONT_MCOLOR_BLACK, FONT_MCOLOR_BLACK, FALSE, 0); } -void StartMission(INT8 index) +void PrepareMission(INT8 index) { const INT32 cost = GetMissionCost(); if (rebelCommandSaveInfo.iSupplies < cost) From 53779635ce57930faec63ff3a47d3311bbe1effc Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sun, 23 Oct 2022 01:53:23 -0700 Subject: [PATCH 28/52] Put Soldier Bounties mission into alphabetic order --- Strategic/Rebel Command.cpp | 64 ++++++++++++++++++------------------- Strategic/Rebel Command.h | 2 +- Utils/_ChineseText.cpp | 4 +-- Utils/_DutchText.cpp | 4 +-- Utils/_EnglishText.cpp | 4 +-- Utils/_FrenchText.cpp | 4 +-- Utils/_GermanText.cpp | 4 +-- Utils/_ItalianText.cpp | 4 +-- Utils/_PolishText.cpp | 4 +-- Utils/_RussianText.cpp | 4 +-- 10 files changed, 49 insertions(+), 49 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index e7508f43d..50e63095c 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2171,8 +2171,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_TITLE]); break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE]); break; default: swprintf(sText, L"Mission Index: %d", rebelCommandSaveInfo.availableMissions[index]); break; } @@ -2189,8 +2189,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionDurationBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration; break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: missionDurationBase = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; break; default: break; } @@ -2210,8 +2210,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionSuccessChanceBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionSuccessChance; break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: missionSuccessChanceBase = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; break; default: break; } @@ -2228,8 +2228,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_DESC]); break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_DESC]); 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; } @@ -2412,15 +2412,6 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } break; - case RCAM_TRAIN_MILITIA_ANYWHERE: - { - intModifier = max(intModifier, 1); - CHAR16 text[100]; - swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_MAX_TRAINERS], intModifier, locSkillText[intModifierSkill]); - agentBonusText.push_back(text); - } - break; - case RCAM_SOLDIER_BOUNTIES_KINGPIN: { floatModifier = max(floatModifier, 1.f); @@ -2452,6 +2443,15 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } break; + case RCAM_TRAIN_MILITIA_ANYWHERE: + { + intModifier = max(intModifier, 1); + CHAR16 text[100]; + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_MAX_TRAINERS], intModifier, locSkillText[intModifierSkill]); + agentBonusText.push_back(text); + } + break; + default: break; } @@ -2775,14 +2775,6 @@ void PrepareMission(INT8 index) } break; - case RCAM_TRAIN_MILITIA_ANYWHERE: - { - missionTitle = RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE; - missionSuccessChance = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; - missionDuration = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; - } - break; - case RCAM_SOLDIER_BOUNTIES_KINGPIN: { missionTitle = RCAMT_SOLDIER_BOUNTIES_KINGPIN_TITLE; @@ -2791,6 +2783,14 @@ void PrepareMission(INT8 index) } break; + case RCAM_TRAIN_MILITIA_ANYWHERE: + { + missionTitle = RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE; + missionSuccessChance = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; + missionDuration = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; + } + break; + default: break; } @@ -4200,16 +4200,6 @@ void SetupInfo() {gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Covert, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Demolitions, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Heavy_Weapons}, {MissionHelpers::SABOTAGE_MECHANICAL_UNITS_COVERT, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_DEMOLITIONS, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_HEAVY_WEAPONS} }); - //RCAM_TRAIN_MILITIA_ANYWHERE - MissionHelpers::missionInfo.push_back( - { - {COVERT_NT, SURVIVAL_NT, TEACHING_NT}, - {-1, CAMOUFLAGED_OT, TEACHING_OT}, - {gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Covert, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Survival, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Teaching}, - {0.f, 0.f, 0.f}, - {gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching}, - {0, 0, MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING} - }); //RCAM_SOLDIER_BOUNTIES_KINGPIN MissionHelpers::missionInfo.push_back( { @@ -4220,6 +4210,16 @@ void SetupInfo() {0, 0, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Snitch, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Demolitions}, {0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_OFFICER_PAYOUTS, 0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS} }); + //RCAM_TRAIN_MILITIA_ANYWHERE + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, SURVIVAL_NT, TEACHING_NT}, + {-1, CAMOUFLAGED_OT, TEACHING_OT}, + {gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Covert, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Survival, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Teaching}, + {0.f, 0.f, 0.f}, + {gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching}, + {0, 0, MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING} + }); } void UpgradeMilitiaStats() @@ -4639,8 +4639,8 @@ void HandleStrategicEvent(const UINT32 eventParam) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: case RCAM_SABOTAGE_MECHANICAL_UNITS: - case RCAM_TRAIN_MILITIA_ANYWHERE: case RCAM_SOLDIER_BOUNTIES_KINGPIN: + case RCAM_TRAIN_MILITIA_ANYWHERE: { validMission = TRUE; } diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index fbd4109d7..4ce6e04e7 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -95,8 +95,8 @@ enum RebelCommandAgentMissions RCAM_REDUCE_UNALERTED_ENEMY_VISION, // aka Lower Readiness RCAM_SABOTAGE_INFANTRY_EQUIPMENT, // aka Sabotage Equipment RCAM_SABOTAGE_MECHANICAL_UNITS, // aka Sabotage Vehicles - RCAM_TRAIN_MILITIA_ANYWHERE, RCAM_SOLDIER_BOUNTIES_KINGPIN, + RCAM_TRAIN_MILITIA_ANYWHERE, RCAM_NUM_MISSIONS, diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 822eb169f..bc67a3ce0 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -12097,10 +12097,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index d5409d804..35bbac4fd 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -12107,10 +12107,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 4ff777845..331bae0d5 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -12097,10 +12097,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 0ea13767e..a04b38db8 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -12089,10 +12089,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 275ca0d0a..576d94cc7 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -12011,10 +12011,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index ad0d2c355..321075a2a 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -12098,10 +12098,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index ffe9bbf50..958d425c6 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -12111,10 +12111,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 35edf34ba..2cc5aeec7 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -12092,10 +12092,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate From 9ac0795507a45b3fb1d58cedfceb5fc4ae71b03f Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sun, 23 Oct 2022 01:53:23 -0700 Subject: [PATCH 29/52] Put Soldier Bounties mission into alphabetic order --- Strategic/Rebel Command.cpp | 66 ++++++++++++++++++------------------- Strategic/Rebel Command.h | 2 +- Utils/_ChineseText.cpp | 4 +-- Utils/_DutchText.cpp | 4 +-- Utils/_EnglishText.cpp | 4 +-- Utils/_FrenchText.cpp | 4 +-- Utils/_GermanText.cpp | 4 +-- Utils/_ItalianText.cpp | 4 +-- Utils/_PolishText.cpp | 4 +-- Utils/_RussianText.cpp | 4 +-- 10 files changed, 50 insertions(+), 50 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index e7508f43d..57114ecb3 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -383,8 +383,8 @@ enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentM MISSION_TEXT(REDUCE_UNALERTED_ENEMY_VISION) MISSION_TEXT(SABOTAGE_INFANTRY_EQUIPMENT) MISSION_TEXT(SABOTAGE_MECHANICAL_UNITS) - MISSION_TEXT(TRAIN_MILITIA_ANYWHERE) MISSION_TEXT(SOLDIER_BOUNTIES_KINGPIN) + MISSION_TEXT(TRAIN_MILITIA_ANYWHERE) }; enum ChangeAdminActionState @@ -2171,8 +2171,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_TITLE]); break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE]); break; default: swprintf(sText, L"Mission Index: %d", rebelCommandSaveInfo.availableMissions[index]); break; } @@ -2189,8 +2189,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionDurationBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration; break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: missionDurationBase = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; break; default: break; } @@ -2210,8 +2210,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionSuccessChanceBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionSuccessChance; break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: missionSuccessChanceBase = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; break; default: break; } @@ -2228,8 +2228,8 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_DESC]); break; 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; + case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_DESC]); 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; } @@ -2412,15 +2412,6 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } break; - case RCAM_TRAIN_MILITIA_ANYWHERE: - { - intModifier = max(intModifier, 1); - CHAR16 text[100]; - swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_MAX_TRAINERS], intModifier, locSkillText[intModifierSkill]); - agentBonusText.push_back(text); - } - break; - case RCAM_SOLDIER_BOUNTIES_KINGPIN: { floatModifier = max(floatModifier, 1.f); @@ -2452,6 +2443,15 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } break; + case RCAM_TRAIN_MILITIA_ANYWHERE: + { + intModifier = max(intModifier, 1); + CHAR16 text[100]; + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_MAX_TRAINERS], intModifier, locSkillText[intModifierSkill]); + agentBonusText.push_back(text); + } + break; + default: break; } @@ -2775,14 +2775,6 @@ void PrepareMission(INT8 index) } break; - case RCAM_TRAIN_MILITIA_ANYWHERE: - { - missionTitle = RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE; - missionSuccessChance = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; - missionDuration = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; - } - break; - case RCAM_SOLDIER_BOUNTIES_KINGPIN: { missionTitle = RCAMT_SOLDIER_BOUNTIES_KINGPIN_TITLE; @@ -2791,6 +2783,14 @@ void PrepareMission(INT8 index) } break; + case RCAM_TRAIN_MILITIA_ANYWHERE: + { + missionTitle = RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE; + missionSuccessChance = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; + missionDuration = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; + } + break; + default: break; } @@ -4200,16 +4200,6 @@ void SetupInfo() {gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Covert, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Demolitions, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Heavy_Weapons}, {MissionHelpers::SABOTAGE_MECHANICAL_UNITS_COVERT, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_DEMOLITIONS, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_HEAVY_WEAPONS} }); - //RCAM_TRAIN_MILITIA_ANYWHERE - MissionHelpers::missionInfo.push_back( - { - {COVERT_NT, SURVIVAL_NT, TEACHING_NT}, - {-1, CAMOUFLAGED_OT, TEACHING_OT}, - {gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Covert, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Survival, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Teaching}, - {0.f, 0.f, 0.f}, - {gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching}, - {0, 0, MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING} - }); //RCAM_SOLDIER_BOUNTIES_KINGPIN MissionHelpers::missionInfo.push_back( { @@ -4220,6 +4210,16 @@ void SetupInfo() {0, 0, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Snitch, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Demolitions}, {0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_OFFICER_PAYOUTS, 0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS} }); + //RCAM_TRAIN_MILITIA_ANYWHERE + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, SURVIVAL_NT, TEACHING_NT}, + {-1, CAMOUFLAGED_OT, TEACHING_OT}, + {gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Covert, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Survival, gRebelCommandSettings.iTrainMilitiaAnywhereDuration_Bonus_Teaching}, + {0.f, 0.f, 0.f}, + {gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching}, + {0, 0, MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING} + }); } void UpgradeMilitiaStats() @@ -4639,8 +4639,8 @@ void HandleStrategicEvent(const UINT32 eventParam) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: case RCAM_SABOTAGE_MECHANICAL_UNITS: - case RCAM_TRAIN_MILITIA_ANYWHERE: case RCAM_SOLDIER_BOUNTIES_KINGPIN: + case RCAM_TRAIN_MILITIA_ANYWHERE: { validMission = TRUE; } diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index fbd4109d7..4ce6e04e7 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -95,8 +95,8 @@ enum RebelCommandAgentMissions RCAM_REDUCE_UNALERTED_ENEMY_VISION, // aka Lower Readiness RCAM_SABOTAGE_INFANTRY_EQUIPMENT, // aka Sabotage Equipment RCAM_SABOTAGE_MECHANICAL_UNITS, // aka Sabotage Vehicles - RCAM_TRAIN_MILITIA_ANYWHERE, RCAM_SOLDIER_BOUNTIES_KINGPIN, + RCAM_TRAIN_MILITIA_ANYWHERE, RCAM_NUM_MISSIONS, diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 822eb169f..bc67a3ce0 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -12097,10 +12097,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index d5409d804..35bbac4fd 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -12107,10 +12107,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 4ff777845..331bae0d5 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -12097,10 +12097,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 0ea13767e..a04b38db8 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -12089,10 +12089,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 275ca0d0a..576d94cc7 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -12011,10 +12011,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index ad0d2c355..321075a2a 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -12098,10 +12098,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index ffe9bbf50..958d425c6 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -12111,10 +12111,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 35edf34ba..2cc5aeec7 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -12092,10 +12092,10 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", 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.", + 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.", }; STR16 szRobotText[] = // TODO: Translate From a35d741403e3c22fdf2a35ba58910ed009b98d8a Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 25 Oct 2022 01:35:18 -0700 Subject: [PATCH 30/52] Add "Disrupt ASD" mission --- GameSettings.cpp | 12 ++ GameSettings.h | 12 ++ Strategic/ASD.cpp | 14 +++ Strategic/ASD.h | 2 + Strategic/Rebel Command.cpp | 219 +++++++++++++++++++++++++++++++++++- Strategic/Rebel Command.h | 7 +- Utils/_ChineseText.cpp | 5 + Utils/_DutchText.cpp | 5 + Utils/_EnglishText.cpp | 5 + Utils/_FrenchText.cpp | 5 + Utils/_GermanText.cpp | 5 + Utils/_ItalianText.cpp | 5 + Utils/_PolishText.cpp | 5 + Utils/_RussianText.cpp | 5 + 14 files changed, 301 insertions(+), 5 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index a130d2e91..265a1982b 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4180,6 +4180,18 @@ void LoadRebelCommandSettings() gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Stealthy = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_DURATION_BONUS_STEALTHY" , 36, 0, 255); gRebelCommandSettings.iDeepDeploymentDuration_Bonus_Survival = iniReader.ReadInteger("Rebel Command Settings", "DEEP_DEPLOYMENT_DURATION_BONUS_SURVIVAL" , 36, 0, 255); + gRebelCommandSettings.iDisruptAsdSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.fDisruptAsdIncomeReductionModifier = iniReader.ReadFloat("Rebel Command Settings", "DISRUPT_ASD_INCOME_MODIFIER", 0.5f, 0.f, 1.f); + gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Covert = iniReader.ReadFloat("Rebel Command Settings", "DISRUPT_ASD_INCOME_MODIFIER_COVERT", 0.5f, 0.f, 1.f); + gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Demolitions = iniReader.ReadFloat("Rebel Command Settings", "DISRUPT_ASD_INCOME_MODIFIER_DEMOLITIONS", 0.5f, 0.f, 1.f); + gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Nightops = iniReader.ReadFloat("Rebel Command Settings", "DISRUPT_ASD_INCOME_MODIFIER_NIGHTOPS", 0.5f, 0.f, 1.f); + gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Technician = iniReader.ReadFloat("Rebel Command Settings", "DISRUPT_ASD_INCOME_MODIFIER_TECHNICIAN", 0.5f, 0.f, 1.f); + gRebelCommandSettings.iDisruptAsdDuration = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_DURATION", 72, 0, 255); + gRebelCommandSettings.iDisruptAsdDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_DURATION_BONUS_COVERT", 48, 0, 255); + gRebelCommandSettings.iDisruptAsdDuration_Bonus_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_DURATION_BONUS_DEMOLITIONS", 48, 0, 255); + gRebelCommandSettings.iDisruptAsdDuration_Bonus_Nightops = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_DURATION_BONUS_NIGHTOPS", 48, 0, 255); + gRebelCommandSettings.iDisruptAsdDuration_Bonus_Technician = iniReader.ReadInteger("Rebel Command Settings", "DISRUPT_ASD_DURATION_BONUS_TECHNICIAN", 48, 0, 255); + gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_SUCCESS_CHANCE", 50, 0, 100); gRebelCommandSettings.iGetEnemyMovementTargetsDuration = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_DURATION", 72, 0, 255); gRebelCommandSettings.iGetEnemyMovementTargetsDuration_Bonus_Covert = iniReader.ReadInteger("Rebel Command Settings", "STRATEGIC_INTEL_DURATION_BONUS_COVERT", 48, 0, 255); diff --git a/GameSettings.h b/GameSettings.h index 0f302a875..61989eb34 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1865,6 +1865,18 @@ typedef struct UINT8 iDeepDeploymentDuration_Bonus_Stealthy; UINT8 iDeepDeploymentDuration_Bonus_Survival; + INT8 iDisruptAsdSuccessChance; + FLOAT fDisruptAsdIncomeReductionModifier; + FLOAT fDisruptAsdIncomeReductionModifier_Covert; + FLOAT fDisruptAsdIncomeReductionModifier_Demolitions; + FLOAT fDisruptAsdIncomeReductionModifier_Nightops; + FLOAT fDisruptAsdIncomeReductionModifier_Technician; + UINT8 iDisruptAsdDuration; + UINT8 iDisruptAsdDuration_Bonus_Covert; + UINT8 iDisruptAsdDuration_Bonus_Demolitions; + UINT8 iDisruptAsdDuration_Bonus_Nightops; + UINT8 iDisruptAsdDuration_Bonus_Technician; + INT8 iGetEnemyMovementTargetsSuccessChance; UINT8 iGetEnemyMovementTargetsDuration; UINT8 iGetEnemyMovementTargetsDuration_Bonus_Covert; diff --git a/Strategic/ASD.cpp b/Strategic/ASD.cpp index 84c670850..6d5861dec 100644 --- a/Strategic/ASD.cpp +++ b/Strategic/ASD.cpp @@ -52,6 +52,7 @@ #include "Sound Control.h" #include "renderworld.h" #include "Isometric Utils.h" +#include "Rebel Command.h" #endif @@ -548,9 +549,22 @@ UINT32 ASDResourceCostMoney( UINT8 aType ) return gGameExternalOptions.gASDResource_Cost[aType]; } +INT32 GetStrategicAIResourceCount( UINT8 aType ) +{ + if (aType < 0 || aType >= ASD_RESOURCE_MAX) + return 0; + + return gASDResource[aType]; +} + // add resources to the AIs resource pool void AddStrategicAIResources( UINT8 aType, INT32 aAmount ) { + if (aType == ASD_MONEY) + { + aAmount *= RebelCommand::GetASDIncomeModifier(); + } + gASDResource[aType] = max( 0, gASDResource[aType] + aAmount ); if ( aType == ASD_HELI ) diff --git a/Strategic/ASD.h b/Strategic/ASD.h index 0b786fbec..62cd5b185 100644 --- a/Strategic/ASD.h +++ b/Strategic/ASD.h @@ -56,6 +56,8 @@ void SetASDFlag( UINT32 aFlag ); UINT32 ASDResourceDeliveryTime( UINT8 aType ); UINT32 ASDResourceCostMoney( UINT8 aType ); +INT32 GetStrategicAIResourceCount( UINT8 aType ); + // add resources to the AIs resource pool void AddStrategicAIResources( UINT8 aType, INT32 aAmount ); diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 57114ecb3..9997934bc 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -63,6 +63,7 @@ Points of interest: #else #include "Rebel Command.h" +#include "ASD.h" #include "Button System.h" #include "Campaign.h" #include "Campaign Types.h" @@ -95,6 +96,8 @@ Points of interest: #include "Strategic Mines.h" #include "Strategic Movement.h" #include "Strategic Town Loyalty.h" +#include "Structure Wrap.h" +#include "Tactical Save.h" #include "Text.h" #include "Town Militia.h" #include "Utilities.h" @@ -125,12 +128,36 @@ extern GROUP *gpGroupList; namespace RebelCommand { +namespace ItemIdCache +{ + // cache these values on load so that we don't need to search for them every time something happens + std::vector gasCans; + std::vector firstAidKits; + std::vector medKits; + std::vector toolKits; + std::vector ammo[10]; // coolness + + void Clear() + { + gasCans.clear(); + firstAidKits.clear(); + medKits.clear(); + toolKits.clear(); + for (int i = 0; i < 10; ++i) + { + ammo[i].clear(); + } + } +} + namespace MissionHelpers { constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_COVERT = 1; constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_SCOUTING = 2; constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_STEALTHY = 3; constexpr UINT16 DEEP_DEPLOYMENT_RANGE_BONUS_SURVIVAL = 4; +constexpr UINT16 DISRUPT_ASD_STEAL_FUEL = 1; +constexpr UINT16 DISRUPT_ASD_DESTROY_RESERVES = 2; constexpr UINT16 REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_COVERT = 1; constexpr UINT16 REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_DEPUTY = 2; constexpr UINT16 REDUCE_STRATEGIC_DECISION_SPEED_MODIFIER_SNITCH = 3; @@ -310,6 +337,9 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_MISSION_AGENT_BONUS, RCT_MISSION_BONUS_SUCCESS_CHANCE, RCT_MISSION_BONUS_DEPLOY_RANGE, + RCT_MISSION_BONUS_ASD_INCOME_REDUCTION, + RCT_MISSION_BONUS_STEAL_FUEL, + RCT_MISSION_BONUS_DESTROY_RESERVES, RCT_MISSION_BONUS_DECISION_TIME, RCT_MISSION_BONUS_UNALERTED_VISION_PENALTY, RCT_MISSION_BONUS_INFANTRY_GEAR_QUALITY, @@ -377,6 +407,7 @@ enum RebelCommandDirectivesText // keep this synced with szRebelCommandDirective enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentMissionsText in the text files { MISSION_TEXT(DEEP_DEPLOYMENT) + MISSION_TEXT(DISRUPT_ASD) MISSION_TEXT(GET_ENEMY_MOVEMENT_TARGETS) MISSION_TEXT(IMPROVE_LOCAL_SHOPS) MISSION_TEXT(REDUCE_STRATEGIC_DECISION_SPEED) @@ -507,8 +538,10 @@ void PrepareMission(INT8 index); void ToggleWebsiteView(); void UpdateAdminActionChangeList(INT16 regionId); +void ApplyAdditionalASDEffects(); constexpr BOOLEAN CanAdminActionBeToggled(RebelCommandAdminActions action) { return action != RebelCommandAdminActions::RCAA_SUPPLY_LINE; } BOOLEAN CanAdminActionBeUsed(INT32 regionIndex, INT32 actionIndex); +void CreateItemAtAirport(UINT16 itemId, INT16 status); INT32 GetAdminActionCostForRegion(INT16 regionId); INT16 GetAdminActionInRegion(INT16 regionId, RebelCommandAdminActions adminAction); UINT8 GetRegionLoyalty(INT16 regionId); @@ -538,7 +571,6 @@ INT16 iCurrentRegionId = 1; INT32 iIncomingSuppliesPerDay = 0; SaveInfo rebelCommandSaveInfo; WebsiteState websiteState; -//INT8 missionIndex[NUM_ARC_AGENT_SLOTS]; INT8 agentIndex[NUM_ARC_AGENT_SLOTS]; std::unordered_map missionMap; MissionOverviewSubview missionOverviewSubview = MOS_MISSION_LIST; @@ -688,6 +720,29 @@ BOOLEAN CanAdminActionBeUsed(INT32 regionIndex, INT32 actionIndex) return TRUE; } +void CreateItemAtAirport(UINT16 itemId, INT16 status) +{ + // create an item - use bobby ray's delivery coordinates/gridno + OBJECTTYPE obj; + const BOOLEAN success = CreateItem(itemId, status, &obj); + if (!success) + { + ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, L"Warning - CreateItemAtAirport() failed for itemid %d", itemId); + return; + } + const BOOLEAN airportSectorLoaded = gWorldSectorX == BOBBYR_SHIPPING_DEST_SECTOR_X && gWorldSectorY == BOBBYR_SHIPPING_DEST_SECTOR_Y && gbWorldSectorZ == BOBBYR_SHIPPING_DEST_SECTOR_Z; + + if (airportSectorLoaded) + { + SetOpenableStructureToClosed( BOBBYR_SHIPPING_DEST_GRIDNO, 0 ); + AddItemToPool( BOBBYR_SHIPPING_DEST_GRIDNO, &obj, -1, 0, 0, 0 ); + } + else + { + AddItemsToUnLoadedSector(BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y, BOBBYR_SHIPPING_DEST_SECTOR_Z, BOBBYR_SHIPPING_DEST_GRIDNO, 1, &obj, 0, 0, 0, -1, FALSE); + } +} + INT32 GetAdminActionCostForRegion(INT16 regionId) { INT16 totalLocalActions = 0; @@ -1165,6 +1220,8 @@ void UpdateAdminActionChangeList(INT16 regionId) BOOLEAN EnterWebsite() { + // rftr todo: temp debugging + rebelCommandSaveInfo.availableMissions[0] = RCAM_DISRUPT_ASD; UpdateAdminActionChangeList(iCurrentRegionId); // make sure we have a valid directive @@ -2165,6 +2222,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) switch (rebelCommandSaveInfo.availableMissions[index]) { case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_TITLE]); break; + case RCAM_DISRUPT_ASD: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DISRUPT_ASD_TITLE]); break; case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE]); break; case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_TITLE]); break; case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_TITLE]); break; @@ -2183,6 +2241,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) switch (rebelCommandSaveInfo.availableMissions[index]) { case RCAM_DEEP_DEPLOYMENT: missionDurationBase = gRebelCommandSettings.iDeepDeploymentDuration; break; + case RCAM_DISRUPT_ASD: missionDurationBase = gRebelCommandSettings.iDisruptAsdDuration; break; case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionDurationBase = gRebelCommandSettings.iGetEnemyMovementTargetsDuration; break; case RCAM_IMPROVE_LOCAL_SHOPS: missionDurationBase = gRebelCommandSettings.iImproveLocalShopsDuration; break; case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionDurationBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration; break; @@ -2204,6 +2263,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) switch (rebelCommandSaveInfo.availableMissions[index]) { case RCAM_DEEP_DEPLOYMENT: missionSuccessChanceBase = gRebelCommandSettings.iDeepDeploymentSuccessChance; break; + case RCAM_DISRUPT_ASD: missionSuccessChanceBase = gRebelCommandSettings.iDisruptAsdSuccessChance; break; case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionSuccessChanceBase = gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance; break; case RCAM_IMPROVE_LOCAL_SHOPS: missionSuccessChanceBase = gRebelCommandSettings.iImproveLocalShopsSuccessChance; break; case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionSuccessChanceBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedSuccessChance; break; @@ -2222,6 +2282,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) switch (rebelCommandSaveInfo.availableMissions[index]) { case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_DESC]); break; + case RCAM_DISRUPT_ASD: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DISRUPT_ASD_DESC]); break; case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_DESC]); break; case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_DESC]); break; case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_DESC]); break; @@ -2361,6 +2422,36 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } break; + case RCAM_DISRUPT_ASD: + { + CHAR16 text[100]; + floatModifier = max(floatModifier, gRebelCommandSettings.fDisruptAsdIncomeReductionModifier); + floatModifier *= 100.f; + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_ASD_INCOME_REDUCTION], floatModifier, L"%s", locSkillText[floatModifierSkill]); + agentBonusText.push_back(text); + + if (gGameOptions.fNewTraitSystem) + { + switch (extraBits) + { + case MissionHelpers::DISRUPT_ASD_STEAL_FUEL: + { + const UINT8 townId = GetTownIdForSector(BOBBYR_SHIPPING_DEST_SECTOR_X, BOBBYR_SHIPPING_DEST_SECTOR_Y); + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_STEAL_FUEL], pTownNames[townId], locSkillText[TECHNICIAN_NT]); + agentBonusText.push_back(text); + } + break; + + case MissionHelpers::DISRUPT_ASD_DESTROY_RESERVES: + { + swprintf(text, szRebelCommandText[RCT_MISSION_BONUS_DESTROY_RESERVES], locSkillText[DEMOLITIONS_NT]); + agentBonusText.push_back(text); + } + break; + } + } + } + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: { // no special modifiers. included for completeness. @@ -2727,6 +2818,14 @@ void PrepareMission(INT8 index) } break; + case RCAM_DISRUPT_ASD: + { + missionTitle = RCAMT_DISRUPT_ASD_TITLE; + missionSuccessChance = gRebelCommandSettings.iDisruptAsdSuccessChance; + missionDuration = gRebelCommandSettings.iDisruptAsdDuration; + } + break; + case RCAM_GET_ENEMY_MOVEMENT_TARGETS: { missionTitle = RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE; @@ -3759,12 +3858,16 @@ void DailyUpdate() rebelCommandSaveInfo.cachedBountyPayout = 0; } + // RCAM_DISRUPT_ASD + ApplyAdditionalASDEffects(); + 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; + else if (i == RCAM_DISRUPT_ASD && gGameExternalOptions.fASDActive == FALSE) continue; validMissions.insert(static_cast(i)); } @@ -4129,6 +4232,7 @@ void SetupInfo() aa.fValue3 = 0.f; info.adminActions.insert(info.adminActions.begin() + RCAA_FORTIFICATIONS, aa); + // rftr todo: this should really be a map... but as long as we insert mission info in the same order as the enum then we're good MissionHelpers::missionInfo.clear(); // example format // { @@ -4149,6 +4253,16 @@ void SetupInfo() {gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Covert, gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Scouting, gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Stealthy, gRebelCommandSettings.iDeepDeploymentRangeEW_Bonus_Survival}, {MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_COVERT, MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SCOUTING, MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_STEALTHY, MissionHelpers::DEEP_DEPLOYMENT_RANGE_BONUS_SURVIVAL} }); + //RCAM_DISRUPT_ASD + MissionHelpers::missionInfo.push_back( + { + {COVERT_NT, TECHNICIAN_NT, DEMOLITIONS_NT, NIGHT_OPS_NT}, + {-1, -1, -1, NIGHTOPS_OT}, + {gRebelCommandSettings.iDisruptAsdDuration_Bonus_Covert, gRebelCommandSettings.iDisruptAsdDuration_Bonus_Technician, gRebelCommandSettings.iDisruptAsdDuration_Bonus_Demolitions, gRebelCommandSettings.iDisruptAsdDuration_Bonus_Nightops}, + {gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Covert, gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Technician, gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Technician, gRebelCommandSettings.fDisruptAsdIncomeReductionModifier_Nightops}, + {0, 0, 0, 0}, + {0, MissionHelpers::DISRUPT_ASD_STEAL_FUEL, MissionHelpers::DISRUPT_ASD_DESTROY_RESERVES, 0} + }); //RCAM_GET_ENEMY_MOVEMENT_TARGETS MissionHelpers::missionInfo.push_back( { @@ -4207,7 +4321,7 @@ void SetupInfo() {-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, 0, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Snitch, gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit_Demolitions}, {0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_OFFICER_PAYOUTS, 0, MissionHelpers::SOLDIER_BOUNTIES_KINGPIN_VEHICLE_PAYOUTS} }); //RCAM_TRAIN_MILITIA_ANYWHERE @@ -4220,6 +4334,30 @@ void SetupInfo() {gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers, gRebelCommandSettings.iTrainMilitiaAnywhereMaxTrainers_Teaching}, {0, 0, MissionHelpers::TRAIN_MILITIA_ANYWHERE_TEACHING} }); + + // cache item IDs + ItemIdCache::Clear(); + // (Item[i].usItemClass & IC_AMMO) && (Magazine[ Item[i].ubClassIndex ].ubMagType == AMMO_BOX or AMMO_CRATE?) + for (UINT16 i = 0; i < MAXITEMS; ++i) + { + if (Item[i].gascan) ItemIdCache::gasCans.push_back(i); + else if (Item[i].firstaidkit) ItemIdCache::firstAidKits.push_back(i); + else if (Item[i].medicalkit) ItemIdCache::medKits.push_back(i); + else if (Item[i].toolkit) ItemIdCache::toolKits.push_back(i); + else if (Item[i].usItemClass & IC_AMMO) + { + if (Magazine[Item[i].ubClassIndex].ubMagType == AMMO_BOX) + { + if ((gGameOptions.fGunNut || !Item[i].biggunlist) + && (gGameOptions.ubGameStyle == STYLE_SCIFI || !Item[i].scifi)) + { + // coolness runs from 1-10, so apply offset + ItemIdCache::ammo[Item[i].ubCoolness-1].push_back(i); + } + } + } + + } } void UpgradeMilitiaStats() @@ -4490,6 +4628,82 @@ INT16 GetAdditionalDeployRange(const UINT8 insertionCode) return 0; } +FLOAT GetASDIncomeModifier() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return 1.f; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_DISRUPT_ASD); + + if (iter == missionMap.end()) + return 1.f; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + if (evt.isSecondEvent) + { + const MERCPROFILESTRUCT* merc = &gMercProfiles[evt.mercProfileId]; + UINT32 durationBonus; + FLOAT floatModifier; + INT16 intModifier; + int durSkill; + int floatSkill; + int intSkill; + UINT16 extraBits; + MissionHelpers::GetMissionInfo(RCAM_DISRUPT_ASD, merc, durationBonus, floatModifier, intModifier, durSkill, floatSkill, intSkill, extraBits); + + return 1.f - floatModifier; + } + + return 1.f; +} + +void ApplyAdditionalASDEffects() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_DISRUPT_ASD); + + if (iter == missionMap.end()) + return; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + if (evt.isSecondEvent) + { + switch (evt.extraBits) + { + case MissionHelpers::DISRUPT_ASD_STEAL_FUEL: + { + // spawn a gas can + CreateItemAtAirport(ItemIdCache::gasCans.at(ItemIdCache::gasCans.size()), 75 + Random(26)); + + // say it came from the ASD's reserves + AddStrategicAIResources(ASD_FUEL, gGameExternalOptions.gASDResource_Fuel_Jeep + Random(gGameExternalOptions.gASDResource_Fuel_Jeep)); + } + break; + + case MissionHelpers::DISRUPT_ASD_DESTROY_RESERVES: + { + // priority: tank > jeep > robots + if (GetStrategicAIResourceCount(ASD_TANK) > 0) + AddStrategicAIResources(ASD_TANK, 1 + Random(2)); + else if (GetStrategicAIResourceCount(ASD_JEEP) > 0) + AddStrategicAIResources(ASD_JEEP, 1 + Random(2)); + else if (GetStrategicAIResourceCount(ASD_ROBOT) > 0) + AddStrategicAIResources(ASD_ROBOT, 2 + Random(3)); + + // let's also try to destroy a good amount of fuel + AddStrategicAIResources(ASD_FUEL, gGameExternalOptions.gASDResource_Fuel_Tank + Random(gGameExternalOptions.gASDResource_Fuel_Tank)); + } + break; + } + } +} + INT8 GetEnemyEquipmentCoolnessModifier() { if (!gGameExternalOptions.fRebelCommandEnabled) @@ -4633,6 +4847,7 @@ void HandleStrategicEvent(const UINT32 eventParam) switch (mission) { case RCAM_DEEP_DEPLOYMENT: + case RCAM_DISRUPT_ASD: case RCAM_GET_ENEMY_MOVEMENT_TARGETS: case RCAM_IMPROVE_LOCAL_SHOPS: case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index 4ce6e04e7..690d165d8 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -89,6 +89,7 @@ enum RebelCommandAgentMissions { RCAM_NONE = -1, RCAM_DEEP_DEPLOYMENT = 0, + RCAM_DISRUPT_ASD, // only available if ASD enabled RCAM_GET_ENEMY_MOVEMENT_TARGETS, // aka Strategic Intel RCAM_IMPROVE_LOCAL_SHOPS, RCAM_REDUCE_STRATEGIC_DECISION_SPEED, // aka Slower Strategic Decisions @@ -101,13 +102,12 @@ enum RebelCommandAgentMissions RCAM_NUM_MISSIONS, // ideas/unimplemented - RCAM_SEND_SUPPLIES_TO_TOWN, - RCAM_BOOST_TOWN_ADMIN_ACTIONS, + RCAM_SEND_SUPPLIES_TO_TOWN, // store agent location townid in extrabits + RCAM_BOOST_TOWN_ADMIN_ACTIONS, // store agent location townid in extrabits RCAM_PROCURE_ITEMS, RCAM_MILITIA_SKILL_TRAITS, // should override militia skill traits ini option - split into multiple (weapon spec, bodybuilding, athletic, night ops) RCAM_OBSERVE_SECTORS, // ??? competes with scouts? RCAM_PURCHASE_SUPPLIES, // increase daily supply income, decrease daily $ income - RCAM_SABOTAGE_ASD, // see ASD.cpp for things that can be played with RCAM_SABOTAGE_MINE, RCAM_REDUCE_ENEMY_POOL, // need to make sure enemy pool is not infinite // giReinforcementPool, also gfUnlimitedTroops = zDiffSetting[gGameOptions.ubDifficultyLevel].bUnlimitedPoolOfTroops; // militia/mercs get bonus vision (???) @@ -223,6 +223,7 @@ BOOLEAN CanAssignTraitsToMilitia(); BOOLEAN CanTrainMilitiaAnywhere(); UINT8 GetMaxTrainersForTrainMilitiaAnywhere(); INT16 GetAdditionalDeployRange(const UINT8 insertionCode); +FLOAT GetASDIncomeModifier(); INT8 GetEnemyEquipmentCoolnessModifier(); INT8 GetEnemyEquipmentStatusModifier(const INT8 initialStatus); UINT8 GetMerchantCoolnessBonus(); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index bc67a3ce0..173f03960 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11948,6 +11948,9 @@ STR16 szRebelCommandText[] = L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -12085,6 +12088,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 35bbac4fd..fc0ecb03b 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11958,6 +11958,9 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -12095,6 +12098,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 331bae0d5..e674df577 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11948,6 +11948,9 @@ STR16 szRebelCommandText[] = L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -12085,6 +12088,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index a04b38db8..09495aa30 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11940,6 +11940,9 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -12077,6 +12080,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 576d94cc7..1d78a540a 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11862,6 +11862,9 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -11999,6 +12002,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 321075a2a..0cdff8f30 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11949,6 +11949,9 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -12086,6 +12089,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 958d425c6..1ffca3ec9 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11962,6 +11962,9 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -12099,6 +12102,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 2cc5aeec7..3e2070caf 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11943,6 +11943,9 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Agent bonus:", L"Chance of success +%d%s (%s)", L"Deployment range +%d (%s)", + L"ASD Income -%2.0f%s (%s)", + L"Steal fuel; send to %s (%s)", + L"Destroy reserve units (%s)", L"Time +%2.0f%s (%s)", L"Vision -%2.0f%s (%s)", L"Gear quality -%d (%s)", @@ -12080,6 +12083,8 @@ STR16 szRebelCommandAgentMissionsText[] = { L"Deep Deployment", L"Coordinate efforts to find ways to sneak up on the enemy, but be careful: it's equally possible to put yourself in a disadvantaged deployment area. When attacking enemy forces, the deployment area is much larger.", + L"Disrupt ASD", + L"Wreak havoc on the day-to-day operations of the Arulco Special Division. Temporarily prevent the ASD from deploying additional mechanised units, and drastically reduce their daily income.", L"Strategic Intel", L"Intercept plans and discover where enemies intend to strike. When viewing teams on the strategic map, sectors prioritised by the enemy will be marked in red.", L"Improve Local Shops", From c1b5d1719afc7670b593ec4f3c0b22b74a1cf0ea Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 25 Oct 2022 13:14:35 -0700 Subject: [PATCH 31/52] Add "Send Supplies" mission --- GameSettings.cpp | 5 +++ GameSettings.h | 5 +++ Strategic/Rebel Command.cpp | 68 +++++++++++++++++++++++++++++++++++-- Strategic/Rebel Command.h | 20 ++--------- Utils/_ChineseText.cpp | 2 +- Utils/_DutchText.cpp | 2 +- Utils/_EnglishText.cpp | 5 ++- Utils/_FrenchText.cpp | 2 +- Utils/_GermanText.cpp | 2 +- Utils/_ItalianText.cpp | 2 +- Utils/_PolishText.cpp | 2 +- Utils/_RussianText.cpp | 2 +- 12 files changed, 90 insertions(+), 27 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 265a1982b..c1932a3f9 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4245,6 +4245,11 @@ void LoadRebelCommandSettings() gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Demolitions = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_DURATION_BONUS_DEMOLITIONS", 72, 0, 255); gRebelCommandSettings.iSabotageMechanicalUnitsDuration_Bonus_Heavy_Weapons = iniReader.ReadInteger("Rebel Command Settings", "SABOTAGE_VEHICLES_DURATION_BONUS_HEAVY_WEAPONS", 72, 0, 255); + gRebelCommandSettings.iSendSuppliesToTownSuccessChance = iniReader.ReadInteger("Rebel Command Settings", "SEND_SUPPLIES_TO_TOWN_SUCCESS_CHANCE", 50, 0, 100); + gRebelCommandSettings.iSendSuppliesToTownDuration = iniReader.ReadInteger("Rebel Command Settings", "SEND_SUPPLIES_TO_TOWN_DURATION", 72, 0, 255); + gRebelCommandSettings.iSendSuppliesToTownLoyaltyGain = iniReader.ReadInteger("Rebel Command Settings", "SEND_SUPPLIES_TO_TOWN_LOYALTY_GAIN", 500, 1, 10000); + gRebelCommandSettings.iSendSuppliesToTownInterval = iniReader.ReadInteger("Rebel Command Settings", "SEND_SUPPLIES_TO_TOWN_INTERVAL", 6, 1, 24); + 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); diff --git a/GameSettings.h b/GameSettings.h index 61989eb34..517d7e3a3 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1930,6 +1930,11 @@ typedef struct UINT8 iSabotageMechanicalUnitsDuration_Bonus_Demolitions; UINT8 iSabotageMechanicalUnitsDuration_Bonus_Heavy_Weapons; + INT8 iSendSuppliesToTownSuccessChance; + UINT8 iSendSuppliesToTownDuration; + INT32 iSendSuppliesToTownLoyaltyGain; + INT8 iSendSuppliesToTownInterval; + INT8 iTrainMilitiaAnywhereSuccessChance; INT8 iTrainMilitiaAnywhereMaxTrainers; INT8 iTrainMilitiaAnywhereMaxTrainers_Teaching; diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 9997934bc..79008f802 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -353,6 +353,7 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_MISSION_CANT_START_LOW_LOYALTY, RCT_MISSION_CANT_START_AGENT_UNAVAILABLE, RCT_MISSION_CANT_START_CONTRACT_EXPIRING, + RCT_MISSION_CANT_USE_REBEL_AGENT, RCT_MISSION_CANT_START_BATTLE_IN_PROGRESS, RCT_MISSION_START_BUTTON, RCT_MISSION_VIEW_ACTIVE, @@ -414,6 +415,7 @@ enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentM MISSION_TEXT(REDUCE_UNALERTED_ENEMY_VISION) MISSION_TEXT(SABOTAGE_INFANTRY_EQUIPMENT) MISSION_TEXT(SABOTAGE_MECHANICAL_UNITS) + MISSION_TEXT(SEND_SUPPLIES_TO_TOWN) MISSION_TEXT(SOLDIER_BOUNTIES_KINGPIN) MISSION_TEXT(TRAIN_MILITIA_ANYWHERE) }; @@ -546,6 +548,8 @@ INT32 GetAdminActionCostForRegion(INT16 regionId); INT16 GetAdminActionInRegion(INT16 regionId, RebelCommandAdminActions adminAction); UINT8 GetRegionLoyalty(INT16 regionId); void HandleScouting(); +void SendSuppliesToTownMission(); +INT16 SendSuppliesToTownDurationBonus(const MERCPROFILESTRUCT* merc); void SetupInfo(); void UpgradeMilitiaStats(); @@ -1221,7 +1225,7 @@ void UpdateAdminActionChangeList(INT16 regionId) BOOLEAN EnterWebsite() { // rftr todo: temp debugging - rebelCommandSaveInfo.availableMissions[0] = RCAM_DISRUPT_ASD; + rebelCommandSaveInfo.availableMissions[0] = RCAM_SEND_SUPPLIES_TO_TOWN; UpdateAdminActionChangeList(iCurrentRegionId); // make sure we have a valid directive @@ -2229,6 +2233,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_TITLE]); break; 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_SEND_SUPPLIES_TO_TOWN: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SEND_SUPPLIES_TO_TOWN_TITLE]); break; case RCAM_SOLDIER_BOUNTIES_KINGPIN: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SOLDIER_BOUNTIES_KINGPIN_TITLE]); break; case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_TITLE]); break; @@ -2248,6 +2253,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionDurationBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionDuration; break; case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: missionDurationBase = gRebelCommandSettings.iSabotageInfantryEquipmentDuration; break; case RCAM_SABOTAGE_MECHANICAL_UNITS: missionDurationBase = gRebelCommandSettings.iSabotageMechanicalUnitsDuration; break; + case RCAM_SEND_SUPPLIES_TO_TOWN: missionDurationBase = gRebelCommandSettings.iSendSuppliesToTownDuration; break; case RCAM_SOLDIER_BOUNTIES_KINGPIN: missionDurationBase = gRebelCommandSettings.iSoldierBountiesKingpinDuration; break; case RCAM_TRAIN_MILITIA_ANYWHERE: missionDurationBase = gRebelCommandSettings.iTrainMilitiaAnywhereDuration; break; @@ -2270,6 +2276,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: missionSuccessChanceBase = gRebelCommandSettings.iReduceUnalertedEnemyVisionSuccessChance; break; case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: missionSuccessChanceBase = gRebelCommandSettings.iSabotageInfantryEquipmentSuccessChance; break; case RCAM_SABOTAGE_MECHANICAL_UNITS: missionSuccessChanceBase = gRebelCommandSettings.iSabotageMechanicalUnitsSuccessChance; break; + case RCAM_SEND_SUPPLIES_TO_TOWN: missionSuccessChanceBase = gRebelCommandSettings.iSendSuppliesToTownSuccessChance; break; case RCAM_SOLDIER_BOUNTIES_KINGPIN: missionSuccessChanceBase = gRebelCommandSettings.iSoldierBountiesKingpinSuccessChance; break; case RCAM_TRAIN_MILITIA_ANYWHERE: missionSuccessChanceBase = gRebelCommandSettings.iTrainMilitiaAnywhereSuccessChance; break; @@ -2289,6 +2296,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_UNALERTED_ENEMY_VISION_DESC]); break; 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_SEND_SUPPLIES_TO_TOWN: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SEND_SUPPLIES_TO_TOWN_DESC]); break; case RCAM_SOLDIER_BOUNTIES_KINGPIN: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_SOLDIER_BOUNTIES_KINGPIN_DESC], gRebelCommandSettings.iSoldierBountiesKingpinPayout_Limit); break; case RCAM_TRAIN_MILITIA_ANYWHERE: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_TRAIN_MILITIA_ANYWHERE_DESC]); break; @@ -2503,6 +2511,15 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) } break; + case RCAM_SEND_SUPPLIES_TO_TOWN: + { + // duration here is affected by lvl instead of a specific skill + CHAR16 durationText[100]; + swprintf(durationText, szRebelCommandText[RCT_MISSION_BONUS_DURATION], SendSuppliesToTownDurationBonus(&merc), pShortAttributeStrings[5]); // "Lvl" + agentBonusText.push_back(durationText); + } + break; + case RCAM_SOLDIER_BOUNTIES_KINGPIN: { floatModifier = max(floatModifier, 1.f); @@ -2578,7 +2595,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) const INT32 worldMin = GetWorldTotalMin(); const INT32 remaining = endTime - worldMin; - if (townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission) + if ((townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission) && rebelCommandSaveInfo.availableMissions[index] != RCAM_SEND_SUPPLIES_TO_TOWN) { canStartMission = FALSE; swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_LOW_LOYALTY]); @@ -2593,6 +2610,11 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) canStartMission = FALSE; swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_CONTRACT_EXPIRING]); } + else if (agentIndex[index] == mercs.size() && rebelCommandSaveInfo.availableMissions[index] == RCAM_SEND_SUPPLIES_TO_TOWN) + { + canStartMission = FALSE; + swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_USE_REBEL_AGENT]); + } if (!canStartMission) { @@ -2874,6 +2896,15 @@ void PrepareMission(INT8 index) } break; + case RCAM_SEND_SUPPLIES_TO_TOWN: + { + missionTitle = RCAMT_SEND_SUPPLIES_TO_TOWN_TITLE; + missionSuccessChance = gRebelCommandSettings.iSendSuppliesToTownSuccessChance; + missionDuration = gRebelCommandSettings.iSendSuppliesToTownDuration + SendSuppliesToTownDurationBonus(merc); + extraBits = SECTOR(merc->sSectorX, merc->sSectorY); + } + break; + case RCAM_SOLDIER_BOUNTIES_KINGPIN: { missionTitle = RCAMT_SOLDIER_BOUNTIES_KINGPIN_TITLE; @@ -3909,6 +3940,9 @@ void HourlyUpdate() { HandleScouting(); + // RCAM_SEND_SUPPLIES_TO_TOWN + SendSuppliesToTownMission(); + // it's midnight! do the daily update if (GetWorldHour() == 0) { @@ -4314,6 +4348,8 @@ void SetupInfo() {gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Covert, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Demolitions, gRebelCommandSettings.iSabotageMechanicalUnitsStatLoss_Heavy_Weapons}, {MissionHelpers::SABOTAGE_MECHANICAL_UNITS_COVERT, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_DEMOLITIONS, MissionHelpers::SABOTAGE_MECHANICAL_UNITS_HEAVY_WEAPONS} }); + //RCAM_SEND_SUPPLIES_TO_TOWN + MissionHelpers::missionInfo.push_back({ }); // no entries necessary - no modifiers //RCAM_SOLDIER_BOUNTIES_KINGPIN MissionHelpers::missionInfo.push_back( { @@ -4854,6 +4890,7 @@ void HandleStrategicEvent(const UINT32 eventParam) case RCAM_REDUCE_UNALERTED_ENEMY_VISION: case RCAM_SABOTAGE_INFANTRY_EQUIPMENT: case RCAM_SABOTAGE_MECHANICAL_UNITS: + case RCAM_SEND_SUPPLIES_TO_TOWN: case RCAM_SOLDIER_BOUNTIES_KINGPIN: case RCAM_TRAIN_MILITIA_ANYWHERE: { @@ -4948,6 +4985,33 @@ void HandleStrategicEvent(const UINT32 eventParam) DoMessageBox(MSG_BOX_BASIC_STYLE, msgBoxText, guiCurrentScreen, MSG_BOX_FLAG_OK, NULL, NULL); } +void SendSuppliesToTownMission() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_SEND_SUPPLIES_TO_TOWN); + + if (iter == missionMap.end()) + return; + + if (GetWorldHour() % gRebelCommandSettings.iSendSuppliesToTownInterval != 0) + return; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + if (evt.isSecondEvent) + { + IncrementTownLoyalty(evt.extraBits, gRebelCommandSettings.iSendSuppliesToTownLoyaltyGain); + } +} + +INT16 SendSuppliesToTownDurationBonus(const MERCPROFILESTRUCT* merc) +{ + return merc ? merc->bExpLevel * 8 : 0; +} + BOOLEAN ShowEnemyMovementTargets() { if (!gGameExternalOptions.fRebelCommandEnabled) diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index 690d165d8..1009f7236 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -15,17 +15,6 @@ namespace RebelCommand // applies to RegionSaveInfo.actionLevels: use the MSB as the active flag since I don't expect it to be used otherwise constexpr UINT8 ADMIN_ACTION_ACTIVE_BIT = 1 << 7; - // for rebelCommandSaveInfo.uBitMask - // requirement breakdown - // 1 bit for notification toggle - // 5 * 4 bits for random mission selection (2off, 2def) = 32 choices each - // need some bits to track mission area (friendly/hostile? num towns?) - // remaining bits to track up/downgrades? - // some should be ASD specific? - // can we not do this and just check strategic events? GetAllStrategicEventsOfType(). could be costly. iterates over event LL on each call - // can we cache in-flight events on load? no real need to save this, right? - //constexpr UINT64 AGENT_NOTIFICATION_BIT = 1 << 0; - // the FIRST and SECOND strategic events share the same type (EVENT_REBELCOMMAND - no need to have multiple types yet, I think...) // so the 32-bit int will have to block out information for both events // FIRST EVENT BREAKDOWN @@ -35,8 +24,7 @@ namespace RebelCommand // C (8 bit) - the profile number of the merc that was sent. invalid if B == 0 // D (8 bit) - the mission ID. should match up with RebelCommandAgentMissions enum // E (8 bit) - the mission duration, in hours. if 0, mission failed. - // the rest of the bits depend on the mission? - // + // extra bits are mission-specific // SECOND EVENT BREAKDOWN // A####### #######B CCCCCCCC DDDDDDDD @@ -44,7 +32,7 @@ namespace RebelCommand // B (1 bit) - 0 if the player sent a generic rebel agent, 1 if the player sent one of their own mercs // C (8 bit) - the profile number of the merc that was sent. invalid if B == 0 // D (8 bit) - the mission ID. should match up with RebelCommandAgentMissions enum - // extra bits are for ??????????? + // extra bits are mission-specific enum RebelCommandDirectives { @@ -96,19 +84,17 @@ enum RebelCommandAgentMissions RCAM_REDUCE_UNALERTED_ENEMY_VISION, // aka Lower Readiness RCAM_SABOTAGE_INFANTRY_EQUIPMENT, // aka Sabotage Equipment RCAM_SABOTAGE_MECHANICAL_UNITS, // aka Sabotage Vehicles + RCAM_SEND_SUPPLIES_TO_TOWN, // ignores minimum loyalty requirement RCAM_SOLDIER_BOUNTIES_KINGPIN, RCAM_TRAIN_MILITIA_ANYWHERE, RCAM_NUM_MISSIONS, // ideas/unimplemented - RCAM_SEND_SUPPLIES_TO_TOWN, // store agent location townid in extrabits RCAM_BOOST_TOWN_ADMIN_ACTIONS, // store agent location townid in extrabits RCAM_PROCURE_ITEMS, RCAM_MILITIA_SKILL_TRAITS, // should override militia skill traits ini option - split into multiple (weapon spec, bodybuilding, athletic, night ops) - RCAM_OBSERVE_SECTORS, // ??? competes with scouts? RCAM_PURCHASE_SUPPLIES, // increase daily supply income, decrease daily $ income - RCAM_SABOTAGE_MINE, RCAM_REDUCE_ENEMY_POOL, // need to make sure enemy pool is not infinite // giReinforcementPool, also gfUnlimitedTroops = zDiffSetting[gGameOptions.ubDifficultyLevel].bUnlimitedPoolOfTroops; // militia/mercs get bonus vision (???) // share vision with civilians? diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 173f03960..203db277b 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11961,7 +11961,7 @@ STR16 szRebelCommandText[] = L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index fc0ecb03b..4172abfa2 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11971,7 +11971,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index e674df577..eafb98a5f 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11961,9 +11961,10 @@ STR16 szRebelCommandText[] = L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12102,6 +12103,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 09495aa30..538516469 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11953,7 +11953,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 1d78a540a..383c483d3 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11875,7 +11875,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 0cdff8f30..bbd31b579 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11962,7 +11962,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 1ffca3ec9..741d8b9ab 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11975,7 +11975,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 3e2070caf..ee26467da 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11956,7 +11956,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", - L"Agent not in loyal town", + L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", L"Battle in progress", From 7d360d01ce1fa9b25f0d7ad6220b62cb94d6bbb5 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 25 Oct 2022 22:55:19 -0700 Subject: [PATCH 32/52] Add mission prep time setting --- GameSettings.cpp | 1 + GameSettings.h | 1 + Strategic/Rebel Command.cpp | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index c1932a3f9..684fee826 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -4160,6 +4160,7 @@ void LoadRebelCommandSettings() // agent missions gRebelCommandSettings.iMissionBaseCost = iniReader.ReadInteger("Rebel Command Settings", "MISSION_BASE_COST", 500, 100, 10000); gRebelCommandSettings.iMissionAdditionalCost = iniReader.ReadInteger("Rebel Command Settings", "MISSION_ADDITIONAL_COST", 250, 0, 10000); + gRebelCommandSettings.iMissionPrepTime = iniReader.ReadInteger("Rebel Command Settings", "MISSION_PREPARATION_TIME", 24, 1, 168); gRebelCommandSettings.iMissionRefreshTimeDays = iniReader.ReadInteger("Rebel Command Settings", "MISSION_REFRESH_TIME_DAYS", 2, 1, 7); gRebelCommandSettings.iMinLoyaltyForMission = iniReader.ReadInteger("Rebel Command Settings", "MIN_LOYALTY_FOR_MISSION", 51, 0, 100); diff --git a/GameSettings.h b/GameSettings.h index 517d7e3a3..5f5db0adc 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1845,6 +1845,7 @@ typedef struct // agent missions INT32 iMissionBaseCost; INT32 iMissionAdditionalCost; + INT16 iMissionPrepTime; INT8 iMissionRefreshTimeDays; INT8 iMinLoyaltyForMission; diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 79008f802..72dfd5351 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2985,7 +2985,7 @@ void PrepareMission(INT8 index) // queue up the mission start event. make sure we use the top of the hour because I'm lazy and we're handling the assignment here instead of Assignments.cpp const UINT32 time = GetWorldTotalMin(); - //AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60 * 24, MissionHelpers::missionParam); + //AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60 * gRebelCommandSettings.iMissionPrepTime, MissionHelpers::missionParam); AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60, MissionHelpers::missionParam); // rftr todo: DELETE ME missionMap.insert(std::make_pair(static_cast(evt.missionId), MissionHelpers::missionParam)); From 54b0bf96b91d16d900984af3d8e342ecfd5e339f Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 26 Oct 2022 00:18:30 -0700 Subject: [PATCH 33/52] Ensure missions can only be started in towns that use loyalty --- Strategic/Rebel Command.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 72dfd5351..cd39e19fd 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2595,7 +2595,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) const INT32 worldMin = GetWorldTotalMin(); const INT32 remaining = endTime - worldMin; - if ((townId < FIRST_TOWN || townId >= NUM_TOWNS || townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission) && rebelCommandSaveInfo.availableMissions[index] != RCAM_SEND_SUPPLIES_TO_TOWN) + if (townId < FIRST_TOWN || townId >= NUM_TOWNS || !gfTownUsesLoyalty[townId] || (townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission && rebelCommandSaveInfo.availableMissions[index] != RCAM_SEND_SUPPLIES_TO_TOWN)) { canStartMission = FALSE; swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_LOW_LOYALTY]); @@ -2610,16 +2610,11 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) canStartMission = FALSE; swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_CONTRACT_EXPIRING]); } - else if (agentIndex[index] == mercs.size() && rebelCommandSaveInfo.availableMissions[index] == RCAM_SEND_SUPPLIES_TO_TOWN) - { - canStartMission = FALSE; - swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_USE_REBEL_AGENT]); - } - - if (!canStartMission) - { - DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); - } + } + else if (agentIndex[index] == mercs.size() && rebelCommandSaveInfo.availableMissions[index] == RCAM_SEND_SUPPLIES_TO_TOWN) + { + canStartMission = FALSE; + swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_USE_REBEL_AGENT]); } else if ((gTacticalStatus.uiFlags & INCOMBAT) || gTacticalStatus.fEnemyInSector) { @@ -2641,6 +2636,10 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) MSYS_SetBtnUserData(btnId, 0, index); btnIds.push_back(btnId); } + else + { + DrawTextToScreen(sText, x, y+295, 231, FONT10ARIAL, FONT_RED, FONT_MCOLOR_BLACK, FALSE, CENTER_JUSTIFIED); + } return TRUE; } From 02d6e48226c1a432816dca8e1f3bddf94e5b3f37 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 26 Oct 2022 20:48:15 -0700 Subject: [PATCH 34/52] Use prep time setting in text Remove debug prep time --- Strategic/Rebel Command.cpp | 10 +++++----- Utils/_ChineseText.cpp | 6 +++--- Utils/_DutchText.cpp | 6 +++--- Utils/_EnglishText.cpp | 6 +++--- Utils/_FrenchText.cpp | 6 +++--- Utils/_GermanText.cpp | 6 +++--- Utils/_ItalianText.cpp | 6 +++--- Utils/_PolishText.cpp | 6 +++--- Utils/_RussianText.cpp | 6 +++--- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index cd39e19fd..795393c3b 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -2778,7 +2778,8 @@ void RenderMissionOverview() case MOS_HELP: { UINT16 y = WEBSITE_TOP + 100; - y += DisplayWrappedString(WEBSITE_LEFT + 35, y, 400, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_MISSION_HELP_1], FONT_MCOLOR_BLACK, FALSE, 0); + swprintf(sText, szRebelCommandText[RCT_MISSION_HELP_1], gRebelCommandSettings.iMissionPrepTime); + y += DisplayWrappedString(WEBSITE_LEFT + 35, y, 400, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, sText, FONT_MCOLOR_BLACK, FALSE, 0); y += 20; y += DisplayWrappedString(WEBSITE_LEFT + 35, y, 400, 2, FONT12ARIAL, FONT_MCOLOR_BLACK, szRebelCommandText[RCT_MISSION_HELP_2], FONT_MCOLOR_BLACK, FALSE, 0); y += 20; @@ -2947,9 +2948,9 @@ void PrepareMission(INT8 index) { MissionHelpers::missionParam = SerialiseMissionFirstEvent(FALSE, mercs[agentIndex[index]]->ubProfile, static_cast(rebelCommandSaveInfo.availableMissions[index]), missionDuration, static_cast(extraBits)); if (merc->bSex == MALE) - swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART2_MALE], text, merc->zNickname); + swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART2_MALE], text, merc->zNickname, gRebelCommandSettings.iMissionPrepTime); else - swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART2_FEMALE], text, merc->zNickname); + swprintf(text, szRebelCommandText[RCT_MISSION_POPUP_PART2_FEMALE], text, merc->zNickname, gRebelCommandSettings.iMissionPrepTime); } DoLapTopMessageBox(MSG_BOX_LAPTOP_DEFAULT, text, LAPTOP_SCREEN, MSG_BOX_FLAG_YESNO, [](UINT8 exitValue) { @@ -2984,8 +2985,7 @@ void PrepareMission(INT8 index) // queue up the mission start event. make sure we use the top of the hour because I'm lazy and we're handling the assignment here instead of Assignments.cpp const UINT32 time = GetWorldTotalMin(); - //AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60 * gRebelCommandSettings.iMissionPrepTime, MissionHelpers::missionParam); - AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60, MissionHelpers::missionParam); // rftr todo: DELETE ME + AddStrategicEvent(EVENT_REBELCOMMAND, time + (60 - time % 60) + 60 * gRebelCommandSettings.iMissionPrepTime, MissionHelpers::missionParam); missionMap.insert(std::make_pair(static_cast(evt.missionId), MissionHelpers::missionParam)); rebelCommandSaveInfo.iSupplies -= GetMissionCost(); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 203db277b..32e7ad07d 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11968,7 +11968,7 @@ STR16 szRebelCommandText[] = L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11977,8 +11977,8 @@ STR16 szRebelCommandText[] = L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 4172abfa2..a390bdbd6 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11978,7 +11978,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11987,8 +11987,8 @@ STR16 szRebelCommandText[] = // TODO.Translate L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index eafb98a5f..6828330ca 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11969,7 +11969,7 @@ STR16 szRebelCommandText[] = L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11978,8 +11978,8 @@ STR16 szRebelCommandText[] = L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 538516469..f1ad0196e 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11960,7 +11960,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11969,8 +11969,8 @@ STR16 szRebelCommandText[] = // TODO.Translate L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 383c483d3..d861bbf6b 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11882,7 +11882,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11891,8 +11891,8 @@ STR16 szRebelCommandText[] = // TODO.Translate L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index bbd31b579..7a8969978 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11969,7 +11969,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11978,8 +11978,8 @@ STR16 szRebelCommandText[] = // TODO.Translate L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 741d8b9ab..0fc8cb50a 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11982,7 +11982,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11991,8 +11991,8 @@ STR16 szRebelCommandText[] = // TODO.Translate L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index ee26467da..4c5a9f68f 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11963,7 +11963,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Prepare Mission (%d supplies)", L"View active mission effects", L"View available mission list", - L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately 24 hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", + L"You are able to prepare one of the two missions presented. Once an agent is dispatched, they will be unavailable for approximately %d hours before becoming available again. A popup will notify you when preparations are complete. If preparations succeed, the mission's effects become active.", L"A rebel agent can be sent to prepare a mission, but your mercenaries will be far more effective. Their experience level and skills can provide additional bonuses to missions.", L"The cost of preparing a mission increases based on the number other missions either active or being prepared.", L"New missions will be available on Day %d at 00:00.", @@ -11972,8 +11972,8 @@ STR16 szRebelCommandText[] = // TODO.Translate L"%s - Active - Expires on Day %d, %02d:%02d", L"[%s (%d supplies)]", L"%s Send a rebel agent to prepare this mission?", - L"%s Send %s to prepare this mission? He will return in 24 hours.", - L"%s Send %s to prepare this mission? She will return in 24 hours.", + L"%s Send %s to prepare this mission? He will return in approximately %d hours.", + L"%s Send %s to prepare this mission? She will return in approximately %d hours.", L"Mission \"%s\" is now in effect.", L"Preparations for mission \"%s\" failed.", L"Mission \"%s\" has expired and is no longer in effect.", From f89f25ab9272366fbc530cd967ad93d457b97b04 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Thu, 27 Oct 2022 00:26:00 -0700 Subject: [PATCH 35/52] Split in-town and loyalty mission prep checks --- Strategic/Rebel Command.cpp | 8 +++++++- Utils/_ChineseText.cpp | 1 + Utils/_DutchText.cpp | 1 + Utils/_EnglishText.cpp | 1 + Utils/_FrenchText.cpp | 1 + Utils/_GermanText.cpp | 1 + Utils/_ItalianText.cpp | 1 + Utils/_PolishText.cpp | 1 + Utils/_RussianText.cpp | 1 + 9 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 795393c3b..d5272a1f7 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -350,6 +350,7 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_MISSION_BONUS_OFFICER_PAYOUT, RCT_MISSION_BONUS_VEHICLE_PAYOUT, RCT_MISSION_BONUS_DURATION, + RCT_MISSION_CANT_START_NOT_IN_TOWN, RCT_MISSION_CANT_START_LOW_LOYALTY, RCT_MISSION_CANT_START_AGENT_UNAVAILABLE, RCT_MISSION_CANT_START_CONTRACT_EXPIRING, @@ -2595,7 +2596,12 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index) const INT32 worldMin = GetWorldTotalMin(); const INT32 remaining = endTime - worldMin; - if (townId < FIRST_TOWN || townId >= NUM_TOWNS || !gfTownUsesLoyalty[townId] || (townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission && rebelCommandSaveInfo.availableMissions[index] != RCAM_SEND_SUPPLIES_TO_TOWN)) + if (townId < FIRST_TOWN || townId >= NUM_TOWNS || !gfTownUsesLoyalty[townId]) + { + canStartMission = FALSE; + swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_NOT_IN_TOWN]); + } + else if (townLoyalty < gRebelCommandSettings.iMinLoyaltyForMission && rebelCommandSaveInfo.availableMissions[index] != RCAM_SEND_SUPPLIES_TO_TOWN) { canStartMission = FALSE; swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_LOW_LOYALTY]); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 32e7ad07d..6977c562d 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11961,6 +11961,7 @@ STR16 szRebelCommandText[] = L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index a390bdbd6..04bc50160 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11971,6 +11971,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 6828330ca..fd729a353 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11961,6 +11961,7 @@ STR16 szRebelCommandText[] = L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index f1ad0196e..fae831659 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11953,6 +11953,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index d861bbf6b..672d3fc14 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11875,6 +11875,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 7a8969978..6a02a32b3 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11962,6 +11962,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 0fc8cb50a..0e52a590e 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11975,6 +11975,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 4c5a9f68f..4cea1aeb0 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11956,6 +11956,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Bonus for officers (%s)", L"Bonus for vehicles (%s)", L"Duration +%d hours (%s)", + L"Agent not in town", L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", From 7ad938a397dcd7d713ba846cd1e92a0d0b82fc29 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Thu, 27 Oct 2022 00:29:29 -0700 Subject: [PATCH 36/52] Remove debug line --- Strategic/Rebel Command.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index d5272a1f7..20aaa4e1f 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -1225,8 +1225,6 @@ void UpdateAdminActionChangeList(INT16 regionId) BOOLEAN EnterWebsite() { - // rftr todo: temp debugging - rebelCommandSaveInfo.availableMissions[0] = RCAM_SEND_SUPPLIES_TO_TOWN; UpdateAdminActionChangeList(iCurrentRegionId); // make sure we have a valid directive From 62861ab38eaa28385c3a84ef940fdb7ff6d5c1d1 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 28 Oct 2022 00:56:35 -0700 Subject: [PATCH 37/52] Add notification when new missions are available --- Strategic/Rebel Command.cpp | 3 +++ Utils/_ChineseText.cpp | 1 + Utils/_DutchText.cpp | 1 + Utils/_EnglishText.cpp | 1 + Utils/_FrenchText.cpp | 1 + Utils/_GermanText.cpp | 1 + Utils/_ItalianText.cpp | 1 + Utils/_PolishText.cpp | 1 + Utils/_RussianText.cpp | 1 + 9 files changed, 11 insertions(+) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 20aaa4e1f..57f7b5e73 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -324,6 +324,7 @@ enum RebelCommandText // keep this synced with szRebelCommandText in the text fi RCT_CONFIRM_CHANGE_ADMIN_ACTION_PROMPT, RCT_INSUFFICIENT_SUPPLIES_ADMIN_ACTIONS_DISABLED, RCT_NEW_MISSIONS_AVAILABLE_TIME, + RCT_NEW_MISSIONS_AVAILABLE_NOTIFICATION, RCT_MISSION_PREP_IN_PROGRESS, RCT_MISSION_DURATION_DAYS, RCT_MISSION_SUCCESS_CHANCE, @@ -3936,6 +3937,8 @@ void DailyUpdate() idx++; } } + + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szRebelCommandText[RCT_NEW_MISSIONS_AVAILABLE_NOTIFICATION]); } } diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 6977c562d..b0707e9d0 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11935,6 +11935,7 @@ STR16 szRebelCommandText[] = L"更改此指令操作将花费$%d并重置。确认支出?", //L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 04bc50160..95d2132c5 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11945,6 +11945,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index fd729a353..7ff18a08d 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11935,6 +11935,7 @@ STR16 szRebelCommandText[] = L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index fae831659..2b9c1648b 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11927,6 +11927,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 672d3fc14..a95d08340 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11849,6 +11849,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 6a02a32b3..8973e7e09 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11936,6 +11936,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 0e52a590e..4e4c06c9a 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11949,6 +11949,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 4cea1aeb0..948984170 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11930,6 +11930,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Changing this Admin Action will cost $%d and reset its tier. Confirm expenditure?", L"Insufficient supplies! Admin Actions have been DISABLED.", L"New missions will be available every %d hours.", + L"New missions are available at the A.R.C. website.", L"Mission preparations in progress.", L"Mission duration: %d days", L"Chance of success: %d%s", From 22404480ff049cb9d55bd5e7cde3fcafd87cea11 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sat, 29 Oct 2022 00:10:13 -0700 Subject: [PATCH 38/52] Fix mission randomisation --- Strategic/Rebel Command.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 57f7b5e73..f3525877e 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -3917,9 +3917,11 @@ void DailyUpdate() { for (int i = 0; i < NUM_ARC_AGENT_SLOTS; ++i) { - const INT8 mission = static_cast(Random(validMissions.size())); - rebelCommandSaveInfo.availableMissions[i] = mission; - validMissions.erase(static_cast(mission)); + const INT8 missionIndex = static_cast(Random(validMissions.size())); + auto iter = validMissions.cbegin(); + for (INT8 j = 0; j < missionIndex; ++j) iter++; + rebelCommandSaveInfo.availableMissions[i] = *iter; + validMissions.erase(static_cast(rebelCommandSaveInfo.availableMissions[i])); } } else // 1 mission available From c56946f9ba8f886fb765faeaf29781e603d4f17f Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sat, 29 Oct 2022 00:10:56 -0700 Subject: [PATCH 39/52] Remove todo --- Strategic/Rebel Command.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index f3525877e..9ffab43fd 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -48,7 +48,6 @@ How to add a new mission: - add to SetupMissionAgentBox() (mission description and merc bonus text) - add to PrepareMission() - add mission-specific functions -- rftr todo: ??? Points of interest: - Init() - set up rebel command for the first time From 94b846e021d1194a8831160e0401dabb44a0462e Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Sat, 29 Oct 2022 01:27:53 -0700 Subject: [PATCH 40/52] Simplify merc returning from mission prep --- Strategic/Rebel Command.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 9ffab43fd..7fad1414d 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -4970,8 +4970,6 @@ void HandleStrategicEvent(const UINT32 eventParam) { // merc ready for reassignment pSoldier->bSectorZ -= REBEL_COMMAND_Z_OFFSET; - pSoldier->ubInsertionDirection = DIRECTION_IRRELEVANT; - pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CENTER; AssignmentDone(pSoldier, TRUE, FALSE); AddCharacterToAnySquad(pSoldier); break; From 70c7c0bf96045b33472d7c21d1606a474ca95ea9 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Mon, 31 Oct 2022 17:40:27 -0700 Subject: [PATCH 41/52] Fix bad screen message Stop time compression when notifying player about missions --- Strategic/Rebel Command.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 7fad1414d..5c98ea608 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -4959,6 +4959,7 @@ void HandleStrategicEvent(const UINT32 eventParam) swprintf(msgBoxText, szRebelCommandText[RCT_MISSION_FAILURE], szRebelCommandAgentMissionsText[evt1.missionId * 2]); swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_FAILURE], szRebelCommandAgentMissionsText[evt1.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); + StopTimeCompression(); } if (!evt1.sentGenericRebelAgent && foundMerc) @@ -4983,8 +4984,9 @@ void HandleStrategicEvent(const UINT32 eventParam) // mission duration is over. deactivate the mission missionMap.erase(static_cast(evt2.missionId)); swprintf(msgBoxText, szRebelCommandText[RCT_MISSION_EXPIRED], szRebelCommandAgentMissionsText[evt2.missionId * 2]); - swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_EXPIRED], szRebelCommandAgentMissionsText[evt1.missionId * 2]); + swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_EXPIRED], szRebelCommandAgentMissionsText[evt2.missionId * 2]); ScreenMsg(FONT_MCOLOR_RED, MSG_INTERFACE, screenMsgText); + StopTimeCompression(); } DoMessageBox(MSG_BOX_BASIC_STYLE, msgBoxText, guiCurrentScreen, MSG_BOX_FLAG_OK, NULL, NULL); From 32d565eb99b1211dba74ef94f57a460fb87e3a50 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Tue, 1 Nov 2022 01:08:17 -0700 Subject: [PATCH 42/52] Change new mission screenmsg to green --- Strategic/Rebel Command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index 5c98ea608..ee75993fa 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -3939,7 +3939,7 @@ void DailyUpdate() } } - ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szRebelCommandText[RCT_NEW_MISSIONS_AVAILABLE_NOTIFICATION]); + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, szRebelCommandText[RCT_NEW_MISSIONS_AVAILABLE_NOTIFICATION]); } } From 568ee070a829f3e0bfd398cc151e82abc1ba354c Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Thu, 3 Nov 2022 00:08:03 -0700 Subject: [PATCH 43/52] Disrupt ASD now blocks upgrades --- Strategic/ASD.cpp | 6 +++--- Strategic/Rebel Command.cpp | 16 ++++++++++++++++ Strategic/Rebel Command.h | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Strategic/ASD.cpp b/Strategic/ASD.cpp index 6d5861dec..ceee99cfa 100644 --- a/Strategic/ASD.cpp +++ b/Strategic/ASD.cpp @@ -1514,7 +1514,7 @@ UINT32 ASDResourceCostFuel( UINT8 aType ) // if ASD has tanks, it can allow the queen to upgrade soldiers to tanks BOOLEAN ASDSoldierUpgradeToTank( ) { - if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsTanks ) + if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsTanks && RebelCommand::GetASDCanDeployUnits() ) { if ( gASD_Flags & ASDFACT_TANK_UNLOCKED ) { @@ -1531,7 +1531,7 @@ BOOLEAN ASDSoldierUpgradeToTank( ) BOOLEAN ASDSoldierUpgradeToJeep( ) { - if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsJeeps ) + if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsJeeps && RebelCommand::GetASDCanDeployUnits() ) { if ( gASD_Flags & ASDFACT_JEEP_UNLOCKED ) { @@ -1548,7 +1548,7 @@ BOOLEAN ASDSoldierUpgradeToJeep( ) BOOLEAN ASDSoldierUpgradeToRobot( ) { - if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsRobots ) + if ( gGameExternalOptions.fASDActive && gGameExternalOptions.fASDAssignsRobots && RebelCommand::GetASDCanDeployUnits() ) { if ( gASD_Flags & ASDFACT_ROBOT_UNLOCKED ) { diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index ee75993fa..d95d3afc6 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -4671,6 +4671,22 @@ INT16 GetAdditionalDeployRange(const UINT8 insertionCode) return 0; } +BOOLEAN GetASDCanDeployUnits() +{ + if (!gGameExternalOptions.fRebelCommandEnabled) + return TRUE; + + const std::unordered_map::iterator iter = missionMap.find(RCAM_DISRUPT_ASD); + + if (iter == missionMap.end()) + return TRUE; + + MissionSecondEvent evt; + DeserialiseMissionSecondEvent(iter->second, evt); + + return evt.isSecondEvent ? FALSE : TRUE; +} + FLOAT GetASDIncomeModifier() { if (!gGameExternalOptions.fRebelCommandEnabled) diff --git a/Strategic/Rebel Command.h b/Strategic/Rebel Command.h index 1009f7236..f8c9bc241 100644 --- a/Strategic/Rebel Command.h +++ b/Strategic/Rebel Command.h @@ -209,6 +209,7 @@ BOOLEAN CanAssignTraitsToMilitia(); BOOLEAN CanTrainMilitiaAnywhere(); UINT8 GetMaxTrainersForTrainMilitiaAnywhere(); INT16 GetAdditionalDeployRange(const UINT8 insertionCode); +BOOLEAN GetASDCanDeployUnits(); FLOAT GetASDIncomeModifier(); INT8 GetEnemyEquipmentCoolnessModifier(); INT8 GetEnemyEquipmentStatusModifier(const INT8 initialStatus); From a554f0de170945f0e7b31024f44a8aa5074f7dd7 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 22:32:23 -0700 Subject: [PATCH 44/52] Remove #pragma optimize --- Strategic/Assignments.cpp | 1 - Strategic/Map Screen Interface Map.cpp | 1 - Strategic/Town Militia.cpp | 1 - Tactical/ArmsDealerInvInit.cpp | 1 - Tactical/DisplayCover.cpp | 1 - TileEngine/Tactical Placement GUI.cpp | 1 - 6 files changed, 6 deletions(-) diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 027d5afc1..04dad5007 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 39cca58a2..185549d92 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" diff --git a/Strategic/Town Militia.cpp b/Strategic/Town Militia.cpp index 9a3e3ed92..98ce1858b 100644 --- a/Strategic/Town Militia.cpp +++ b/Strategic/Town Militia.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #include "builddefines.h" #ifdef PRECOMPILEDHEADERS diff --git a/Tactical/ArmsDealerInvInit.cpp b/Tactical/ArmsDealerInvInit.cpp index 16d0fec63..df0c9422e 100644 --- a/Tactical/ArmsDealerInvInit.cpp +++ b/Tactical/ArmsDealerInvInit.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else diff --git a/Tactical/DisplayCover.cpp b/Tactical/DisplayCover.cpp index 32832e706..34b67dd85 100644 --- a/Tactical/DisplayCover.cpp +++ b/Tactical/DisplayCover.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "AI All.h" #include "DisplayCover.h" diff --git a/TileEngine/Tactical Placement GUI.cpp b/TileEngine/Tactical Placement GUI.cpp index 3a8523d66..787eba223 100644 --- a/TileEngine/Tactical Placement GUI.cpp +++ b/TileEngine/Tactical Placement GUI.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #include "builddefines.h" // WANNE 2 From 6f6d457188f1977b0ecd8bf12d8c1cca306ad904 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 22:37:28 -0700 Subject: [PATCH 45/52] Undo unrelated Chinese text changes --- Utils/_ChineseText.cpp | 62 +++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index b0707e9d0..fad19f0e4 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -4219,7 +4219,7 @@ STR16 pHelicopterEtaStrings[] = L"Skyrider", L"着陆点", L"直升机严重受损,必须降落在敌军领地!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> - L"直升机将直接返回基地,你希望在此之前丢下乘客吗?", + L"直升机将直接返回基地,你希望在此之前放下乘客吗?", L"剩余燃料:", L"到加油站距离:", }; @@ -7032,7 +7032,7 @@ STR16 pMessageStrings[] = L"磁盘空间不足。只有%sMB可用空间,《铁血联盟2》需要%sMB。", L"从AIM雇佣了%s。", //"Hired %s from AIM", L"%s抓住了%s。", //"%s has caught %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. - L"%s使用了%s。", //L"%s has taken %s。", + L"%s使用了(拾取)%s。", //L"%s has taken %s。", L"%s没有医疗技能", //"%s has no medical skill",//'Merc name' has no medical skill. //CDRom errors (such as ejecting CD while attempting to read the CD) @@ -11373,17 +11373,17 @@ STR16 szIMPGearPocketText[] = L"选择头部装备", //L"Select face gear", L"选择头部装备", // L"Select face gear", - L"选择主枪", // L"Select main gun", - L"选择手枪", //L"Select sidearm", + L"选择主武器", // L"Select main gun", + L"选择副武器", //L"Select sidearm", L"选择LBE背心", //L"Select LBE vest", - L"选择LBE皮套", //L"Select left LBE holster", - L"选择LBE皮套", //L"Select right LBE holster", + L"选择左LBE枪套", //L"Select left LBE holster", + L"选择右LBE枪套", //L"Select right LBE holster", L"选择LBE战斗包", //L"Select LBE combat pack", L"选择LBE背包", //L"Select LBE backpack", - L"Select launcher / rifle", - L"选择武器", //L"Select melee weapon", + L"选择发射器/步枪", //L"Select launcher / rifle", + L"选择近战武器", //L"Select melee weapon", L"选择附加物品", //L"Select additional items", //BIGPOCK1POS L"选择附加物品", //L"Select additional items", @@ -11392,28 +11392,28 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", - L"Select medkit", //MEDPOCK1POS - L"Select medkit", - L"Select medkit", - L"Select medkit", - L"Select main gun ammo", //SMALLPOCK1POS - L"Select main gun ammo", - L"Select main gun ammo", - L"Select main gun ammo", - L"Select main gun ammo", - L"Select launcher / rifle ammo", //SMALLPOCK6POS - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select sidearm ammo", //SMALLPOCK11POS - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", + L"选择医疗套件", //L"Select medkit",MEDPOCK1POS + L"选择医疗套件", //L"Select medkit", + L"选择医疗套件", //L"Select medkit", + L"选择医疗套件", //L"Select medkit", + L"选择主武器弹药", //L"Select main gun ammo",SMALLPOCK1POS + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo",SMALLPOCK6POS + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择配枪弹药", //L"Select sidearm ammo",SMALLPOCK11POS + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", L"选择附加物品", //L"Select additional items", //SMALLPOCK19POS L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", @@ -11426,7 +11426,7 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", //SMALLPOCK30POS - L"Left click to select item / Right click to close window", + L"左键单击选择项目/右键单击关闭窗口", //L"Left click to select item / Right click to close window", }; STR16 szMilitiaStrategicMovementText[] = From 75332ea2193e7a53884f943f6658d0ff73012f3e Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 22:37:28 -0700 Subject: [PATCH 46/52] Undo unrelated Chinese text changes --- .gitignore | 404 ++++++++++++++++++++++++++ MainMenuScreen.cpp | 7 + SaveLoadGame.cpp | 1 + Standard Gaming Platform/sgp.cpp | 1 + Standard Gaming Platform/vobject.cpp | 1 + Strategic/Hourly Update.cpp | 1 + Strategic/Strategic AI.cpp | 11 +- Tactical/Inventory Choosing.cpp | 21 +- Tactical/Soldier Control.cpp | 1 + Tactical/Soldier Profile.cpp | 144 +++++++++ Utils/_ChineseText.cpp | 66 ++--- ext/VFS/build/VFS_VS2019.vcxproj | 13 +- ext/VFS/build/VFS_VS2019.vcxproj.user | 2 +- ja2_VS2019.sln | 9 +- ja2_VS2019.vcxproj | 6 +- 15 files changed, 629 insertions(+), 59 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..92e01666c --- /dev/null +++ b/.gitignore @@ -0,0 +1,404 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +build/ +ext/ +lib/ +*.sln +*.vcxproj diff --git a/MainMenuScreen.cpp b/MainMenuScreen.cpp index 656e804b0..b28ee2366 100644 --- a/MainMenuScreen.cpp +++ b/MainMenuScreen.cpp @@ -496,6 +496,13 @@ void HandleMainMenuKeyboardInput() gbHandledMainMenu = QUIT; HandleMainMenuInput(); break; + +//#ifdef _WIN32 +// // open bp discord! +// case 'z': +// ShellExecute(NULL, "open", "https://discord.gg/xtnydCjP", NULL, NULL, SW_SHOWNORMAL); +// break; +//#endif } } } diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 6811ac800..9bb399fc5 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "JA2 All.h" #include "PreBattle Interface.h" diff --git a/Standard Gaming Platform/sgp.cpp b/Standard Gaming Platform/sgp.cpp index 406bdd76c..84ef7cd0a 100644 --- a/Standard Gaming Platform/sgp.cpp +++ b/Standard Gaming Platform/sgp.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) /* $Id: sgp.c,v 1.4 2004/03/19 06:16:04 digicrab Exp $ */ //its test what doeas it do? #ifdef JA2_PRECOMPILED_HEADERS diff --git a/Standard Gaming Platform/vobject.cpp b/Standard Gaming Platform/vobject.cpp index baf76e853..6328f28ab 100644 --- a/Standard Gaming Platform/vobject.cpp +++ b/Standard Gaming Platform/vobject.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef JA2_PRECOMPILED_HEADERS #include "JA2 SGP ALL.H" #elif defined( WIZ8_PRECOMPILED_HEADERS ) diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index 876211ad6..bd3dc8eaf 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #else diff --git a/Strategic/Strategic AI.cpp b/Strategic/Strategic AI.cpp index 573493b77..bb4a718ee 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -3251,6 +3252,7 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ iDstGarrisonID ].ubComposition ); + //InitializeGroup(GROUP_TYPE_PATROL, (UINT8)iReinforcementsApproved, *pGroup->pEnemyGroup, Random(10) < gGameOptions.ubDifficultyLevel ); if (gGameExternalOptions.fASDActive && Random(10) < gGameOptions.ubDifficultyLevel) { ASDInitializePatrolGroup(pGroup); @@ -6886,7 +6888,12 @@ void RemoveSoldiersFromGarrisonBasedOnComposition( INT32 iGarrisonID, UINT8 ubSi } else { - Assert( 0 ); + + const UINT8 ubSectorX = (UINT8)SECTORX( gGarrisonGroup[ iGarrisonID ].ubSectorID ); + const UINT8 ubSectorY = (UINT8)SECTORY( gGarrisonGroup[ iGarrisonID ].ubSectorID ); + CHAR8 str[512]; + sprintf(str, "Couldn't elim elites at X/Y=%d/%d -- Sector A/T/E=%d/%d/%d -- Comp T/E=%d/%d -- Size=%d", ubSectorX, ubSectorY, ubOrigSectorAdmins, ubOrigSectorTroops, ubOrigSectorElites, ubOrigNumTroops, ubOrigNumElites, ubOrigSize); + AssertMsg(0, str); } ubNumElites--; } @@ -7146,7 +7153,7 @@ void InitializeGroup( const GROUP_TYPE groupType, const UINT8 groupSize, UINT8 & } } - // replace some soldiers with elites for attack groups + // replace some soldiers with elites if ( groupType == GROUP_TYPE_ATTACK && difficultyMod > 0 ) { eliteCount += troopCount - troopCount / difficultyMod; diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index ff88ef95a..75f9a3ce9 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -3339,10 +3340,11 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness if ( i > gArmyItemChoices[bSoldierClass][ typeIndex ].ubChoices ) break; - if (getMatchingCoolness == TRUE) - uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices); - else // otherwise there is a chance to pick nothing! - uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices + (int)(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices / 3)); + uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices + (int)(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices / 3)); +// if (getMatchingCoolness == TRUE) +// uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices); +// else // otherwise there is a chance to pick nothing! +// uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices + (int)(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices / 3)); if ( uiChoice >= gArmyItemChoices[bSoldierClass][ typeIndex ].ubChoices ) { @@ -3364,7 +3366,8 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness pickItem = FALSE; - if (usItem > 0 && Item[usItem].randomitem == 0 && ItemIsLegal(usItem)) + //if (usItem > 0 && Item[usItem].randomitem == 0 && ItemIsLegal(usItem)) + if (usItem >= 0 && Item[usItem].ubCoolness <= wantedCoolness && ItemIsLegal(usItem)) { // On day if (DayTime() == TRUE) @@ -3386,6 +3389,9 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness pickItem = TRUE; } } + +// if (Item[usItem].randomitem > 0) +// pickItem = FALSE; } @@ -3395,8 +3401,9 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness if (pickItem == TRUE) { // pick a default item in case we don't find anything with a matching coolness, but pick the most matching (by coolness) item - if ( defaultItem == 0 || - abs((int)wantedCoolness - (int)Item[usItem].ubCoolness) < abs((int)wantedCoolness - (int)Item[defaultItem].ubCoolness)) + //if ( defaultItem == 0 || + // abs((int)wantedCoolness - (int)Item[usItem].ubCoolness) < abs((int)wantedCoolness - (int)Item[defaultItem].ubCoolness)) + if (defaultItem == 0 || Item[usItem].ubCoolness > Item[defaultItem].ubCoolness) { defaultItem = usItem; } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index cde0fa8d6..a7ffee8e4 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1,3 +1,4 @@ +#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index f9fbce1a7..c3ee0620b 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -102,6 +102,7 @@ extern UINT8 gubItemDroppableFlag[NUM_INV_SLOTS]; //Random Stats RANDOM_STATS_VALUES gRandomStatsValue[NUM_PROFILES]; void RandomStats(); +void RandomSkills(); void RandomStartSalary(); //Jenilee @@ -463,6 +464,147 @@ void RandomStats() ExitRandomMercs(); } } +#pragma optimize("",off) +void RandomSkills() +{ + for (UINT32 cnt = 0; cnt < NUM_PROFILES; cnt++) + { + MERCPROFILESTRUCT* pProfile = &(gMercProfiles[cnt]); + + std::vector skillPool; + + // get current skills + int traitCount = 0; + for (int index = 0; index < (sizeof(pProfile->bSkillTraits) / sizeof(pProfile->bSkillTraits[0])); ++index) + { + if (pProfile->bSkillTraits[index] != 0) + { + skillPool.push_back(pProfile->bSkillTraits[index]); + traitCount++; + } + } + + // add random skills + int traitsToAdd = max(4 - traitCount, 2); + while (traitsToAdd > 0) + { + const INT8 random = Random(NUM_SKILLTRAITS_NT - 1) + 1; // skill traits 1-23. see SkillTraitNew enum + + // do we already have this skill? + int count = 0; + for (const INT8 skillId : skillPool) + { + if (random == skillId) + count++; + } + + // if a major trait and we have 2, restart + if ((random >= AUTO_WEAPONS_NT && random <= DOCTOR_NT) || random == COVERT_NT) + { + if (count >= 2) + continue; + } + // else if a minor trait and we have 1, restart + else if (count >= 1) + continue; + + // only add certain skills if appropriate-ish + switch (random) + { + case AUTO_WEAPONS_NT: + case HEAVY_WEAPONS_NT: + case SNIPER_NT: + case RANGER_NT: + case GUNSLINGER_NT: + if (pProfile->bMarksmanship < 75) continue; + break; + + case AMBIDEXTROUS_NT: + if (pProfile->bDexterity < 70) continue; + break; + + case BODYBUILDING_NT: + if (pProfile->bStrength < 70 && pProfile->bLifeMax < 70) continue; + break; + + case STEALTHY_NT: + if (pProfile->bAgility < 70) continue; + break; + + case SQUADLEADER_NT: + case TEACHING_NT: + if (pProfile->bLeadership < 40) continue; + break; + + case TECHNICIAN_NT: + if (pProfile->bMechanical < 40) continue; + break; + + case DOCTOR_NT: + if (pProfile->bMedical < 40) continue; + break; + + case DEMOLITIONS_NT: + if (pProfile->bExplosive < 40) continue; + break; + //AUTO_WEAPONS_NT, // 1 + //HEAVY_WEAPONS_NT, // 2 + //SNIPER_NT, // 3 + //RANGER_NT, // 4 + //GUNSLINGER_NT, // 5 + //MARTIAL_ARTS_NT, // 6 + //SQUADLEADER_NT, // 7 + //TECHNICIAN_NT, // 8 + //DOCTOR_NT, // 9 + //AMBIDEXTROUS_NT, // 10 + //MELEE_NT, // 11 + //THROWING_NT, // 12 + //NIGHT_OPS_NT, // 13 + //STEALTHY_NT, // 14 + //ATHLETICS_NT, // 15 + //BODYBUILDING_NT, // 16 + //DEMOLITIONS_NT, // 17 + //TEACHING_NT, // 18 + //SCOUTING_NT, // 19 + //COVERT_NT, // 20 // a major trait + //RADIO_OPERATOR_NT, //21 // a minor trait + //SNITCH_NT, //22 // a minor trait + //SURVIVAL_NT, //23 // a minor trait + } + + // add the skill + skillPool.push_back(random); + traitsToAdd--; + } + + // shuffle traits + for (int a = 0; a < skillPool.size(); ++a) + { + const int randomIndex = Random(skillPool.size()); + std::swap(skillPool[a], skillPool[randomIndex]); + } + + int traitsToKeep = max(4, traitCount + 1); + traitsToKeep = min(traitsToKeep, skillPool.size()); + + // copy over final skills + std::vector::const_iterator iter = skillPool.cbegin(); + for (int index = 0; index < (sizeof(pProfile->bSkillTraits) / sizeof(pProfile->bSkillTraits[0])); ++index) + { + if (index < traitsToKeep && iter != skillPool.cend()) + { + pProfile->bSkillTraits[index] = *iter; + iter++; + } + else + { + pProfile->bSkillTraits[index] = 0; + } + } + } +} +#pragma optimize("",on) + void RandomStartSalary() { UINT32 cnt; @@ -1000,6 +1142,8 @@ for( int i = 0; i < NUM_PROFILES; i++ ) // --------------- RandomStats (); //random stats by Jazz + + RandomSkills(); // Buggler: random starting salary RandomStartSalary (); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index b0707e9d0..6ea78bf6d 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -290,7 +290,7 @@ STR16 pEncyclopediaFilterCharText[] = {//major char filter button text //..L"------v" L"全部",//All - L"A.I.M.", + L"A.I.M", L"MERC", L"RPC", L"NPC", @@ -4219,7 +4219,7 @@ STR16 pHelicopterEtaStrings[] = L"Skyrider", L"着陆点", L"直升机严重受损,必须降落在敌军领地!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> - L"直升机将直接返回基地,你希望在此之前丢下乘客吗?", + L"直升机将直接返回基地,你希望在此之前放下乘客吗?", L"剩余燃料:", L"到加油站距离:", }; @@ -5099,7 +5099,7 @@ STR16 pLaptopIcons[] = STR16 pBookMarkStrings[] = { - L"A.I.M.", + L"A.I.M", L"Bobby Ray's", L"I.M.P", L"M.E.R.C", @@ -7032,7 +7032,7 @@ STR16 pMessageStrings[] = L"磁盘空间不足。只有%sMB可用空间,《铁血联盟2》需要%sMB。", L"从AIM雇佣了%s。", //"Hired %s from AIM", L"%s抓住了%s。", //"%s has caught %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. - L"%s使用了%s。", //L"%s has taken %s。", + L"%s使用了(拾取)%s。", //L"%s has taken %s。", L"%s没有医疗技能", //"%s has no medical skill",//'Merc name' has no medical skill. //CDRom errors (such as ejecting CD while attempting to read the CD) @@ -11373,17 +11373,17 @@ STR16 szIMPGearPocketText[] = L"选择头部装备", //L"Select face gear", L"选择头部装备", // L"Select face gear", - L"选择主枪", // L"Select main gun", - L"选择手枪", //L"Select sidearm", + L"选择主武器", // L"Select main gun", + L"选择副武器", //L"Select sidearm", L"选择LBE背心", //L"Select LBE vest", - L"选择LBE皮套", //L"Select left LBE holster", - L"选择LBE皮套", //L"Select right LBE holster", + L"选择左LBE枪套", //L"Select left LBE holster", + L"选择右LBE枪套", //L"Select right LBE holster", L"选择LBE战斗包", //L"Select LBE combat pack", L"选择LBE背包", //L"Select LBE backpack", - L"Select launcher / rifle", - L"选择武器", //L"Select melee weapon", + L"选择发射器/步枪", //L"Select launcher / rifle", + L"选择近战武器", //L"Select melee weapon", L"选择附加物品", //L"Select additional items", //BIGPOCK1POS L"选择附加物品", //L"Select additional items", @@ -11392,28 +11392,28 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", - L"Select medkit", //MEDPOCK1POS - L"Select medkit", - L"Select medkit", - L"Select medkit", - L"Select main gun ammo", //SMALLPOCK1POS - L"Select main gun ammo", - L"Select main gun ammo", - L"Select main gun ammo", - L"Select main gun ammo", - L"Select launcher / rifle ammo", //SMALLPOCK6POS - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select sidearm ammo", //SMALLPOCK11POS - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", + L"选择医疗套件", //L"Select medkit",MEDPOCK1POS + L"选择医疗套件", //L"Select medkit", + L"选择医疗套件", //L"Select medkit", + L"选择医疗套件", //L"Select medkit", + L"选择主武器弹药", //L"Select main gun ammo",SMALLPOCK1POS + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo",SMALLPOCK6POS + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择配枪弹药", //L"Select sidearm ammo",SMALLPOCK11POS + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", L"选择附加物品", //L"Select additional items", //SMALLPOCK19POS L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", @@ -11426,7 +11426,7 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", //SMALLPOCK30POS - L"Left click to select item / Right click to close window", + L"左键单击选择项目/右键单击关闭窗口", //L"Left click to select item / Right click to close window", }; STR16 szMilitiaStrategicMovementText[] = diff --git a/ext/VFS/build/VFS_VS2019.vcxproj b/ext/VFS/build/VFS_VS2019.vcxproj index 5a0b71328..ecdec418b 100644 --- a/ext/VFS/build/VFS_VS2019.vcxproj +++ b/ext/VFS/build/VFS_VS2019.vcxproj @@ -126,10 +126,10 @@ - StaticLibrary true NotSet v142 + StaticLibrary StaticLibrary @@ -151,7 +151,6 @@ StaticLibrary - false false NotSet v142 @@ -225,16 +224,12 @@ - - ..\..\..\lib\VS2013\$(Configuration)\ - + ..\..\..\lib\VS2013\$(Configuration)\ - - ..\..\..\build\VS2013\$(ProjectName)_$(Configuration)\ - + ..\..\..\build\VS2013\$(ProjectName)_$(Configuration)\ @@ -338,10 +333,10 @@ - Windows true true true + Windows diff --git a/ext/VFS/build/VFS_VS2019.vcxproj.user b/ext/VFS/build/VFS_VS2019.vcxproj.user index e4c0d17a1..a3e122771 100644 --- a/ext/VFS/build/VFS_VS2019.vcxproj.user +++ b/ext/VFS/build/VFS_VS2019.vcxproj.user @@ -1,8 +1,8 @@  - H:\JA2 Dev WindowsLocalDebugger + true H:\JA2 Dev diff --git a/ja2_VS2019.sln b/ja2_VS2019.sln index e9ab65259..cd4a0034b 100644 --- a/ja2_VS2019.sln +++ b/ja2_VS2019.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.645 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30320.27 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VFS", "ext\VFS\build\VFS_VS2019.vcxproj", "{463CB476-2798-493F-9CE8-CEAC5ECE5664}" ProjectSection(ProjectDependencies) = postProject @@ -360,9 +360,10 @@ Global {802552D2-B514-42E5-A169-F1E108527678}.Release_WithDebugInfo|Win32.ActiveCfg = Debug|Win32 {802552D2-B514-42E5-A169-F1E108527678}.Release_WithDebugInfo|x64.ActiveCfg = Release_WithDebugInfo|x64 {802552D2-B514-42E5-A169-F1E108527678}.Release|Win32.ActiveCfg = Release|Win32 + {802552D2-B514-42E5-A169-F1E108527678}.Release|Win32.Build.0 = Release|Win32 {802552D2-B514-42E5-A169-F1E108527678}.Release|x64.ActiveCfg = Release|x64 - {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.ActiveCfg = Debug|Win32 - {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.Build.0 = Debug|Win32 + {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.ActiveCfg = Release_WithDebugInfo|Win32 + {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.Build.0 = Release_WithDebugInfo|Win32 {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|x64.ActiveCfg = Debug|x64 {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|x64.Build.0 = Debug|x64 {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.MapEditor|Win32.ActiveCfg = MapEditor|Win32 diff --git a/ja2_VS2019.vcxproj b/ja2_VS2019.vcxproj index 6140ccaf9..362412480 100644 --- a/ja2_VS2019.vcxproj +++ b/ja2_VS2019.vcxproj @@ -193,8 +193,8 @@ true $(JA2Config)_$(JA2LangPrefix)_$(Configuration)_master .exe - $(SolutionDir)\bin\VS2013\ - $(SolutionDir)\build\VS2013\$(JA2Config)_$(JA2LangPrefix)\$(ProjectName)_$(Configuration)\ + ..\OUTPUT\1dot13 + $(SolutionDir)$(Configuration)\ true @@ -217,7 +217,7 @@ false $(JA2Config)_$(JA2LangPrefix)_$(Configuration)_master_VS2019 .exe - $(SolutionDir)\bin\VS2013\ + ..\OUTPUT\1dot13 $(SolutionDir)\build\VS2013\$(JA2Config)_$(JA2LangPrefix)\$(ProjectName)_$(Configuration)\ From 7c6f7d6d0972408873491a7c12aa5e90b23f0c7b Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 22:40:25 -0700 Subject: [PATCH 47/52] Revert "Undo unrelated Chinese text changes" This reverts commit 75332ea2193e7a53884f943f6658d0ff73012f3e. --- .gitignore | 404 -------------------------- MainMenuScreen.cpp | 7 - SaveLoadGame.cpp | 1 - Standard Gaming Platform/sgp.cpp | 1 - Standard Gaming Platform/vobject.cpp | 1 - Strategic/Hourly Update.cpp | 1 - Strategic/Strategic AI.cpp | 11 +- Tactical/Inventory Choosing.cpp | 21 +- Tactical/Soldier Control.cpp | 1 - Tactical/Soldier Profile.cpp | 144 --------- Utils/_ChineseText.cpp | 62 ++-- ext/VFS/build/VFS_VS2019.vcxproj | 13 +- ext/VFS/build/VFS_VS2019.vcxproj.user | 2 +- ja2_VS2019.sln | 9 +- ja2_VS2019.vcxproj | 6 +- 15 files changed, 57 insertions(+), 627 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 92e01666c..000000000 --- a/.gitignore +++ /dev/null @@ -1,404 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.tlog -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - -# Visual Studio 6 workspace and project file (working project files containing files to include in project) -*.dsw -*.dsp - -# Visual Studio 6 technical files -*.ncb -*.aps - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# Visual Studio History (VSHistory) files -.vshistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -# VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.code-workspace - -# Local History for Visual Studio Code -.history/ - -# Windows Installer files from build outputs -*.cab -*.msi -*.msix -*.msm -*.msp - -# JetBrains Rider -*.sln.iml - -build/ -ext/ -lib/ -*.sln -*.vcxproj diff --git a/MainMenuScreen.cpp b/MainMenuScreen.cpp index b28ee2366..656e804b0 100644 --- a/MainMenuScreen.cpp +++ b/MainMenuScreen.cpp @@ -496,13 +496,6 @@ void HandleMainMenuKeyboardInput() gbHandledMainMenu = QUIT; HandleMainMenuInput(); break; - -//#ifdef _WIN32 -// // open bp discord! -// case 'z': -// ShellExecute(NULL, "open", "https://discord.gg/xtnydCjP", NULL, NULL, SW_SHOWNORMAL); -// break; -//#endif } } } diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 9bb399fc5..6811ac800 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "JA2 All.h" #include "PreBattle Interface.h" diff --git a/Standard Gaming Platform/sgp.cpp b/Standard Gaming Platform/sgp.cpp index 84ef7cd0a..406bdd76c 100644 --- a/Standard Gaming Platform/sgp.cpp +++ b/Standard Gaming Platform/sgp.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) /* $Id: sgp.c,v 1.4 2004/03/19 06:16:04 digicrab Exp $ */ //its test what doeas it do? #ifdef JA2_PRECOMPILED_HEADERS diff --git a/Standard Gaming Platform/vobject.cpp b/Standard Gaming Platform/vobject.cpp index 6328f28ab..baf76e853 100644 --- a/Standard Gaming Platform/vobject.cpp +++ b/Standard Gaming Platform/vobject.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef JA2_PRECOMPILED_HEADERS #include "JA2 SGP ALL.H" #elif defined( WIZ8_PRECOMPILED_HEADERS ) diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index bd3dc8eaf..876211ad6 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #else diff --git a/Strategic/Strategic AI.cpp b/Strategic/Strategic AI.cpp index bb4a718ee..573493b77 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Strategic All.h" #include "GameSettings.h" @@ -3252,7 +3251,6 @@ BOOLEAN SendReinforcementsForGarrison( INT32 iDstGarrisonID, UINT16 usDefencePoi pGroup = CreateNewEnemyGroupDepartingFromSector( gGarrisonGroup[ iSrcGarrisonID ].ubSectorID, 0, (UINT8)iReinforcementsApproved, 0, 0, 0, 0 ); ConvertGroupTroopsToComposition( pGroup, gGarrisonGroup[ iDstGarrisonID ].ubComposition ); - //InitializeGroup(GROUP_TYPE_PATROL, (UINT8)iReinforcementsApproved, *pGroup->pEnemyGroup, Random(10) < gGameOptions.ubDifficultyLevel ); if (gGameExternalOptions.fASDActive && Random(10) < gGameOptions.ubDifficultyLevel) { ASDInitializePatrolGroup(pGroup); @@ -6888,12 +6886,7 @@ void RemoveSoldiersFromGarrisonBasedOnComposition( INT32 iGarrisonID, UINT8 ubSi } else { - - const UINT8 ubSectorX = (UINT8)SECTORX( gGarrisonGroup[ iGarrisonID ].ubSectorID ); - const UINT8 ubSectorY = (UINT8)SECTORY( gGarrisonGroup[ iGarrisonID ].ubSectorID ); - CHAR8 str[512]; - sprintf(str, "Couldn't elim elites at X/Y=%d/%d -- Sector A/T/E=%d/%d/%d -- Comp T/E=%d/%d -- Size=%d", ubSectorX, ubSectorY, ubOrigSectorAdmins, ubOrigSectorTroops, ubOrigSectorElites, ubOrigNumTroops, ubOrigNumElites, ubOrigSize); - AssertMsg(0, str); + Assert( 0 ); } ubNumElites--; } @@ -7153,7 +7146,7 @@ void InitializeGroup( const GROUP_TYPE groupType, const UINT8 groupSize, UINT8 & } } - // replace some soldiers with elites + // replace some soldiers with elites for attack groups if ( groupType == GROUP_TYPE_ATTACK && difficultyMod > 0 ) { eliteCount += troopCount - troopCount / difficultyMod; diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index 75f9a3ce9..ff88ef95a 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -3340,11 +3339,10 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness if ( i > gArmyItemChoices[bSoldierClass][ typeIndex ].ubChoices ) break; - uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices + (int)(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices / 3)); -// if (getMatchingCoolness == TRUE) -// uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices); -// else // otherwise there is a chance to pick nothing! -// uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices + (int)(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices / 3)); + if (getMatchingCoolness == TRUE) + uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices); + else // otherwise there is a chance to pick nothing! + uiChoice = Random(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices + (int)(gArmyItemChoices[bSoldierClass][typeIndex].ubChoices / 3)); if ( uiChoice >= gArmyItemChoices[bSoldierClass][ typeIndex ].ubChoices ) { @@ -3366,8 +3364,7 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness pickItem = FALSE; - //if (usItem > 0 && Item[usItem].randomitem == 0 && ItemIsLegal(usItem)) - if (usItem >= 0 && Item[usItem].ubCoolness <= wantedCoolness && ItemIsLegal(usItem)) + if (usItem > 0 && Item[usItem].randomitem == 0 && ItemIsLegal(usItem)) { // On day if (DayTime() == TRUE) @@ -3389,9 +3386,6 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness pickItem = TRUE; } } - -// if (Item[usItem].randomitem > 0) -// pickItem = FALSE; } @@ -3401,9 +3395,8 @@ UINT16 PickARandomItem(UINT8 typeIndex, INT8 bSoldierClass, UINT8 wantedCoolness if (pickItem == TRUE) { // pick a default item in case we don't find anything with a matching coolness, but pick the most matching (by coolness) item - //if ( defaultItem == 0 || - // abs((int)wantedCoolness - (int)Item[usItem].ubCoolness) < abs((int)wantedCoolness - (int)Item[defaultItem].ubCoolness)) - if (defaultItem == 0 || Item[usItem].ubCoolness > Item[defaultItem].ubCoolness) + if ( defaultItem == 0 || + abs((int)wantedCoolness - (int)Item[usItem].ubCoolness) < abs((int)wantedCoolness - (int)Item[defaultItem].ubCoolness)) { defaultItem = usItem; } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index a7ffee8e4..cde0fa8d6 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1,4 +1,3 @@ -#pragma optimize("",off) #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index c3ee0620b..f9fbce1a7 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -102,7 +102,6 @@ extern UINT8 gubItemDroppableFlag[NUM_INV_SLOTS]; //Random Stats RANDOM_STATS_VALUES gRandomStatsValue[NUM_PROFILES]; void RandomStats(); -void RandomSkills(); void RandomStartSalary(); //Jenilee @@ -464,147 +463,6 @@ void RandomStats() ExitRandomMercs(); } } -#pragma optimize("",off) -void RandomSkills() -{ - for (UINT32 cnt = 0; cnt < NUM_PROFILES; cnt++) - { - MERCPROFILESTRUCT* pProfile = &(gMercProfiles[cnt]); - - std::vector skillPool; - - // get current skills - int traitCount = 0; - for (int index = 0; index < (sizeof(pProfile->bSkillTraits) / sizeof(pProfile->bSkillTraits[0])); ++index) - { - if (pProfile->bSkillTraits[index] != 0) - { - skillPool.push_back(pProfile->bSkillTraits[index]); - traitCount++; - } - } - - // add random skills - int traitsToAdd = max(4 - traitCount, 2); - while (traitsToAdd > 0) - { - const INT8 random = Random(NUM_SKILLTRAITS_NT - 1) + 1; // skill traits 1-23. see SkillTraitNew enum - - // do we already have this skill? - int count = 0; - for (const INT8 skillId : skillPool) - { - if (random == skillId) - count++; - } - - // if a major trait and we have 2, restart - if ((random >= AUTO_WEAPONS_NT && random <= DOCTOR_NT) || random == COVERT_NT) - { - if (count >= 2) - continue; - } - // else if a minor trait and we have 1, restart - else if (count >= 1) - continue; - - // only add certain skills if appropriate-ish - switch (random) - { - case AUTO_WEAPONS_NT: - case HEAVY_WEAPONS_NT: - case SNIPER_NT: - case RANGER_NT: - case GUNSLINGER_NT: - if (pProfile->bMarksmanship < 75) continue; - break; - - case AMBIDEXTROUS_NT: - if (pProfile->bDexterity < 70) continue; - break; - - case BODYBUILDING_NT: - if (pProfile->bStrength < 70 && pProfile->bLifeMax < 70) continue; - break; - - case STEALTHY_NT: - if (pProfile->bAgility < 70) continue; - break; - - case SQUADLEADER_NT: - case TEACHING_NT: - if (pProfile->bLeadership < 40) continue; - break; - - case TECHNICIAN_NT: - if (pProfile->bMechanical < 40) continue; - break; - - case DOCTOR_NT: - if (pProfile->bMedical < 40) continue; - break; - - case DEMOLITIONS_NT: - if (pProfile->bExplosive < 40) continue; - break; - //AUTO_WEAPONS_NT, // 1 - //HEAVY_WEAPONS_NT, // 2 - //SNIPER_NT, // 3 - //RANGER_NT, // 4 - //GUNSLINGER_NT, // 5 - //MARTIAL_ARTS_NT, // 6 - //SQUADLEADER_NT, // 7 - //TECHNICIAN_NT, // 8 - //DOCTOR_NT, // 9 - //AMBIDEXTROUS_NT, // 10 - //MELEE_NT, // 11 - //THROWING_NT, // 12 - //NIGHT_OPS_NT, // 13 - //STEALTHY_NT, // 14 - //ATHLETICS_NT, // 15 - //BODYBUILDING_NT, // 16 - //DEMOLITIONS_NT, // 17 - //TEACHING_NT, // 18 - //SCOUTING_NT, // 19 - //COVERT_NT, // 20 // a major trait - //RADIO_OPERATOR_NT, //21 // a minor trait - //SNITCH_NT, //22 // a minor trait - //SURVIVAL_NT, //23 // a minor trait - } - - // add the skill - skillPool.push_back(random); - traitsToAdd--; - } - - // shuffle traits - for (int a = 0; a < skillPool.size(); ++a) - { - const int randomIndex = Random(skillPool.size()); - std::swap(skillPool[a], skillPool[randomIndex]); - } - - int traitsToKeep = max(4, traitCount + 1); - traitsToKeep = min(traitsToKeep, skillPool.size()); - - // copy over final skills - std::vector::const_iterator iter = skillPool.cbegin(); - for (int index = 0; index < (sizeof(pProfile->bSkillTraits) / sizeof(pProfile->bSkillTraits[0])); ++index) - { - if (index < traitsToKeep && iter != skillPool.cend()) - { - pProfile->bSkillTraits[index] = *iter; - iter++; - } - else - { - pProfile->bSkillTraits[index] = 0; - } - } - } -} -#pragma optimize("",on) - void RandomStartSalary() { UINT32 cnt; @@ -1142,8 +1000,6 @@ for( int i = 0; i < NUM_PROFILES; i++ ) // --------------- RandomStats (); //random stats by Jazz - - RandomSkills(); // Buggler: random starting salary RandomStartSalary (); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 6ea78bf6d..34792c953 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -4219,7 +4219,7 @@ STR16 pHelicopterEtaStrings[] = L"Skyrider", L"着陆点", L"直升机严重受损,必须降落在敌军领地!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> - L"直升机将直接返回基地,你希望在此之前放下乘客吗?", + L"直升机将直接返回基地,你希望在此之前丢下乘客吗?", L"剩余燃料:", L"到加油站距离:", }; @@ -7032,7 +7032,7 @@ STR16 pMessageStrings[] = L"磁盘空间不足。只有%sMB可用空间,《铁血联盟2》需要%sMB。", L"从AIM雇佣了%s。", //"Hired %s from AIM", L"%s抓住了%s。", //"%s has caught %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. - L"%s使用了(拾取)%s。", //L"%s has taken %s。", + L"%s使用了%s。", //L"%s has taken %s。", L"%s没有医疗技能", //"%s has no medical skill",//'Merc name' has no medical skill. //CDRom errors (such as ejecting CD while attempting to read the CD) @@ -11373,17 +11373,17 @@ STR16 szIMPGearPocketText[] = L"选择头部装备", //L"Select face gear", L"选择头部装备", // L"Select face gear", - L"选择主武器", // L"Select main gun", - L"选择副武器", //L"Select sidearm", + L"选择主枪", // L"Select main gun", + L"选择手枪", //L"Select sidearm", L"选择LBE背心", //L"Select LBE vest", - L"选择左LBE枪套", //L"Select left LBE holster", - L"选择右LBE枪套", //L"Select right LBE holster", + L"选择LBE皮套", //L"Select left LBE holster", + L"选择LBE皮套", //L"Select right LBE holster", L"选择LBE战斗包", //L"Select LBE combat pack", L"选择LBE背包", //L"Select LBE backpack", - L"选择发射器/步枪", //L"Select launcher / rifle", - L"选择近战武器", //L"Select melee weapon", + L"Select launcher / rifle", + L"选择武器", //L"Select melee weapon", L"选择附加物品", //L"Select additional items", //BIGPOCK1POS L"选择附加物品", //L"Select additional items", @@ -11392,28 +11392,28 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", - L"选择医疗套件", //L"Select medkit",MEDPOCK1POS - L"选择医疗套件", //L"Select medkit", - L"选择医疗套件", //L"Select medkit", - L"选择医疗套件", //L"Select medkit", - L"选择主武器弹药", //L"Select main gun ammo",SMALLPOCK1POS - L"选择主武器弹药", //L"Select main gun ammo", - L"选择主武器弹药", //L"Select main gun ammo", - L"选择主武器弹药", //L"Select main gun ammo", - L"选择主武器弹药", //L"Select main gun ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo",SMALLPOCK6POS - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", - L"选择配枪弹药", //L"Select sidearm ammo",SMALLPOCK11POS - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", - L"选择配枪弹药", //L"Select sidearm ammo", + L"Select medkit", //MEDPOCK1POS + L"Select medkit", + L"Select medkit", + L"Select medkit", + L"Select main gun ammo", //SMALLPOCK1POS + L"Select main gun ammo", + L"Select main gun ammo", + L"Select main gun ammo", + L"Select main gun ammo", + L"Select launcher / rifle ammo", //SMALLPOCK6POS + L"Select launcher / rifle ammo", + L"Select launcher / rifle ammo", + L"Select launcher / rifle ammo", + L"Select launcher / rifle ammo", + L"Select sidearm ammo", //SMALLPOCK11POS + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", + L"Select sidearm ammo", L"选择附加物品", //L"Select additional items", //SMALLPOCK19POS L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", @@ -11426,7 +11426,7 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", //SMALLPOCK30POS - L"左键单击选择项目/右键单击关闭窗口", //L"Left click to select item / Right click to close window", + L"Left click to select item / Right click to close window", }; STR16 szMilitiaStrategicMovementText[] = diff --git a/ext/VFS/build/VFS_VS2019.vcxproj b/ext/VFS/build/VFS_VS2019.vcxproj index ecdec418b..5a0b71328 100644 --- a/ext/VFS/build/VFS_VS2019.vcxproj +++ b/ext/VFS/build/VFS_VS2019.vcxproj @@ -126,10 +126,10 @@ + StaticLibrary true NotSet v142 - StaticLibrary StaticLibrary @@ -151,6 +151,7 @@ StaticLibrary + false false NotSet v142 @@ -224,12 +225,16 @@ - + + ..\..\..\lib\VS2013\$(Configuration)\ + ..\..\..\lib\VS2013\$(Configuration)\ - + + ..\..\..\build\VS2013\$(ProjectName)_$(Configuration)\ + ..\..\..\build\VS2013\$(ProjectName)_$(Configuration)\ @@ -333,10 +338,10 @@ + Windows true true true - Windows diff --git a/ext/VFS/build/VFS_VS2019.vcxproj.user b/ext/VFS/build/VFS_VS2019.vcxproj.user index a3e122771..e4c0d17a1 100644 --- a/ext/VFS/build/VFS_VS2019.vcxproj.user +++ b/ext/VFS/build/VFS_VS2019.vcxproj.user @@ -1,8 +1,8 @@  + H:\JA2 Dev WindowsLocalDebugger - true H:\JA2 Dev diff --git a/ja2_VS2019.sln b/ja2_VS2019.sln index cd4a0034b..e9ab65259 100644 --- a/ja2_VS2019.sln +++ b/ja2_VS2019.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30320.27 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.645 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VFS", "ext\VFS\build\VFS_VS2019.vcxproj", "{463CB476-2798-493F-9CE8-CEAC5ECE5664}" ProjectSection(ProjectDependencies) = postProject @@ -360,10 +360,9 @@ Global {802552D2-B514-42E5-A169-F1E108527678}.Release_WithDebugInfo|Win32.ActiveCfg = Debug|Win32 {802552D2-B514-42E5-A169-F1E108527678}.Release_WithDebugInfo|x64.ActiveCfg = Release_WithDebugInfo|x64 {802552D2-B514-42E5-A169-F1E108527678}.Release|Win32.ActiveCfg = Release|Win32 - {802552D2-B514-42E5-A169-F1E108527678}.Release|Win32.Build.0 = Release|Win32 {802552D2-B514-42E5-A169-F1E108527678}.Release|x64.ActiveCfg = Release|x64 - {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.ActiveCfg = Release_WithDebugInfo|Win32 - {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.Build.0 = Release_WithDebugInfo|Win32 + {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.ActiveCfg = Debug|Win32 + {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|Win32.Build.0 = Debug|Win32 {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|x64.ActiveCfg = Debug|x64 {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.Debug|x64.Build.0 = Debug|x64 {3B7B950D-0DC8-4ADD-9FE2-7DE4297C62F6}.MapEditor|Win32.ActiveCfg = MapEditor|Win32 diff --git a/ja2_VS2019.vcxproj b/ja2_VS2019.vcxproj index 362412480..6140ccaf9 100644 --- a/ja2_VS2019.vcxproj +++ b/ja2_VS2019.vcxproj @@ -193,8 +193,8 @@ true $(JA2Config)_$(JA2LangPrefix)_$(Configuration)_master .exe - ..\OUTPUT\1dot13 - $(SolutionDir)$(Configuration)\ + $(SolutionDir)\bin\VS2013\ + $(SolutionDir)\build\VS2013\$(JA2Config)_$(JA2LangPrefix)\$(ProjectName)_$(Configuration)\ true @@ -217,7 +217,7 @@ false $(JA2Config)_$(JA2LangPrefix)_$(Configuration)_master_VS2019 .exe - ..\OUTPUT\1dot13 + $(SolutionDir)\bin\VS2013\ $(SolutionDir)\build\VS2013\$(JA2Config)_$(JA2LangPrefix)\$(ProjectName)_$(Configuration)\ From edad33eb9fe0f1c43da2508e336818be9b9feb55 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 22:45:54 -0700 Subject: [PATCH 48/52] Properly undo unrelated Chinese text changes --- Utils/_ChineseText.cpp | 64 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 34792c953..2fa671e8f 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -4219,7 +4219,7 @@ STR16 pHelicopterEtaStrings[] = L"Skyrider", L"着陆点", L"直升机严重受损,必须降落在敌军领地!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> - L"直升机将直接返回基地,你希望在此之前丢下乘客吗?", + L"直升机将直接返回基地,你希望在此之前放下乘客吗?", L"剩余燃料:", L"到加油站距离:", }; @@ -7032,7 +7032,7 @@ STR16 pMessageStrings[] = L"磁盘空间不足。只有%sMB可用空间,《铁血联盟2》需要%sMB。", L"从AIM雇佣了%s。", //"Hired %s from AIM", L"%s抓住了%s。", //"%s has caught %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. - L"%s使用了%s。", //L"%s has taken %s。", + L"%s使用了(拾取)%s。", //L"%s has taken %s。", L"%s没有医疗技能", //"%s has no medical skill",//'Merc name' has no medical skill. //CDRom errors (such as ejecting CD while attempting to read the CD) @@ -11371,19 +11371,19 @@ STR16 szIMPGearPocketText[] = L"选择背心", // L"Select vest", L"选择裤子", //L"Select pants", L"选择头部装备", //L"Select face gear", - L"选择头部装备", // L"Select face gear", + L"选择头部装备", //L"Select face gear", - L"选择主枪", // L"Select main gun", - L"选择手枪", //L"Select sidearm", + L"选择主武器", //L"Select main gun", + L"选择副武器", //L"Select sidearm", L"选择LBE背心", //L"Select LBE vest", - L"选择LBE皮套", //L"Select left LBE holster", - L"选择LBE皮套", //L"Select right LBE holster", + L"选择左LBE枪套", //L"Select left LBE holster", + L"选择右LBE枪套", //L"Select right LBE holster", L"选择LBE战斗包", //L"Select LBE combat pack", L"选择LBE背包", //L"Select LBE backpack", - L"Select launcher / rifle", - L"选择武器", //L"Select melee weapon", + L"选择发射器/步枪", //L"Select launcher / rifle", + L"选择近战武器", //L"Select melee weapon", L"选择附加物品", //L"Select additional items", //BIGPOCK1POS L"选择附加物品", //L"Select additional items", @@ -11392,28 +11392,28 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", - L"Select medkit", //MEDPOCK1POS - L"Select medkit", - L"Select medkit", - L"Select medkit", - L"Select main gun ammo", //SMALLPOCK1POS - L"Select main gun ammo", - L"Select main gun ammo", - L"Select main gun ammo", - L"Select main gun ammo", - L"Select launcher / rifle ammo", //SMALLPOCK6POS - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select launcher / rifle ammo", - L"Select sidearm ammo", //SMALLPOCK11POS - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", - L"Select sidearm ammo", + L"选择医疗套件", //L"Select medkit",MEDPOCK1POS + L"选择医疗套件", //L"Select medkit", + L"选择医疗套件", //L"Select medkit", + L"选择医疗套件", //L"Select medkit", + L"选择主武器弹药", //L"Select main gun ammo",SMALLPOCK1POS + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择主武器弹药", //L"Select main gun ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo",SMALLPOCK6POS + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择发射器/枪弹药", //L"Select launcher / rifle ammo", + L"选择配枪弹药", //L"Select sidearm ammo",SMALLPOCK11POS + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", + L"选择配枪弹药", //L"Select sidearm ammo", L"选择附加物品", //L"Select additional items", //SMALLPOCK19POS L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", @@ -11426,7 +11426,7 @@ STR16 szIMPGearPocketText[] = L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", L"选择附加物品", //L"Select additional items", //SMALLPOCK30POS - L"Left click to select item / Right click to close window", + L"左键单击选择项目/右键单击关闭窗口", //L"Left click to select item / Right click to close window", }; STR16 szMilitiaStrategicMovementText[] = From 5dd002db298d628b354dfaa7dad26bdc273cb6d9 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 22:53:21 -0700 Subject: [PATCH 49/52] Update text --- Utils/_ChineseText.cpp | 3 +++ Utils/_DutchText.cpp | 3 +++ Utils/_FrenchText.cpp | 3 +++ Utils/_GermanText.cpp | 3 +++ Utils/_ItalianText.cpp | 3 +++ Utils/_PolishText.cpp | 3 +++ Utils/_RussianText.cpp | 3 +++ 7 files changed, 21 insertions(+) diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 2fa671e8f..16d4f03e9 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11966,6 +11966,7 @@ STR16 szRebelCommandText[] = L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12104,6 +12105,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 95d2132c5..1afaa83e1 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11976,6 +11976,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12114,6 +12115,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 2b9c1648b..1f264bd3f 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11958,6 +11958,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12096,6 +12097,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index a95d08340..059f894f2 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11880,6 +11880,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12018,6 +12019,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 8973e7e09..4acaaf5d2 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11967,6 +11967,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12105,6 +12106,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 4e4c06c9a..ceed1a17c 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11980,6 +11980,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12118,6 +12119,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 948984170..76308a088 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11961,6 +11961,7 @@ STR16 szRebelCommandText[] = // TODO.Translate L"Town loyalty too low", L"Agent unavailable", L"Agent contract expiring", + L"Can't use rebel agent", L"Battle in progress", L"Prepare Mission (%d supplies)", L"View active mission effects", @@ -12099,6 +12100,8 @@ STR16 szRebelCommandAgentMissionsText[] = L"Disrupt enemy supply chains and prevent the enemy from maintaining their gear properly. Enemy soldiers use equipment that is worse than normal.", L"Sabotage Vehicles", L"Sabotage vehicle maintenance hubs to reduce their combat effectiveness and readiness. Enemy vehicles encountered have reduced stats.", + L"Send Supplies", + L"Temporarily increase direct support to this town. Town loyalty passively increases for the duration of the mission.", 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.", L"Train Militia Anywhere", From 76a5fa1731c9905e79d49cbd74f5a196fe177629 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 22:55:38 -0700 Subject: [PATCH 50/52] Remove #pragma optimize --- Strategic/Rebel Command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index d95d3afc6..a986a2cf0 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -1,4 +1,4 @@ -#pragma optimize("", off) +//#pragma optimize("", off) /* Rebel Command by rftr From b401e3944ef2cb474cd499ce9c03e98a54314b38 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 23:00:00 -0700 Subject: [PATCH 51/52] Update gameversion --- GameVersion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GameVersion.cpp b/GameVersion.cpp index 99f52ce6d..7f4a6d8fa 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -57,6 +57,6 @@ CHAR8 czVersionNumber[16] = { "Build 22.11.04" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; -CHAR16 zRevisionNumber[16] = { L"Revision 9404" }; +CHAR16 zRevisionNumber[16] = { L"Revision 9405" }; // SAVE_GAME_VERSION is defined in header, change it there From f6241feb349b9b1f8c19457c662bc2702a5186dd Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Fri, 4 Nov 2022 23:15:30 -0700 Subject: [PATCH 52/52] Properly reduce ASD resources --- Strategic/Rebel Command.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Strategic/Rebel Command.cpp b/Strategic/Rebel Command.cpp index a986a2cf0..181eca14d 100644 --- a/Strategic/Rebel Command.cpp +++ b/Strategic/Rebel Command.cpp @@ -4741,7 +4741,7 @@ void ApplyAdditionalASDEffects() CreateItemAtAirport(ItemIdCache::gasCans.at(ItemIdCache::gasCans.size()), 75 + Random(26)); // say it came from the ASD's reserves - AddStrategicAIResources(ASD_FUEL, gGameExternalOptions.gASDResource_Fuel_Jeep + Random(gGameExternalOptions.gASDResource_Fuel_Jeep)); + AddStrategicAIResources(ASD_FUEL, -(gGameExternalOptions.gASDResource_Fuel_Jeep + Random(gGameExternalOptions.gASDResource_Fuel_Jeep))); } break; @@ -4749,14 +4749,14 @@ void ApplyAdditionalASDEffects() { // priority: tank > jeep > robots if (GetStrategicAIResourceCount(ASD_TANK) > 0) - AddStrategicAIResources(ASD_TANK, 1 + Random(2)); + AddStrategicAIResources(ASD_TANK, -(1 + Random(2))); else if (GetStrategicAIResourceCount(ASD_JEEP) > 0) - AddStrategicAIResources(ASD_JEEP, 1 + Random(2)); + AddStrategicAIResources(ASD_JEEP, -(1 + Random(2))); else if (GetStrategicAIResourceCount(ASD_ROBOT) > 0) - AddStrategicAIResources(ASD_ROBOT, 2 + Random(3)); + AddStrategicAIResources(ASD_ROBOT, -(2 + Random(3))); // let's also try to destroy a good amount of fuel - AddStrategicAIResources(ASD_FUEL, gGameExternalOptions.gASDResource_Fuel_Tank + Random(gGameExternalOptions.gASDResource_Fuel_Tank)); + AddStrategicAIResources(ASD_FUEL, -(gGameExternalOptions.gASDResource_Fuel_Tank + Random(gGameExternalOptions.gASDResource_Fuel_Tank))); } break; }