From cb9c217bb178ea4b77688ddd1f610dca8a99bdd6 Mon Sep 17 00:00:00 2001 From: Flugente Date: Mon, 3 Dec 2012 00:50:48 +0000 Subject: [PATCH] - New Feature: The rosine system now allows to capture enemy soldeirs via using handcuffs on them. They can e transferred to a prison the player controls, and be interrogated there. - GameDir revision 1568 is required for this feature. - Savegame compatibility is maintained. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5709 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 12 + GameSettings.h | 15 +- GameVersion.h | 3 +- Init.h | 1 + Laptop/finances.cpp | 5 + Laptop/finances.h | 1 + Strategic/Assignments.cpp | 477 ++++++++++++++++++++++++- Strategic/Assignments.h | 4 + Strategic/Campaign Types.h | 14 +- Strategic/Facilities.cpp | 10 + Strategic/Facilities.h | 3 +- Strategic/Map Screen Interface Map.cpp | 18 + Strategic/XML_FacilityTypes.cpp | 19 +- Tactical/Faces.cpp | 8 + Tactical/Handle Items.cpp | 83 ++++- Tactical/Handle UI.cpp | 33 ++ Tactical/Handle UI.h | 1 + Tactical/Interface Cursors.cpp | 3 + Tactical/Interface Cursors.h | 3 + Tactical/Interface.cpp | 4 + Tactical/Item Types.h | 9 +- Tactical/Morale.cpp | 2 +- Tactical/Overhead.cpp | 248 ++++++++++++- Tactical/Points.cpp | 11 +- Tactical/Points.h | 1 + Tactical/Soldier Control.cpp | 142 ++++++++ Tactical/Soldier Control.h | 11 +- Tactical/UI Cursors.cpp | 29 ++ Tactical/opplist.cpp | 7 +- TacticalAI/AIMain.cpp | 7 +- TacticalAI/AIUtils.cpp | 45 +++ TacticalAI/DecideAction.cpp | 59 +-- TacticalAI/Realtime.cpp | 6 +- TacticalAI/ai.h | 3 + Utils/Cursors.cpp | 19 + Utils/Cursors.h | 5 + Utils/Text.h | 15 + Utils/_ChineseText.cpp | 25 +- Utils/_DutchText.cpp | 19 + Utils/_EnglishText.cpp | 25 +- Utils/_FrenchText.cpp | 19 + Utils/_GermanText.cpp | 21 +- Utils/_ItalianText.cpp | 23 +- Utils/_PolishText.cpp | 19 + Utils/_RussianText.cpp | 19 + Utils/_TaiwaneseText.cpp | 23 +- 46 files changed, 1472 insertions(+), 57 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 9a51deb1..417c9e62 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1551,6 +1551,17 @@ void LoadGameExternalOptions() gGameExternalOptions.fOnlyRepairGunsArmour = iniReader.ReadBoolean("Strategic Gameplay Settings","ONLY_REPAIR_GUNS_AND_ARMOUR", FALSE); gGameExternalOptions.fDirtSystem = iniReader.ReadBoolean("Strategic Gameplay Settings","DIRT_SYSTEM", FALSE); gGameExternalOptions.usSectorDirtDivider = iniReader.ReadInteger("Strategic Gameplay Settings","SECTOR_DIRT_DIVIDER", 1000, 1, 100000); + + // Flugente: prisoner system + gGameExternalOptions.fAllowPrisonerSystem = iniReader.ReadBoolean("Strategic Gameplay Settings","ALLOW_TAKE_PRISONERS", TRUE); + gGameExternalOptions.fEnemyCanSurrender = iniReader.ReadBoolean("Strategic Gameplay Settings","ENEMY_CAN_SURRENDER", TRUE); + gGameExternalOptions.ubPrisonerReturntoQueenChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_RETURN_TO_ARMY_CHANCE", 50, 0, 100); + gGameExternalOptions.ubPrisonerProcessDefectChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_DEFECT_CHANCE", 10, 0, 100); + gGameExternalOptions.ubPrisonerProcessInfoBaseChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INFO_BASECHANCE", 10, 0, 100); + gGameExternalOptions.ubPrisonerProcessInfoDetectChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INFO_DETECT_CHANCE", 5, 0, 100); + gGameExternalOptions.ubPrisonerProcessInfoNumberChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INFO_NUMBER_CHANCE", 30, 0, 100); + gGameExternalOptions.ubPrisonerProcessInfoDirectionChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INFO_DIRECTION_CHANCE", 40, 0, 100); + gGameExternalOptions.ubPrisonerProcessRansomBaseChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_RANSOM_CHANCE", 10, 0, 100); // CHRISL: Determine how Skyrider should handle landing in enemy occupied sectors gGameExternalOptions.ubSkyriderHotLZ = iniReader.ReadInteger("Strategic Gameplay Settings", "ALLOW_SKYRIDER_HOT_LZ", 0); @@ -2452,6 +2463,7 @@ void LoadGameAPBPConstants() APBPConstants[AP_CLEANINGKIT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_CLEANINGKIT",80),80); APBPConstants[AP_INVENTORY_EXPLOSIVE_ACTIVATE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INVENTORY_EXPLOSIVE_ACTIVATE",20),20); APBPConstants[AP_DISGUISE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_DISGUISE",80),80); + APBPConstants[AP_HANDCUFF] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_HANDCUFF",50),50); SetupMaxActionPointsAnimation(); #undef ReadInteger diff --git a/GameSettings.h b/GameSettings.h index 1c698b35..eb7004c0 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1130,8 +1130,8 @@ typedef struct // Flugente: Weapon Overheating BOOLEAN fDisplayOverheatThermometer; // Should a 'thermometer' for guns and replacable barrels be displayed? UINT8 ubOverheatThermometerRedOffset; // amount of red colour while temperature is below threshold - FLOAT iCooldownModificatorLonelyBarrel; // Cooldown modificator for barrels alone in the landscape ;-) - FLOAT iOverheatTemperatureGlobalModfier; // a global modifier to the singel shot temperatuer value, if one feels that all values hould be lower/higher + FLOAT iCooldownModificatorLonelyBarrel; // Cooldown modificator for barrels left alone in the landscape ;-) + FLOAT iOverheatTemperatureGlobalModfier; // a global modifier to the singel shot temperature value, if one feels that all values should be lower/higher // Flugente: Weapon Mounting BOOLEAN fWeaponResting; // Should it be possible to rest your weapon on structures in crouched position? @@ -1150,6 +1150,17 @@ typedef struct BOOLEAN fOnlyRepairGunsArmour; // we can only repair guns and armour BOOLEAN fDirtSystem; // allow dirt on items increase the chance for weapon jamming UINT32 usSectorDirtDivider; // divide a guns dirt factor by this to get dirt increase for every turn + + // Flugente: prisoner related settings + BOOLEAN fAllowPrisonerSystem; + BOOLEAN fEnemyCanSurrender; + UINT8 ubPrisonerReturntoQueenChance; + UINT8 ubPrisonerProcessDefectChance; + UINT8 ubPrisonerProcessInfoBaseChance; + UINT8 ubPrisonerProcessInfoDetectChance; + UINT8 ubPrisonerProcessInfoNumberChance; + UINT8 ubPrisonerProcessInfoDirectionChance; + UINT8 ubPrisonerProcessRansomBaseChance; // Sandro: Alternative weapon holding (rifles fired from hip / pistols fired one-handed) UINT8 ubAllowAlternativeWeaponHolding; diff --git a/GameVersion.h b/GameVersion.h index c01e04a0..f5d28279 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -20,8 +20,9 @@ extern CHAR16 zTrackingNumber[16]; // // Keeps track of the saved game version. Increment the saved game version whenever // you will invalidate the saved game file -#define SAVE_GAME_VERSION 135 // 134 // 133 // 132 //131 //125 //124 //114 //113 //112 //111 //110 //109 //108 //107 //106 //105 //104 //103 //102 //101 //100 // 99 +#define SAVE_GAME_VERSION 136 // 134 // 133 // 132 //131 //125 //124 //114 //113 //112 //111 //110 //109 //108 //107 //106 //105 //104 //103 //102 //101 //100 // 99 +#define PRISON_SYSTEM 136 // Flugente: added var to the sector structure. Shouldn't break compatibility, but let's be safe #define DUAL_BURST_ADDED 135 #define MORE_ROOMS 134 // changed room numbers from 8 to 16 bit by DBrot #define FOOD_CHANGES 133 // changes for food system diff --git a/Init.h b/Init.h index dafbff07..92cdc58e 100644 --- a/Init.h +++ b/Init.h @@ -202,6 +202,7 @@ AP_EAT, AP_CLEANINGKIT, AP_INVENTORY_EXPLOSIVE_ACTIVATE, AP_DISGUISE, +AP_HANDCUFF, TOTAL_APBP_VALUES }; #endif diff --git a/Laptop/finances.cpp b/Laptop/finances.cpp index 1d3646cb..240b2254 100644 --- a/Laptop/finances.cpp +++ b/Laptop/finances.cpp @@ -1571,6 +1571,11 @@ void ProcessTransactionString(STR16 pString, FinanceUnitPtr pFinance) swprintf(pString, L"%s", pTransactionText[ MILITIA_UPKEEP ]); break; + // Flugente: ransom from released prisoners + case PRISONER_RANSOM: + swprintf(pString, L"%s", pTransactionText[ PRISONER_RANSOM ]); + break; + } diff --git a/Laptop/finances.h b/Laptop/finances.h index 3da88793..31500f90 100644 --- a/Laptop/finances.h +++ b/Laptop/finances.h @@ -53,6 +53,7 @@ enum SOLD_ITEMS, FACILITY_OPERATIONS, // HEADROCK HAM 3.6: Facility costs (daily payment) MILITIA_UPKEEP, // HEADROCK HAM 3.6: Militia Upkeep Costs (daily payment) + PRISONER_RANSOM, // Flugente: ransom for released prisoners TEXT_NUM_FINCANCES }; diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index bea0a4fc..1aac652e 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -398,6 +398,12 @@ void TrainSoldierWithPts( SOLDIERTYPE *pSoldier, INT16 sTrainPts ); // train militia in this sector with this soldier BOOLEAN TrainTownInSector( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMapY, INT16 sTrainingPts ); +// Flugente:: handle processing of prisoners +void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ); + +// Flugente: prisons can riot if there aren't enough guards around +void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ ); + // is the character between secotrs in mvt BOOLEAN CharacterIsBetweenSectors( SOLDIERTYPE *pSoldier ); @@ -2220,7 +2226,9 @@ void UpdateAssignments() for( bZ = 0; bZ < 4; bZ++) { // handle militia squads movings and creating (not an assignment) - if(!bZ && sX < 17 && sY < 17 && sX > 0 && sY > 0)UpdateMilitiaSquads( sX, sY ); + if(!bZ && sX < 17 && sY < 17 && sX > 0 && sY > 0) + UpdateMilitiaSquads( sX, sY ); + // is there anyone in this sector? if( fSectorsWithSoldiers[ sX + sY * MAP_WORLD_X ][ bZ ] == TRUE ) { @@ -2232,7 +2240,14 @@ void UpdateAssignments() // handle any training HandleTrainingInSector( sX, sY, bZ ); + + // handle processing of prisoners + HandlePrisonerProcessingInSector( sX, sY, bZ ); } + + // Flugente: prisons can riot if there aren't enough guards around + if ( !bZ ) + HandlePrison( sX, sY, bZ ); } } } @@ -2596,6 +2611,84 @@ UINT8 CalculateRepairPointsForRepairman(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts return(( UINT8 )usRepairPts); } +extern INT32 CalcThreateningEffectiveness( UINT8 ubMerc ); + +// Flugente: calculate interrogation value +FLOAT CalculateInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) +{ + UINT32 usInterrogationPoints = 0; + + // for max points we display the maximum amount of prisoners instead + *pusMaxPts = 0; + if ( !pSoldier || !pSoldier->bSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] ); + + *pusMaxPts = (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar); + } + + // no prisoners -> no interrogation (this should not happen) + if ( !*pusMaxPts ) + return .0f; + + usInterrogationPoints = 50 + 10 * EffectiveExpLevel( pSoldier ) + EffectiveLeadership( pSoldier ); + + // adjust for threatening value + INT32 threatenvalue = CalcThreateningEffectiveness( pSoldier->ubProfile ) * gMercProfiles[pSoldier->ubProfile].usApproachFactor[2] ; + + usInterrogationPoints *= threatenvalue; + usInterrogationPoints /= 6500; + + // TODO: adjust for cop background + + // adjust for fatigue + ReducePointsForFatigue( pSoldier, &usInterrogationPoints ); + + // return current repair pts + return( usInterrogationPoints ); +} + +// Flugente: calculate prison guard value +FLOAT CalculatePrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) +{ + // this is not an assignment. Simply being in the sector will allow us to be counted as guards + UINT32 usValue = 0; + + // for max points we display the maximum amount of prisoners instead + *pusMaxPts = 0; + /*if ( !pSoldier || !pSoldier->bSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] ); + + *pusMaxPts = (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar); + } + + // no prisoners -> no interrogation (this should not happen) + if ( !*pusMaxPts ) + return .0f;*/ + + if ( pSoldier->flags.fMercAsleep ) + return 0; + + usValue = 15 * EffectiveExpLevel( pSoldier ) + EffectiveLeadership( pSoldier ) / 2 + 2 * EffectiveStrength( pSoldier, FALSE); + + if (gGameOptions.fNewTraitSystem) + { + usValue += 25 * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT ) + 10 * HAS_SKILL_TRAIT( pSoldier, MELEE_NT ); + } + else + { + usValue += 25 * NUM_SKILL_TRAITS( pSoldier, MARTIALARTS_OT ) + 25 * NUM_SKILL_TRAITS( pSoldier, HANDTOHAND_OT ) + 10 * HAS_SKILL_TRAIT( pSoldier, KNIFING_OT ); + } + + // adjust for fatigue + ReducePointsForFatigue( pSoldier, &usValue ); + + // TODO: adjust for prison guard background + + // return current repair pts + return( usValue ); +} UINT16 ToolKitPoints(SOLDIERTYPE *pSoldier) { @@ -5379,6 +5472,345 @@ BOOLEAN TrainTownInSector( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMapY, INT1 } +extern INT32 giReinforcementPool; + +// handle processing of prisoners +void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) +{ + // Is there a prison in this sector? + UINT16 prisonerbaselimit = 0; + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) + { + // Is this facility here? + if (gFacilityLocations[SECTOR(sMapX, sMapY)][cnt].fFacilityHere) + { + // we determine wether this is a prison by checking for usPrisonBaseLimit + if (gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > 0) + { + prisonerbaselimit = gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit; + break; + } + } + } + + if ( !prisonerbaselimit ) + return; + + // Are there any prisoners in this prison? + UINT32 numprisoners = 0; + if ( !bZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + numprisoners = pSectorInfo->uiNumberOfPrisonersOfWar; + } + else + { + UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + + numprisoners = pSectorInfo->uiNumberOfPrisonersOfWar; + } + + if ( !numprisoners ) + return; + + // if sector not under our control, has enemies in it, or is currently in combat mode + if (!SectorOursAndPeaceful( sMapX, sMapY, bZ )) + return; + + // loop over all mercs in this sector that are on the FACILITY_INTERROGATE_PRISONERS assignment and determine their interrogation progress + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt=0; + UINT8 numinterrogators = 0; + FLOAT interrogationpoints = .0f; + + // count any interrogators found here, and sum up their interrogation values + for ( uiCnt = 0, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++uiCnt, ++pSoldier) + { + if( pSoldier->bActive && ( pSoldier->sSectorX == sMapX ) && ( pSoldier->sSectorY == sMapY ) && ( pSoldier->bSectorZ == bZ) ) + { + // if he's training teammates in this stat + if( ( pSoldier->bAssignment == FACILITY_INTERROGATE_PRISONERS ) && ( EnoughTimeOnAssignment( pSoldier ) ) && ( pSoldier->flags.fMercAsleep == FALSE ) ) + { + ++numinterrogators; + + UINT16 tmp; + interrogationpoints += CalculateInterrogationValue(pSoldier, &tmp ); + } + } + } + + if ( !numinterrogators ) + return; + + // for every x points, we can interrogate 1 prisoner + // TODO: for now, we lose the remaining points + UINT32 prisonersinterrogated = interrogationpoints / 100; + + if ( prisonersinterrogated > numprisoners ) + prisonersinterrogated = numprisoners; + + if ( !prisonersinterrogated ) + return; + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_PROCESSED], prisonersinterrogated ); + + UINT32 turnedmilitia = 0; + UINT32 revealedpositions = 0; + UINT32 ransomscollected = 0; + UINT32 ransommoney = 0; + for ( UINT32 i = 0; i < prisonersinterrogated; ++i ) + { + // we determine what happens to the prisoners + UINT8 result = Random( 100 ); + + // chance that prisoner will work on our side as militia + if ( result < gGameExternalOptions.ubPrisonerProcessDefectChance ) + { + ++turnedmilitia; + + // we continue so that this guy can not also run back to the queen + continue; + } + // chance that prisoner will give us random info about enemy positions + else if ( result < gGameExternalOptions.ubPrisonerProcessDefectChance + gGameExternalOptions.ubPrisonerProcessInfoBaseChance ) + { + BOOLEAN found = FALSE; + // run through sectors and handle each type in sector + for(INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) + { + if ( found ) + break; + + for(INT16 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) + { + UINT32 result = Random(100); + if ( result < gGameExternalOptions.ubPrisonerProcessInfoDetectChance ) + { + // there need to be enemies here... + if ( NumStationaryEnemiesInSector( sX, sY ) == 0 ) + continue; + + // enemy patrol detected + SectorInfo[ SECTOR( sX, sY ) ].uiFlags |= SF_ASSIGN_NOTICED_ENEMIES_HERE; + + if ( result < gGameExternalOptions.ubPrisonerProcessInfoNumberChance ) + { + // we also learned the number of enemies + SectorInfo[ SECTOR( sX, sY ) ].uiFlags |= SF_ASSIGN_NOTICED_ENEMIES_KNOW_NUMBER; + } + + if ( result < gGameExternalOptions.ubPrisonerProcessInfoDirectionChance ) + { + // we also learned the direction of the patrol + SectorInfo[ SECTOR( sX, sY ) ].uiFlags |= SF_ASSIGN_NOTICED_ENEMIES_KNOW_DIRECTION; + } + + ++revealedpositions; + found = TRUE; + break; + } + } + } + } + // chance prisoner will grant us ransom money + else if ( result < gGameExternalOptions.ubPrisonerProcessDefectChance + gGameExternalOptions.ubPrisonerProcessInfoBaseChance + gGameExternalOptions.ubPrisonerProcessRansomBaseChance ) + { + ransommoney += (Random(5) + 1) * 100; + + ++ransomscollected; + } + // we have to let him go without any benefits + else + { + + } + + // there is a chance that escaped prisoners may return to the queen... + if ( Random( 100 ) < gGameExternalOptions.ubPrisonerReturntoQueenChance ) + ++giReinforcementPool; + } + + if ( turnedmilitia ) + { + // add these guys to the local garrison as green militias + StrategicAddMilitiaToSector(sMapX, sMapY, GREEN_MILITIA, turnedmilitia); + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_TURN_MILITIA], turnedmilitia ); + } + + if ( revealedpositions ) + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_DETECTION], revealedpositions ); + + if ( ransomscollected ) + { + AddTransactionToPlayersBook( PRISONER_RANSOM, 0, GetWorldTotalMin(), ransommoney ); + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RANSOM], ransomscollected ); + } + + // give experience rewards to the interrogators + // total experience to share + FLOAT totalexp = 100 * prisonersinterrogated; + FLOAT expratio = totalexp / (interrogationpoints * 33); // TODO + + // award experience + for ( uiCnt = 0, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++uiCnt, ++pSoldier) + { + if( pSoldier->bActive && ( pSoldier->sSectorX == sMapX ) && ( pSoldier->sSectorY == sMapY ) && ( pSoldier->bSectorZ == bZ) ) + { + // if he's training teammates in this stat + if( ( pSoldier->bAssignment == FACILITY_INTERROGATE_PRISONERS ) && ( EnoughTimeOnAssignment( pSoldier ) ) && ( pSoldier->flags.fMercAsleep == FALSE ) ) + { + UINT16 tmp; + UINT16 exppoints = (UINT16)(expratio * CalculateInterrogationValue(pSoldier, &tmp ) ); + + StatChange( pSoldier, LDRAMT, exppoints, TRUE ); + StatChange( pSoldier, WISDOMAMT, max(0, exppoints - 1), TRUE ); + StatChange( pSoldier, EXPERAMT, max(0, exppoints - 2), TRUE ); + } + } + } + + // remove interrogated prisoners... + if ( !bZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + // safety first... + if ( prisonersinterrogated > pSectorInfo->uiNumberOfPrisonersOfWar ) + pSectorInfo->uiNumberOfPrisonersOfWar = 0; + else + pSectorInfo->uiNumberOfPrisonersOfWar -= prisonersinterrogated; + } + else + { + UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + + // safety first... + if ( prisonersinterrogated > pSectorInfo->uiNumberOfPrisonersOfWar ) + pSectorInfo->uiNumberOfPrisonersOfWar = 0; + else + pSectorInfo->uiNumberOfPrisonersOfWar -= prisonersinterrogated; + } +} + +// Flugente: prisons can riot if there aren't enough guards around +void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) +{ + BOOLEAN fBeginRiot = FALSE; + + // Is there a prison in this sector? + UINT16 prisonerbaselimit = 0; + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) + { + // Is this facility here? + if (gFacilityLocations[SECTOR(sMapX, sMapY)][cnt].fFacilityHere) + { + // we determine wether this is a prison by checking for usPrisonBaseLimit + if (gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > 0) + { + prisonerbaselimit = gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit; + break; + } + } + } + + if ( !prisonerbaselimit ) + return; + + // Are there any prisoners in this prison? + UINT32 numprisoners = 0; + if ( !bZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + numprisoners = pSectorInfo->uiNumberOfPrisonersOfWar; + } + else + { + UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + + numprisoners = pSectorInfo->uiNumberOfPrisonersOfWar; + } + + if ( !numprisoners ) + return; + + // if sector is not under our control, the prisoners are added to the local garrison + if( !bZ && StrategicMap[ sMapX + sMapY * MAP_WORLD_X ].fEnemyControlled == TRUE ) + { + // add enemies + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + pSectorInfo->ubNumTroops += numprisoners; + + } + + // if sector not under our control, has enemies in it, or is currently in combat mode + if (!SectorOursAndPeaceful( sMapX, sMapY, bZ )) + return; + + // loop over all mercs in this sector that are on the FACILITY_INTERROGATE_PRISONERS assignment and determine their interrogation progress + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt = 0; + UINT8 numprisonguards = 0; + FLOAT prisonguardvalue = .0f; + + // count any interrogators found here, and sum up their interrogation values + UINT32 firstid = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; + UINT32 lastid = gTacticalStatus.Team[ OUR_TEAM ].bLastID; + for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) + { + if( pSoldier->bActive && ( pSoldier->sSectorX == sMapX ) && ( pSoldier->sSectorY == sMapY ) && ( pSoldier->bSectorZ == bZ) && pSoldier->flags.fMercAsleep == FALSE ) + { + ++numprisonguards; + + UINT16 tmp; + prisonguardvalue += CalculatePrisonGuardValue(pSoldier, &tmp ); + } + } + // add militia strength + if ( !bZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + prisonguardvalue += 100 * pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + 150 * pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + 200 * pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + } + else + { + // there are no underground prisons, so screw this... + } + + if ( !numprisonguards ) + fBeginRiot = TRUE; + + // we now have to determine the combined strength of the prisoners + FLOAT prisonerriotvalue = .0f; + for ( UINT32 i = 0; i < numprisoners; ++i ) + { + prisonerriotvalue += 100.0f; + } + + if ( prisonerriotvalue > prisonguardvalue ) + { + if ( numprisoners > prisonerbaselimit && Random( (UINT32)(prisonerriotvalue) ) > Random( (UINT32)(prisonguardvalue) ) ) + fBeginRiot = TRUE; + } + + if ( fBeginRiot ) + { + // add enemies + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + pSectorInfo->ubNumTroops += numprisoners; + + CHAR16 zShortTownIDString[ 50 ]; + GetShortSectorString( sMapX, sMapX, zShortTownIDString ); + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RIOT], zShortTownIDString ); + } +} INT16 GetTownTrainPtsForCharacter( SOLDIERTYPE *pTrainer, UINT16 *pusMaxPts ) { @@ -11540,6 +11972,31 @@ void SetSoldierAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment, INT32 iParam pSoldier->bVehicleUnderRepairID = ( INT8 )iParam3; } break; + + case( FACILITY_INTERROGATE_PRISONERS ): + if( pSoldier->CanProcessPrisoners() ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + + // remove from squad + RemoveCharacterFromSquads( pSoldier ); + + // remove from any vehicle + if( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + if ( pSoldier->bAssignment != FACILITY_INTERROGATE_PRISONERS ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, FACILITY_INTERROGATE_PRISONERS ); + AssignMercToAMovementGroup( pSoldier ); + } + break; + case( VEHICLE ): if( CanCharacterVehicle( pSoldier ) && IsThisVehicleAccessibleToSoldier( pSoldier, iParam1 ) ) { @@ -12610,6 +13067,10 @@ void ReEvaluateEveryonesNothingToDo() fNothingToDo = !CanCharacterRepair( pSoldier ) || HasCharacterFinishedRepairing( pSoldier ); break; + case FACILITY_INTERROGATE_PRISONERS: + fNothingToDo = !pSoldier->CanProcessPrisoners(); + break; + case TRAIN_TOWN: fNothingToDo = !CanCharacterTrainMilitia( pSoldier ); break; @@ -12834,6 +13295,16 @@ void SetAssignmentForList( INT8 bAssignment, INT8 bParam ) } break; + case FACILITY_INTERROGATE_PRISONERS: + if ( CanCharacterFacility( pSoldier, bParam, FAC_INTERROGATE_PRISONERS ) && pSoldier->CanProcessPrisoners() ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + ChangeSoldiersAssignment( pSoldier, FACILITY_INTERROGATE_PRISONERS ); + pSoldier->sFacilityTypeOperated = bParam; + fItWorked = TRUE; + } + break; + case( SQUAD_1 ): case( SQUAD_2 ): case( SQUAD_3 ): @@ -16324,7 +16795,9 @@ void FacilityAssignmentMenuBtnCallback ( MOUSE_REGION * pRegion, INT32 iReason ) pSoldier->bTrainStat = EXPLOSIVE_ASSIGN; ChangeSoldiersAssignment( pSoldier, TRAIN_TEAMMATE ); break; - + case FAC_INTERROGATE_PRISONERS: + ChangeSoldiersAssignment( pSoldier, FACILITY_INTERROGATE_PRISONERS ); + break; } // Flugente: I guess this piece of code is here to get a group Id for the soldier, which must not be there for movement specifically. Just my understanding, in case anybody else coming here wonders diff --git a/Strategic/Assignments.h b/Strategic/Assignments.h index 9f18a5b2..1a44fb98 100644 --- a/Strategic/Assignments.h +++ b/Strategic/Assignments.h @@ -64,6 +64,7 @@ enum FACILITY_STAFF, // HEADROCK HAM 3.6: Operating a facility for strategic gain. FACILITY_EAT, // added by Flugente FACILITY_REST, // HEADROCK HAM 3.6: Facility equivalent of resting (no assignment) + FACILITY_INTERROGATE_PRISONERS, // added by Flugente ASSIGNMENT_DEAD, ASSIGNMENT_UNCONCIOUS, // unused ASSIGNMENT_POW, @@ -189,6 +190,9 @@ UINT16 CalculateHealingPointsForDoctor(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts, // find number of repair pts repairman has available UINT8 CalculateRepairPointsForRepairman(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts, BOOLEAN fMakeSureKitIsInHand ); +// Flugente: calculate interrogation and prison guard values +FLOAT CalculateInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ); +FLOAT CalculatePrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ); // get bonus tarining pts due to an instructor for this student // HEADROCK HAM 3.5: Three functions below have lost an argument which is no longer required ("uiAtGunRange", which was "uiAtFacility" in HAM 3.4) diff --git a/Strategic/Campaign Types.h b/Strategic/Campaign Types.h index aff71b8b..cbb94d31 100644 --- a/Strategic/Campaign Types.h +++ b/Strategic/Campaign Types.h @@ -95,6 +95,10 @@ enum //strategic values for each sector #define SF_HAVE_SAID_PLAYER_QUOTE_NEW_SECTOR 0x00001000 #endif +#define SF_ASSIGN_NOTICED_ENEMIES_HERE 0x00002000 // Flugente: info from assigment: enemies were found +#define SF_ASSIGN_NOTICED_ENEMIES_KNOW_NUMBER 0x00004000 // Flugente: info from assigment: enemies were found, and we know their number +#define SF_ASSIGN_NOTICED_ENEMIES_KNOW_DIRECTION 0x00008000 // Flugente: info from assigment: enemies were found, and we know the direction they are moving in + #define SF_SMOKE_EFFECTS_TEMP_FILE_EXISTS 0x00100000 //Temp File starts with sm_ #define SF_LIGHTING_EFFECTS_TEMP_FILE_EXISTS 0x00200000 //Temp File starts with l_ #define SF_REVEALED_STATUS_TEMP_FILE_EXISTS 0x01000000 //Temp File starts with v_ @@ -182,6 +186,7 @@ enum FAC_TRAINER_MECHANICAL, FAC_TRAINER_LEADERSHIP, FAC_TRAINER_EXPLOSIVES, + FAC_INTERROGATE_PRISONERS, NUM_FACILITY_ASSIGNMENTS, }; @@ -249,6 +254,7 @@ typedef struct FACILITYASSIGNMENTTYPE UINT16 usMineIncomeModifier; // Percentage income adjustment BOOLEAN fOnlyLocalMineAffected; // Determines whether income modifier applies to local mine only, or all mines. INT16 sCantinaFoodModifier; // how many food points do we get when spending time in a cantina? + UINT16 usPrisonBaseLimit; // for how many prisoners was this prison built? UINT8 ubMinimumStrength; // Minimum STR Requirement to begin this assignment UINT8 ubMinimumHealth; // Minimum HLT Requirement to begin this assignment @@ -473,7 +479,9 @@ typedef struct SECTORINFO BOOLEAN fCampaignSector; #endif - INT8 bPadding[ 41 ]; + UINT32 uiNumberOfPrisonersOfWar; + + INT8 bPadding[ 37 ]; }SECTORINFO; @@ -510,7 +518,9 @@ typedef struct UNDERGROUND_SECTORINFO BOOLEAN fCampaignSector; #endif - INT8 bPadding[36]; + UINT32 uiNumberOfPrisonersOfWar; + + INT8 bPadding[32]; //no padding left! }UNDERGROUND_SECTORINFO; diff --git a/Strategic/Facilities.cpp b/Strategic/Facilities.cpp index 67b2d594..facacd38 100644 --- a/Strategic/Facilities.cpp +++ b/Strategic/Facilities.cpp @@ -141,12 +141,19 @@ INT16 GetFacilityModifier( UINT8 ubModifierType, UINT8 ubFacilityType, UINT8 ubA sAssignmentModifier = 100 + ((sAssignmentModifier-100) + (sAmbientModifier-100)); return (sAssignmentModifier); + // Flugente: not needed anywhere atm case FACILITY_CANTINA_MOD: sAssignmentModifier = gFacilityTypes[ubFacilityType].AssignmentData[ubAssignmentType].sCantinaFoodModifier; sAmbientModifier = gFacilityTypes[ubFacilityType].AssignmentData[0].sCantinaFoodModifier; sAssignmentModifier = 100 + ((sAssignmentModifier-100) + (sAmbientModifier-100)); return (sAssignmentModifier); + case FACILITY_PRISON_MOD: + sAssignmentModifier = gFacilityTypes[ubFacilityType].AssignmentData[ubAssignmentType].usPrisonBaseLimit; + sAmbientModifier = gFacilityTypes[ubFacilityType].AssignmentData[0].usPrisonBaseLimit; + sAssignmentModifier = 100 + ((sAssignmentModifier-100) + (sAmbientModifier-100)); + return (sAssignmentModifier); + default: return (0); } @@ -906,6 +913,9 @@ INT8 GetSoldierFacilityAssignmentIndex( SOLDIERTYPE *pSoldier ) case FACILITY_REST: bAssignmentIndex = FAC_REST; break; + case FACILITY_INTERROGATE_PRISONERS: + bAssignmentIndex = FAC_INTERROGATE_PRISONERS; + break; default: bAssignmentIndex = -1; break; diff --git a/Strategic/Facilities.h b/Strategic/Facilities.h index c67d6133..24b85a63 100644 --- a/Strategic/Facilities.h +++ b/Strategic/Facilities.h @@ -47,7 +47,8 @@ enum FACILITY_MINE_INCOME_MOD, FACILITY_SKYRIDER_COST_MOD, - FACILITY_CANTINA_MOD + FACILITY_CANTINA_MOD, + FACILITY_PRISON_MOD }; // HEADROCK HAM 3.6: Different enemy detection and counting levels diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index fc486278..5dd5c63c 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -6930,6 +6930,24 @@ UINT32 WhatPlayerKnowsAboutEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) } } + // Flugente: we know that enemies are here + if ( uiSectorFlags & SF_ASSIGN_NOTICED_ENEMIES_HERE ) + { + fDetection = TRUE; + + // we know how many there are + if ( uiSectorFlags & SF_ASSIGN_NOTICED_ENEMIES_KNOW_NUMBER ) + { + fCount = TRUE; + } + + // we know the direction they are moving in + if ( uiSectorFlags & SF_ASSIGN_NOTICED_ENEMIES_KNOW_DIRECTION ) + { + fDirection = TRUE; + } + } + // Facilities can set a flag that allows detection in some sectors. We can read flags directly from the sector // data to know whether we should show the enemies there. This overrides ANYTHING else. if (SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubDetectionLevel & 1) diff --git a/Strategic/XML_FacilityTypes.cpp b/Strategic/XML_FacilityTypes.cpp index a1bd4d3f..e979a646 100644 --- a/Strategic/XML_FacilityTypes.cpp +++ b/Strategic/XML_FacilityTypes.cpp @@ -99,6 +99,7 @@ void InitAssignmentDataArray( facilitytypeParseData *pData ) pData->curAssignmentData.fOnlyLocalMineAffected = 0; pData->curAssignmentData.sCantinaFoodModifier = 100; + pData->curAssignmentData.usPrisonBaseLimit = 0; pData->curAssignmentData.ubMaximumBreath = 100; pData->curAssignmentData.ubMaximumMorale = 100; @@ -220,7 +221,8 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C strcmp(name, "sSkyriderCostModifier") == 0 || strcmp(name, "usMineIncomeModifier") == 0 || strcmp(name, "fOnlyLocalMineAffected") == 0 || - strcmp(name, "sCantinaFoodModifier") == 0 )) + strcmp(name, "sCantinaFoodModifier") == 0 || + strcmp(name, "usPrisonBaseLimit") == 0 )) { pData->curElement = FACILITYTYPE_ASSIGNMENT_ELEMENT; @@ -453,6 +455,7 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) gFacilityTypes[pData->curIndex].AssignmentData[cnt].fOnlyLocalMineAffected = pData->curFacilityTypeData.AssignmentData[cnt].fOnlyLocalMineAffected; gFacilityTypes[pData->curIndex].AssignmentData[cnt].sCantinaFoodModifier = pData->curFacilityTypeData.AssignmentData[cnt].sCantinaFoodModifier; + gFacilityTypes[pData->curIndex].AssignmentData[cnt].usPrisonBaseLimit = pData->curFacilityTypeData.AssignmentData[cnt].usPrisonBaseLimit; // Conditions gFacilityTypes[pData->curIndex].AssignmentData[cnt].ubMinimumStrength = pData->curFacilityTypeData.AssignmentData[cnt].ubMinimumStrength; @@ -593,6 +596,7 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].fOnlyLocalMineAffected = pData->curAssignmentData.fOnlyLocalMineAffected; pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].sCantinaFoodModifier = pData->curAssignmentData.sCantinaFoodModifier; + pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].usPrisonBaseLimit = pData->curAssignmentData.usPrisonBaseLimit; pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].ubMaximumBreath = pData->curAssignmentData.ubMaximumBreath; pData->curFacilityTypeData.AssignmentData[pData->curAssignmentType].ubMaximumMorale = pData->curAssignmentData.ubMaximumMorale; @@ -823,6 +827,11 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) { //pData->curAssignmentType = (INT16) atol(pData->szCharData); pData->curAssignmentType = FAC_STUDENT_EXPLOSIVES; + } + else if (strcmp(pData->szCharData, "INTERROGATE_PRISONERS") == 0) + { + //pData->curAssignmentType = (INT16) atol(pData->szCharData); + pData->curAssignmentType = FAC_INTERROGATE_PRISONERS; } else { @@ -945,7 +954,13 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) else if(strcmp(name, "sCantinaFoodModifier") == 0 ) { pData->curElement = FACILITYTYPE_ASSIGNMENT; - pData->curAssignmentData.sCantinaFoodModifier = (UINT16) atol(pData->szCharData); + pData->curAssignmentData.sCantinaFoodModifier = (INT16) atol(pData->szCharData); + } + + else if(strcmp(name, "usPrisonBaseLimit") == 0 ) + { + pData->curElement = FACILITYTYPE_ASSIGNMENT; + pData->curAssignmentData.usPrisonBaseLimit = (UINT16) atol(pData->szCharData); } ////////////////////////////////////////////// diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index f241fc4c..b671e956 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -2404,6 +2404,14 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE } break; + + case FACILITY_INTERROGATE_PRISONERS: + sIconIndex = 23; + fDoIcon = TRUE; + sPtsAvailable = (INT16)( CalculateInterrogationValue(pSoldier, &usMaximumPts ) ) / 100; + fShowNumber = TRUE; + fShowMaximum = TRUE; + break; } // Check for being serviced... diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index f6fd0ee9..97bc4974 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -1215,6 +1215,87 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa } } + // Flugente: handcuffing people + if ( HasItemFlag(usHandItem, HANDCUFFS ) ) + { + // ATE: AI CANNOT GO THROUGH HERE! + INT32 usMapPos; + BOOLEAN fHadToUseCursorPos = FALSE; + + GetMouseMapPos( &usMapPos ); + + // See if we can get there to stab + sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE ); + if ( sActionGridNo == -1 ) + { + // Try another location... + sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE ); + + if ( sActionGridNo == -1 ) + { + return( ITEM_HANDLE_CANNOT_GETTO_LOCATION ); + } + + /*if ( !gTacticalStatus.fAutoBandageMode ) + { + fHadToUseCursorPos = TRUE; + }*/ + } + + // Calculate AP costs... + sAPCost = GetAPsToHandcuff( pSoldier, sActionGridNo ); + sAPCost += PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints); + + if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) ) + { + // OK, set UI + SetUIBusy( pSoldier->ubID ); + + // CHECK IF WE ARE AT THIS GRIDNO NOW + if ( pSoldier->sGridNo != sActionGridNo ) + { + // SEND PENDING ACTION + pSoldier->aiData.ubPendingAction = MERC_HANDCUFF_PERSON; + + if ( fHadToUseCursorPos ) + { + pSoldier->aiData.sPendingActionData2 = usMapPos; + } + else + { + if ( pTargetSoldier != NULL ) + { + pSoldier->aiData.sPendingActionData2 = pTargetSoldier->sGridNo; + } + else + { + pSoldier->aiData.sPendingActionData2 = sGridNo; + } + } + pSoldier->aiData.bPendingActionData3 = ubDirection; + pSoldier->aiData.ubPendingActionAnimCount = 0; + + // WALK UP TO DEST FIRST + pSoldier->EVENT_InternalGetNewSoldierPath( sActionGridNo, pSoldier->usUIMovementMode, FALSE, TRUE ); + } + else + { + pSoldier->EVENT_SoldierHandcuffPerson( sAdjustedGridNo, ubDirection ); + } + + if ( fFromUI ) + { + guiPendingOverrideEvent = A_CHANGE_TO_MOVE; + } + + return( ITEM_HANDLE_OK ); + } + else + { + return( ITEM_HANDLE_NOAPS ); + } + } + if ( Item[usHandItem].canandstring ) { STRUCTURE *pStructure; @@ -4574,7 +4655,7 @@ void CleanWeapons( BOOLEAN fCleanAll ) if ( pSoldier->bActive ) pSoldier->CleanWeapon(fCleanAll); } - else // peform action for every merc in this sector + else // perform action for every merc in this sector { UINT8 bMercID, bLastTeamID; SOLDIERTYPE* pSoldier = NULL; diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index 79341219..e362e37a 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -4142,6 +4142,24 @@ INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags ) gsUIHandleShowMoveGridLocation = sActionGridNo; } } + else if ( uiFlags == MOVEUI_TARGET_HANDCUFF ) + { + sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE ); + if ( sActionGridNo == -1 ) + { + sActionGridNo = usMapPos; + } + + sAPCost = GetAPsToHandcuff( pSoldier, sActionGridNo ); + + sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints); + + if ( sActionGridNo != pSoldier->sGridNo ) + { + gfUIHandleShowMoveGrid = TRUE; + gsUIHandleShowMoveGridLocation = sActionGridNo; + } + } else if ( uiFlags == MOVEUI_TARGET_MERCS ) { INT32 sGotLocation = NOWHERE; @@ -4494,6 +4512,21 @@ BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier ) return( FALSE ); } + if ( ubItemCursor == HANDCUFFCURS ) + { + if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, HANDCUFFS ) ) + { + if ( gfUIFullTargetFound ) + { + usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo; + + return( TRUE ); + } + } + + return( FALSE ); + } + if ( ubItemCursor == BOMBCURS ) { if ( usMapPos == pSoldier->sGridNo ) diff --git a/Tactical/Handle UI.h b/Tactical/Handle UI.h index 3580f928..fd9a04bb 100644 --- a/Tactical/Handle UI.h +++ b/Tactical/Handle UI.h @@ -30,6 +30,7 @@ #define MOVEUI_TARGET_CAN 11 #define MOVEUI_TARGET_REFUEL 12 #define MOVEUI_TARGET_FORTIFICATION 13 +#define MOVEUI_TARGET_HANDCUFF 14 #define MOVEUI_RETURN_ON_TARGET_MERC 1 diff --git a/Tactical/Interface Cursors.cpp b/Tactical/Interface Cursors.cpp index e1c92a75..6acce30e 100644 --- a/Tactical/Interface Cursors.cpp +++ b/Tactical/Interface Cursors.cpp @@ -215,6 +215,9 @@ UICursor gUICursors[ NUM_UI_CURSORS ] = FORTIFICATION_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FORTIFICATION, 0, FORTIFICATION_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FORTIFICATION_RED, 0, + HANDCUFF_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HANDCUFF, 0, + HANDCUFF_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HANDCUFF_RED, 0, + }; diff --git a/Tactical/Interface Cursors.h b/Tactical/Interface Cursors.h index f1524361..bf2e56f1 100644 --- a/Tactical/Interface Cursors.h +++ b/Tactical/Interface Cursors.h @@ -189,6 +189,9 @@ typedef enum FORTIFICATION_GREY_UICURSOR, FORTIFICATION_RED_UICURSOR, + HANDCUFF_GREY_UICURSOR, + HANDCUFF_RED_UICURSOR, + NUM_UI_CURSORS } UICursorDefines; diff --git a/Tactical/Interface.cpp b/Tactical/Interface.cpp index 134f8fba..bcb2fb1b 100644 --- a/Tactical/Interface.cpp +++ b/Tactical/Interface.cpp @@ -5043,6 +5043,10 @@ STR16 GetSoldierHealthString( SOLDIERTYPE *pSoldier ) } else { + // Flugente: display if we are a prisoner of war + if ( pSoldier->bSoldierFlagMask & SOLDIER_POW ) + return zHealthStr[ 7 ]; + INT32 cnt, cntStart; if( pSoldier->stats.bLife == pSoldier->stats.bLifeMax ) { diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index e4e2d75f..a0e0a834 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -174,6 +174,7 @@ typedef enum ATTACHMENT_SLOT{ #define TINCANCURS 22 #define REFUELCURS 23 #define FORTICURS 24 +#define HANDCUFFCURS 25 #define CAMERARANGE 10 @@ -728,7 +729,7 @@ extern OBJECTTYPE gTempObject; // note that these should not be used to determine what kind of an attachment an item is, that is determined by attachmentclass and the AC_xxx flags above #define EMPTY_SANDBAG 0x00000001 //1 #define FULL_SANDBAG 0x00000002 //2 -#define SHOVEL 0x00000004 //4 +#define SHOVEL 0x00000004 //4 // a shovel is used for filling sandbags and other building-related tasks #define CONCERTINA 0x00000008 //8 #define WATER_DRUM 0x00000010 //16 // water drums allow to refill canteens in the sector they are in @@ -743,15 +744,15 @@ extern OBJECTTYPE gTempObject; #define ATTENTION_ITEM 0x00001000 //4096 // this item is 'interesting' to the AI. Dumb soldiers may try to pick it up #define GAROTTE 0x00002000 //8192 // this item is a garotte -#define COVERT 0x00004000 //16384 // if LBE, any gun inside will be covert. On a gun, it will covert in any LBE, even if the LBE does not have that tag itself +#define COVERT 0x00004000 //16384 // if LBE, any gun inside will be covert. On a gun, it will be covert in any LBE, even if the LBE does not have that tag itself #define CORPSE 0x00008000 //32768 // a dead body #define SKIN_BLOODCAT 0x00010000 //65536 // retrieve this by skinning (=decapitating) a bloodcat #define NO_METAL_DETECTION 0x00020000 //131072 // a planted bomb with this flag can NOT be detected via metal detector. Use sparingly! #define JUMP_GRENADE 0x00040000 //262144 // add +25 heigth to explosion, used for bouncing grenades and jumping mines -/*#define PLAYER_NET_4_LVL_1 0x00080000 //524288 +#define HANDCUFFS 0x00080000 //524288 // item can be used to capture soldiers -#define PLAYER_NET_1_LVL_2 0x00100000 //1048576 +/*#define PLAYER_NET_1_LVL_2 0x00100000 //1048576 #define PLAYER_NET_2_LVL_2 0x00200000 //2097152 #define PLAYER_NET_3_LVL_2 0x00400000 //4194304 #define PLAYER_NET_4_LVL_2 0x00800000 //8388608 diff --git a/Tactical/Morale.cpp b/Tactical/Morale.cpp index 25def544..667778b2 100644 --- a/Tactical/Morale.cpp +++ b/Tactical/Morale.cpp @@ -711,7 +711,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I if ( gGameOptions.fNewTraitSystem ) { // Flugente: if we have the covert trait and are covert, we might simply be returning from a reconnaissance mission in enemy territory. No need for a morale drop in this case - if ( !HAS_SKILL_TRAIT( pTeamSoldier, COVERT_NT ) || ( pTeamSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) == 0) ) + if ( !HAS_SKILL_TRAIT( pTeamSoldier, COVERT_NT ) || ( (pTeamSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) == 0) ) { // SANDRO - no penalty for pacifists to run away if ( gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait != CHAR_TRAIT_PACIFIST ) diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 9894a8f9..60b4b59d 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -1660,6 +1660,11 @@ BOOLEAN ExecuteOverhead( ) pSoldier->EVENT_SoldierBuildStructure( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; } + else if ( pSoldier->aiData.ubPendingAction == MERC_HANDCUFF_PERSON ) + { + pSoldier->EVENT_SoldierHandcuffPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEITEM ) { pSoldier->EVENT_SoldierBeginGiveItem( ); @@ -4040,7 +4045,7 @@ UINT8 LastActiveTeamMember( UINT8 ubTeam ) void CheckForPotentialAddToBattleIncrement( SOLDIERTYPE *pSoldier ) { - UINT16 iCounter2; + //UINT16 iCounter2; // Check if we are a threat! if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) ) { @@ -6632,6 +6637,240 @@ void DeathNoMessageTimerCallback( void ) } } +BOOLEAN GetPlayerControlledPrisonSectorId(UINT32& auSectorID) +{ + auSectorID = 0; + UINT16 highestprisonsize = 0; + + for(INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) + { + for(INT16 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) + { + if ( !SectorOursAndPeaceful( sX, sY, 0 ) ) + continue; + + // Is there a prison in this sector? + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) + { + // Is this facility here? + if (gFacilityLocations[SECTOR(sX, sY)][cnt].fFacilityHere) + { + // we determine wether this is a prison by checking for usPrisonBaseLimit + if ( gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > highestprisonsize ) + { + highestprisonsize = gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit; + auSectorID = SECTOR(sX, sY); + break; + } + } + } + } + } + + return (highestprisonsize > 0); +} + +extern INT32 giReinforcementPool; + +void PrisonerMessageBoxCallBack( UINT8 ubExitValue ) +{ + if ( !gbWorldSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + UINT32 prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; + + pSectorInfo->uiNumberOfPrisonersOfWar = 0; + + if (ubExitValue == MSG_BOX_RETURN_YES) + { + UINT32 uSectorID = 0; + if ( GetPlayerControlledPrisonSectorId(uSectorID) ) + { + SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ uSectorID ] ); + + if ( pPrisonSectorInfo ) + pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; + } + } + else + { + // send some prisoners back to queen's pool + // there is a chance that escaped prisoners may return to the queen... + giReinforcementPool += (prisonerstobemoved * gGameExternalOptions.ubPrisonerReturntoQueenChance) / 100; + } + } + else + { + UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + + UINT32 prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; + + pSectorInfo->uiNumberOfPrisonersOfWar = 0; + + if (ubExitValue == MSG_BOX_RETURN_YES) + { + UINT32 uSectorID = 0; + if ( GetPlayerControlledPrisonSectorId(uSectorID) ) + { + SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ uSectorID ] ); + + if ( pPrisonSectorInfo ) + pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; + } + } + else + { + // send some prisoners back to queen's pool + // there is a chance that escaped prisoners may return to the queen... + giReinforcementPool += (prisonerstobemoved * gGameExternalOptions.ubPrisonerReturntoQueenChance) / 100; + } + } +} + +void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) +{ + SOLDIERTYPE *pTeamSoldier; + INT32 cnt = 0; + UINT8 ubNumPrisoners = 0; + UINT8 ubNumPrisonerAdmin = 0; + UINT8 ubNumPrisonerTroop = 0; + UINT8 ubNumPrisonerElite = 0; + + // Check if the battle is won! + // Loop through all mercs and make go + for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt ) + { + // Kill those not already dead.,... + if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == ENEMY_TEAM ) + { + // For sure for flag thet they are dead is not set + if ( ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) + { + if ( pTeamSoldier->stats.bLife > OKLIFE && pTeamSoldier->stats.bLife != 0 ) + { + switch ( pTeamSoldier->ubSoldierClass ) + { + case SOLDIER_CLASS_ADMINISTRATOR: ubNumPrisonerAdmin++; break; + case SOLDIER_CLASS_ARMY: ubNumPrisonerTroop++; break; + case SOLDIER_CLASS_ELITE: ubNumPrisonerElite++; break; + default: + // if none of the above classes, ignore this one + continue; + break; + } + + ++ubNumPrisoners; + + // place items on the floor + INT8 bVisible = 0; + UINT16 usItemFlags = 0; + UINT8 size = pTeamSoldier->inv.size(); + for ( UINT8 cnt = 0; cnt < size; ++cnt ) + { + OBJECTTYPE* pObj = &( pTeamSoldier->inv[ cnt ] ); + + if ( pObj->exists() == true ) + { + // Check if it's supposed to be dropped + if ( !( (*pObj).fFlags & OBJECT_UNDROPPABLE ) || pTeamSoldier->bTeam == gbPlayerNum ) + { + if ( !(Item[ pObj->usItem ].defaultundroppable ) ) + { + //ReduceAmmoDroppedByNonPlayerSoldiers( pTeamSoldier, cnt ); + + //if this soldier was an enemy + // Kaiden: Added from UB's reveal all items after combat feature! + // HEADROCK HAM B2.8: Now also reveals equipment dropped by militia, if requirement is met. + if( pTeamSoldier->bTeam == ENEMY_TEAM || + ( gGameExternalOptions.ubMilitiaDropEquipment == 2 && pTeamSoldier->bTeam == MILITIA_TEAM ) || + ( gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam != OUR_TEAM )) + { + //add a flag to the item so when all enemies are killed, we can run through and reveal all the enemies items + usItemFlags |= WORLD_ITEM_DROPPED_FROM_ENEMY; + + if ( Item[pObj->usItem].damageable && Item[pObj->usItem].usItemClass != IC_THROWING_KNIFE ) // Madd: drop crappier items from enemies on higher difficulty levels - note the quick fix for throwing knives + { + (*pObj)[0]->data.objectStatus -= (gGameOptions.ubDifficultyLevel - 1) * Random(20); + (*pObj)[0]->data.objectStatus = min(max((*pObj)[0]->data.objectStatus,1),100); // never below 1% or above 100% + + (*pObj)[0]->data.sRepairThreshold = max(1, min(100, ((*pObj)[0]->data.objectStatus + 200)/3 )); + } + } + + //if(UsingNewAttachmentSystem()==true) + //ReduceAttachmentsOnGunForNonPlayerChars(pTeamSoldier, pObj); + + // HEADROCK HAM B2.8: Militia will drop items only if allowed. + if (!(gGameExternalOptions.ubMilitiaDropEquipment == 0 && pTeamSoldier->bTeam == MILITIA_TEAM ) && + !(gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam == OUR_TEAM )) + { + AddItemToPool( pTeamSoldier->sGridNo, pObj, bVisible , pTeamSoldier->pathing.bLevel, usItemFlags, -1 ); + } + } + } + } + } + + DropKeysInKeyRing( pTeamSoldier, pTeamSoldier->sGridNo, pTeamSoldier->pathing.bLevel, bVisible, FALSE, 0, FALSE ); + + // Make team look for items + AllSoldiersLookforItems( TRUE ); + + if ( pTeamSoldier->bTeam != gbPlayerNum ) + // Remove merc! + // ATE: Remove merc slot first - will disappear if no corpse data found! + TacticalRemoveSoldier( pTeamSoldier->ubID ); + else + pTeamSoldier->RemoveSoldierFromGridNo( ); + + // Remove as target + RemoveManAsTarget( pTeamSoldier ); + } + } + } + } + + if (!bMapZ) // Battle ended Above-ground + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); + + pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; + + pSectorInfo->ubNumAdmins -= ubNumPrisonerAdmin; + pSectorInfo->ubNumTroops -= ubNumPrisonerTroop; + pSectorInfo->ubNumElites -= ubNumPrisonerElite; + + pSectorInfo->ubAdminsInBattle -= ubNumPrisonerAdmin; + pSectorInfo->ubTroopsInBattle -= ubNumPrisonerTroop; + pSectorInfo->ubElitesInBattle -= ubNumPrisonerElite; + } + else + { + UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ ); + + pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; + + pSectorInfo->ubNumAdmins -= ubNumPrisonerAdmin; + pSectorInfo->ubNumTroops -= ubNumPrisonerTroop; + pSectorInfo->ubNumElites -= ubNumPrisonerElite; + + pSectorInfo->ubAdminsInBattle -= ubNumPrisonerAdmin; + pSectorInfo->ubTroopsInBattle -= ubNumPrisonerTroop; + pSectorInfo->ubElitesInBattle -= ubNumPrisonerElite; + } + + if ( ubNumPrisoners ) + { + //if ( guiCurrentScreen == GAME_SCREEN ) + UINT32 uSectorID = 0; + if ( GetPlayerControlledPrisonSectorId(uSectorID) ) + DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[ PRISONER_DECIDE_STR ], guiCurrentScreen, ( UINT8 )MSG_BOX_FLAG_YESNO, PrisonerMessageBoxCallBack, NULL ); + else + DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[ PRISONER_NO_PRISONS_STR ], guiCurrentScreen, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL ); + } +} + void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { if (!bMapZ) // Battle ended Above-ground @@ -6829,6 +7068,9 @@ BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated ) } } + // Flugente: remove those enemies that are captured and add them to the prisoner pool + RemoveCapturedEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + // Kill all enemies. Sometime even after killing all the enemies, there appeares "in battle" enemies in sector info RemoveStaticEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); @@ -7431,6 +7673,10 @@ UINT8 NumCapableEnemyInSector( ) } else { + // Flugente: captured soldiers also do not count + if ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW ) + continue; + // Check for any more badguys if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) ) { diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index de6c0092..514ace6b 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -3663,9 +3663,18 @@ INT16 GetAPsToBuildFortification( SOLDIERTYPE *pSoldier, INT32 usMapPos ) sAPCost += APBPConstants[AP_FORTIFICATION]; return sAPCost; - } +INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos ) +{ + INT16 sAPCost = 0; + + sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ); + + sAPCost += APBPConstants[AP_HANDCUFF]; + + return sAPCost; +} INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier ) { diff --git a/Tactical/Points.h b/Tactical/Points.h index 55a8ee86..93955f57 100644 --- a/Tactical/Points.h +++ b/Tactical/Points.h @@ -357,6 +357,7 @@ INT16 GetAPsToUseCan( SOLDIERTYPE *pSoldier, INT32 usMapPos ); INT16 GetBPsTouseJar( SOLDIERTYPE *pSoldier ); INT16 GetAPsToBuildFortification( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente +INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index f5b07f76..e3cf9df8 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -15217,6 +15217,51 @@ void SOLDIERTYPE::Strip() } } +// can we process prisoners in this sector? +BOOLEAN SOLDIERTYPE::CanProcessPrisoners() +{ + if ( !bInSector || stats.bLife < OKLIFE ) + return FALSE; + + // Is there a prison in this sector? + BOOLEAN prisonhere = FALSE; + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) + { + // Is this facility here? + if (gFacilityLocations[SECTOR(this->sSectorX, this->sSectorY)][cnt].fFacilityHere) + { + // we determine wether this is a prison by checking for usPrisonBaseLimit + if (gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > 0) + { + prisonhere = TRUE; + break; + } + } + } + + if ( !prisonhere ) + return FALSE; + + // Are there any prisoners in this prison? + if ( !this->bSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); + + if ( pSectorInfo->uiNumberOfPrisonersOfWar > 0 ) + return TRUE; + } + // no underground prisons anyway + /*else + { + UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); + + if ( pSectorInfo->uiNumberOfPrisonersOfWar > 0 ) + return TRUE; + }*/ + + return FALSE; +} + INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) { INT8 bBandaged; //,savedOurTurn; @@ -16115,6 +16160,103 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection } } +void SOLDIERTYPE::EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection ) +{ + UINT8 ubPerson = WhoIsThere2( sGridNo, this->pathing.bLevel ); + + if ( ubPerson != NOBODY && MercPtrs[ ubPerson ]->bTeam == ENEMY_TEAM && !(MercPtrs[ ubPerson ]->bSoldierFlagMask & SOLDIER_POW) ) + { + // we found someone we can handcuff + SOLDIERTYPE* pSoldier = MercPtrs[ ubPerson ]; + + // check wether we will be successful + BOOLEAN success = FALSE; + if ( pSoldier->flags.fMercAsleep || pSoldier->bCollapsed ) + success = TRUE; + else + { + // check wether we can forcefully handcuff the other soldier, but this will be hard + UINT32 attackrating = 10 * EffectiveExpLevel( this ) + EffectiveStrength( this, FALSE ) + 2 * EffectiveDexterity( this, FALSE ) + EffectiveAgility( this, FALSE ); + UINT32 defenserating = 10 * EffectiveExpLevel( pSoldier ) + 2 * EffectiveStrength( pSoldier, FALSE ) + EffectiveDexterity( pSoldier, FALSE ) + 2 * EffectiveAgility( pSoldier, FALSE ); + + ReducePointsForFatigue( this, &attackrating ); + ReducePointsForFatigue( pSoldier, &defenserating ); + + if ( Random(attackrating) > Random(defenserating) + 50 ) + success = TRUE; + } + + if ( success ) + { + // arrest this guy + pSoldier->bSoldierFlagMask |= SOLDIER_POW; + + // move the items in his hands to the floor and move our handcuff into his hands + if ( pSoldier->inv[ HANDPOS ].exists() == true && !( pSoldier->inv[ HANDPOS ].fFlags & OBJECT_UNDROPPABLE )) + { + // ATE: if our guy, make visible.... + INT8 bVisible = (pSoldier->bTeam == gbPlayerNum) ? 1 : 0; + UINT16 itemflags = ( pSoldier->bTeam == ENEMY_TEAM ) ? 0 : WORLD_ITEM_DROPPED_FROM_ENEMY; + + if(UsingNewAttachmentSystem()==true) + ReduceAttachmentsOnGunForNonPlayerChars(pSoldier, &(pSoldier->inv[ HANDPOS ])); + + AddItemToPool( pSoldier->sGridNo, &(pSoldier->inv[ HANDPOS ]), bVisible, pSoldier->pathing.bLevel, itemflags, -1 ); //Madd: added usItemFlags to function arguments + DeleteObj( &(pSoldier->inv[HANDPOS]) ); + } + + if ( pSoldier->inv[ SECONDHANDPOS ].exists() == true && !( pSoldier->inv[ SECONDHANDPOS ].fFlags & OBJECT_UNDROPPABLE )) + { + // ATE: if our guy, make visible.... + INT8 bVisible = (pSoldier->bTeam == gbPlayerNum) ? 1 : 0; + UINT16 itemflags = ( pSoldier->bTeam == ENEMY_TEAM ) ? 0 : WORLD_ITEM_DROPPED_FROM_ENEMY; + + if(UsingNewAttachmentSystem()==true) + ReduceAttachmentsOnGunForNonPlayerChars(pSoldier, &(pSoldier->inv[ SECONDHANDPOS ])); + + AddItemToPool( pSoldier->sGridNo, &(pSoldier->inv[ SECONDHANDPOS ]), bVisible, pSoldier->pathing.bLevel, itemflags, -1 ); //Madd: added usItemFlags to function arguments + DeleteObj( &(pSoldier->inv[SECONDHANDPOS]) ); + } + + // move handcuffs to his hands + if ( HasItemFlag( (&(this->inv[HANDPOS]))->usItem, HANDCUFFS ) ) + { + AutoPlaceObject( pSoldier, &(this->inv[HANDPOS]), FALSE ); + DeleteObj( &(this->inv[HANDPOS]) ); + } + + // CHANGE DIRECTION AND GOTO ANIMATION NOW + this->EVENT_SetSoldierDesiredDirection( ubDirection ); + this->EVENT_SetSoldierDirection( ubDirection ); + + // CHANGE TO ANIMATION + this->EVENT_InitNewSoldierAnim( RELOAD_ROBOT, 0 , FALSE ); + + // we gain a bit of experience... + StatChange( this, STRAMT, 2, TRUE ); + StatChange( this, DEXTAMT, 3, TRUE ); + StatChange( this, EXPERAMT, 2, TRUE ); + + DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), 0, AFTERACTION_INTERRUPT ); + } + else + { + // we gain a bit of experience... + StatChange( this, DEXTAMT, 2, TRUE ); + + DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), 0, AFTERACTION_INTERRUPT ); + + // curses! + this->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); + } + } + else + { + // Say NOTHING quote... + this->DoMercBattleSound( BATTLE_SOUND_NOTHING ); + } +} + void SOLDIERTYPE::EVENT_SoldierBeginReloadRobot( INT32 sGridNo, UINT8 ubDirection, UINT8 ubMercSlot ) { diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index b569eeb9..424df2b6 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -223,6 +223,7 @@ enum MERC_ATTACH_CAN, MERC_FUEL_VEHICLE, MERC_BUILD_FORTIFICATION, + MERC_HANDCUFF_PERSON, }; // ENUMERATIONS FOR THROW ACTIONS @@ -356,8 +357,8 @@ enum #define SOLDIER_DAMAGED_PANTS 0x00000100 //256 // Soldier's vest is damaged (and thus can't be taken off) #define SOLDIER_HEADSHOT 0x00000200 //512 // last hit received was a headshot (attack to the head, so knifes/punches also work) -/*#define WH40K_POWER_WEAPON 0x00000400 //1024 -#define ENEMY_NET_4_LVL_3 0x00000800 //2048 +#define SOLDIER_POW 0x00000400 //1024 // we are a prisoner of war +/*#define ENEMY_NET_4_LVL_3 0x00000800 //2048 #define ENEMY_NET_1_LVL_4 0x00001000 //4096 #define ENEMY_NET_2_LVL_4 0x00002000 //8192 @@ -411,7 +412,7 @@ extern CLOTHES_STRUCT Clothes[CLOTHES_MAX]; // This macro should be used whenever we want to see if someone is neutral // IF WE ARE CONSIDERING ATTACKING THEM. Creatures & bloodcats will attack neutrals // but they can't attack empty vehicles!! -#define CONSIDERED_NEUTRAL( me, them ) ( (them->aiData.bNeutral || them->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) && ( me->bTeam != CREATURE_TEAM || (them->flags.uiStatusFlags & SOLDIER_VEHICLE) ) ) +#define CONSIDERED_NEUTRAL( me, them ) ( (them->aiData.bNeutral || them->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER|SOLDIER_POW)) && ( me->bTeam != CREATURE_TEAM || (them->flags.uiStatusFlags & SOLDIER_VEHICLE) ) ) typedef struct { @@ -1322,6 +1323,7 @@ public: void EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCounter ); void EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente + void EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente BOOLEAN EVENT_InternalGetNewSoldierPath( INT32 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestart ); void EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BOOLEAN fFromMove, UINT16 usAnimState ); @@ -1494,6 +1496,9 @@ public: // lose disguise or take off any clothes item and switch back to original clothes void Strip(); + + // Flugente: prisoner system + BOOLEAN CanProcessPrisoners(); ////////////////////////////////////////////////////////////////////////////// }; // SOLDIERTYPE; diff --git a/Tactical/UI Cursors.cpp b/Tactical/UI Cursors.cpp index 99edd7fd..818032e2 100644 --- a/Tactical/UI Cursors.cpp +++ b/Tactical/UI Cursors.cpp @@ -54,6 +54,7 @@ UINT8 HandleBombCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fActivated UINT8 HandleJarCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); UINT8 HandleTinCanCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente +UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente extern BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel ); @@ -304,6 +305,11 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos ubCursorID = HandleFortificationCursor( pSoldier, sTargetGridNo, uiCursorFlags ); break; + case HANDCUFFCURS: + + ubCursorID = HandleHandcuffCursor( pSoldier, sTargetGridNo, uiCursorFlags ); + break; + case INVALIDCURS: ubCursorID = INVALID_ACTION_UICURSOR; @@ -2208,7 +2214,26 @@ UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 ui return( FORTIFICATION_RED_UICURSOR ); } +UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ) +{ + // DRAW PATH TO GUY + HandleUIMovementCursor( pSoldier, uiCursorFlags, sGridNo, MOVEUI_TARGET_HANDCUFF ); + + // do we have handcuffs in our hand? + if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, HANDCUFFS ) ) + { + // is there a person here? + UINT8 usSoldierIndex = WhoIsThere2( sGridNo, pSoldier->pathing.bLevel ); + if ( usSoldierIndex != NOBODY ) + { + // no handcuffing if the guy is already caught... + if ( !(MercPtrs[usSoldierIndex]->bSoldierFlagMask & SOLDIER_POW) ) + return( HANDCUFF_GREY_UICURSOR ); + } + } + return( HANDCUFF_RED_UICURSOR ); +} void HandleEndConfirmCursor( SOLDIERTYPE *pSoldier ) { @@ -2685,6 +2710,10 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier ) if ( HasItemFlag(usInHand, (EMPTY_SANDBAG|FULL_SANDBAG|SHOVEL|CONCERTINA)) ) ubCursor = FORTICURS; + // Flugente: cursor for handcuffs + if ( HasItemFlag(usInHand, HANDCUFFS) ) + ubCursor = HANDCUFFCURS; + // Now check our terrain to see if we cannot do the action now... if ( WaterTooDeepForAttacks( pSoldier->sGridNo) ) { diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index e6e51457..b4c726c0 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -3012,9 +3012,12 @@ IAN COMMENTED THIS OUT MAY 1997 - DO WE NEED THIS? if (pOpponent) { // check to see if OPPONENT considers US neutral - if ( (pOpponent->aiData.bOppList[ubTarget] == SEEN_CURRENTLY) && !pOpponent->aiData.bNeutral && !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && (pSoldier->bSide != pOpponent->bSide) && pOpponent->RecognizeAsCombatant(pSoldier->ubID) ) + if ( (pOpponent->aiData.bOppList[ubTarget] == SEEN_CURRENTLY) && !pOpponent->aiData.bNeutral && (pSoldier->bSide != pOpponent->bSide) ) { - RemoveOneOpponent(pOpponent); + // Flugente: we consider enemies to be neutral if they are prisoners of war (otherwise the AI would kill prisoners). Bu as we want to remove them, we have to account for that + // we also move RecognizeAsCombatant to be the last condition checked, because it is the most computationally expensive one + if ( ( !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) || pSoldier->bSoldierFlagMask & SOLDIER_POW ) && pOpponent->RecognizeAsCombatant(pSoldier->ubID) ) + RemoveOneOpponent(pOpponent); } UpdatePersonal(pOpponent,ubTarget,NOT_HEARD_OR_SEEN,NOWHERE,0); gbSeenOpponents[ubLoop][ubTarget] = FALSE; diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 48ec6149..cfa8aa9b 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -1789,7 +1789,12 @@ void TurnBasedHandleNPCAI(SOLDIERTYPE *pSoldier) } */ - + // Flugente: pows don't do anything + if ( pSoldier->bSoldierFlagMask & SOLDIER_POW ) + { + EndAIGuysTurn( pSoldier); + return; + } if ((pSoldier->aiData.bAction != AI_ACTION_NONE) && pSoldier->aiData.bActionInProgress) { diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index 9f6708c0..a52a2e9b 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -2971,3 +2971,48 @@ INT32 CalcStraightThreatValue( SOLDIERTYPE *pEnemy ) return(iThreatValue); } + +// Flugente: get the id of the closest soldier with a specific flag that we can currently see +UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam, UINT32 aFlag ) +{ + UINT8 id = NOBODY; + + UINT32 uiLoop; + BOOLEAN fRangeRestricted = FALSE, fFound = FALSE; + SOLDIERTYPE * pFriend; + INT16 range = aRange; + + // go through each soldier, looking for "friends" (soldiers on same side) + for (uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop) + { + pFriend = MercSlots[ uiLoop ]; + + // if this merc is inactive, not in sector, or dead + if (!pFriend) + continue; + + if ( auTeam != pFriend->bTeam ) + continue; + + // check for flag + if ( !(pFriend->bSoldierFlagMask & aFlag) ) + continue; + + // skip ourselves + if (pFriend->ubID == pSoldier->ubID) + continue; + + // if we're not already neighbors + if (SpacesAway(pSoldier->sGridNo, pFriend->sGridNo) < range) + { + // can we see this guy? + if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pFriend->sGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) ) + { + range = SpacesAway(pSoldier->sGridNo,pFriend->sGridNo); + id = pFriend->ubID; + } + } + } + + return id; +} diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index 4c378971..0a317261 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -869,32 +869,42 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier) } //ddd{ - if(gGameExternalOptions.bNewTacticalAIBehavior - && !( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) ) - && pSoldier->bTeam == ENEMY_TEAM) + if(gGameExternalOptions.bNewTacticalAIBehavior && pSoldier->bTeam == ENEMY_TEAM ) { - - INT32 cnt; - ROTTING_CORPSE * pCorpse; - - for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ ) + if ( !(gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) ) { - pCorpse = &(gRottingCorpse[ cnt ] ); + + INT32 cnt; + ROTTING_CORPSE * pCorpse; + + for ( cnt = 0; cnt < giNumRottingCorpse; cnt++ ) + { + pCorpse = &(gRottingCorpse[ cnt ] ); - if ( pCorpse->fActivated && pCorpse->def.ubAIWarningValue > 0 ) - if ( PythSpacesAway( pSoldier->sGridNo, pCorpse->def.sGridNo ) <= 5 )// (smaxvid ?) - { - //, .? - //CHRISL: Shouldn't we be using the corpse's bLevel? Otherwise a soldier inside a building can see a corpse on the roof of that building - //if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) ) - if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pCorpse->def.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) ) + if ( pCorpse->fActivated && pCorpse->def.ubAIWarningValue > 0 ) + if ( PythSpacesAway( pSoldier->sGridNo, pCorpse->def.sGridNo ) <= 5 )// (smaxvid ?) { - ScreenMsg( MSG_FONT_YELLOW, MSG_INTERFACE, New113Message[MSG113_ENEMY_FOUND_DEAD_BODY]); - //pCorpse->def.ubAIWarningValue=0; - gRottingCorpse[ cnt ].def.ubAIWarningValue=0; - return( AI_ACTION_RED_ALERT ); + //, .? + //CHRISL: Shouldn't we be using the corpse's bLevel? Otherwise a soldier inside a building can see a corpse on the roof of that building + //if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pSoldier->pathing.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) ) + if ( SoldierTo3DLocationLineOfSightTest( pSoldier, pCorpse->def.sGridNo, pCorpse->def.bLevel, 3, TRUE, CALC_FROM_WANTED_DIR ) ) + { + ScreenMsg( MSG_FONT_YELLOW, MSG_INTERFACE, New113Message[MSG113_ENEMY_FOUND_DEAD_BODY]); + //pCorpse->def.ubAIWarningValue=0; + gRottingCorpse[ cnt ].def.ubAIWarningValue=0; + return( AI_ACTION_RED_ALERT ); + } } - } + } + } + + // Flugente: if we see one of our buddies in handcuffs, its a clear sign of enemy activity! + if ( pSoldier->bTeam == ENEMY_TEAM ) + { + UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 10, ENEMY_TEAM, SOLDIER_POW ); + + if ( ubPerson != NOBODY ) + return( AI_ACTION_RED_ALERT ); } } //ddd} @@ -1462,7 +1472,14 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier) return(AI_ACTION_NONE); } + // Flugente: if we see one of our buddies in handcuffs, its a clear sign of enemy activity! + if ( pSoldier->bTeam == ENEMY_TEAM ) + { + UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 10, ENEMY_TEAM, SOLDIER_POW ); + if ( ubPerson != NOBODY ) + return( AI_ACTION_RED_ALERT ); + } //////////////////////////////////////////////////////////////////////////// // LOOK AROUND TOWARD NOISE: determine %chance for man to turn towards noise diff --git a/TacticalAI/Realtime.cpp b/TacticalAI/Realtime.cpp index 74f44074..420763a6 100644 --- a/TacticalAI/Realtime.cpp +++ b/TacticalAI/Realtime.cpp @@ -132,8 +132,12 @@ void RTHandleAI( SOLDIERTYPE * pSoldier ) #endif // let it continue return; + } } - } + + // Flugente: prisoners of war don't do anything + if ( pSoldier->bSoldierFlagMask & SOLDIER_POW ) + return; // if man has nothing to do if (pSoldier->aiData.bAction == AI_ACTION_NONE) diff --git a/TacticalAI/ai.h b/TacticalAI/ai.h index 76449799..72b194a4 100644 --- a/TacticalAI/ai.h +++ b/TacticalAI/ai.h @@ -256,4 +256,7 @@ INT8 CalcBestCTGT( SOLDIERTYPE *pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 INT8 CalcAverageCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft ); UINT8 NumberOfTeamMatesAdjacent( SOLDIERTYPE * pSoldier, INT32 sGridNo ); +// Flugente: get the id of the closest soldier (coser than x tiles) of a specific team with a specific flag that we can currently see +UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam, UINT32 aFlag ); + #endif diff --git a/Utils/Cursors.cpp b/Utils/Cursors.cpp index 9cb9cccc..eb97dbb2 100644 --- a/Utils/Cursors.cpp +++ b/Utils/Cursors.cpp @@ -122,6 +122,9 @@ CursorFileData CursorFileDatabase[] = { "CURSORS\\hammer.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: fortification stuff { "CURSORS\\hammer_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, + { "CURSORS\\handcuffs.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: handcuffs stuff + { "CURSORS\\handcuffs_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, + { "CURSORS\\can_01.sti" , FALSE, 0, 0, 0, NULL }, { "CURSORS\\can_02.sti" , FALSE, 0, 0, 0, NULL }, { "CURSORS\\cur_tagr_ncth.sti" , FALSE, 0, ANIMATED_CURSOR, 7, NULL }, @@ -1182,6 +1185,7 @@ CursorData CursorDatabase[] = 0, 0, 0, 0, 0, 2, CENTER_CURSOR, CENTER_CURSOR , 0, 0 , 0, 0 }, + // Flugente: fortification { C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR, C_FORTIFICATION , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR, 0, 0, 0, 0, 0, @@ -1196,6 +1200,21 @@ CursorData CursorDatabase[] = 0, 0, 0, 0, 0, 2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 }, + // Flugente: handcuffs + { C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR, + C_HANDCUFFS , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 }, + + { C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR, + C_HANDCUFFS_RED , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 }, + { C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR, C_FUEL , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR, 0, 0, 0, 0, 0, diff --git a/Utils/Cursors.h b/Utils/Cursors.h index 660a4471..a3478976 100644 --- a/Utils/Cursors.h +++ b/Utils/Cursors.h @@ -156,6 +156,9 @@ typedef enum CURSOR_FORTIFICATION, CURSOR_FORTIFICATION_RED, + CURSOR_HANDCUFF, + CURSOR_HANDCUFF_RED, + CURSOR_FUEL, CURSOR_FUEL_RED, @@ -231,6 +234,8 @@ typedef enum C_JUMPOVER, C_FORTIFICATION, C_FORTIFICATION_RED, + C_HANDCUFFS, + C_HANDCUFFS_RED, C_FUEL, C_FUEL_RED, C_ACTIONMODERED_NCTH, diff --git a/Utils/Text.h b/Utils/Text.h index 8f66ce92..3441dea1 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -728,6 +728,19 @@ enum extern STR16 szFoodTextStr[]; +enum +{ + STR_PRISONER_PROCESSED, + STR_PRISONER_RANSOM, + STR_PRISONER_DETECTION, + STR_PRISONER_TURN_MILITIA, + STR_PRISONER_RIOT, + + TEXT_NUM_PRISONER_STR +}; + +extern STR16 szPrisonerTextStr[]; + enum { AIR_RAID_TURN_STR, @@ -897,6 +910,8 @@ enum FUNCTION_SELECTION_STR, CORPSE_SELECTION_STR, WEAPON_CLEANING_STR, + PRISONER_NO_PRISONS_STR, + PRISONER_DECIDE_STR, TEXT_NUM_TACTICAL_STR }; diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 811b3cbc..3350899a 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -1635,13 +1635,14 @@ STR16 pAssignmentStrings[] = L"在途中",// in transit - abbreviated form L"修理", // repairing L"锻炼", // training themselves - L"民兵", // training a town to revolt - L"游击队", //L"M.Militia", //training moving militia units //ham3.6 + L"民兵", // training a town to revolt + L"游击队", //L"M.Militia", //training moving militia units //ham3.6 L"教练", // training a teammate L"学员", // being trained by someone else L"工作", // L"Staff", // operating a strategic facility //ham3.6 L"饮食", // eating at a facility (cantina etc.) L"休息", //L"Rest",// Resting at a facility //ham3.6 + L"Prison", // Flugente: interrogate prisoners L"死亡", // dead L"无力中", // abbreviation for incapacitated L"战俘", // Prisoner of war - captured @@ -1727,6 +1728,7 @@ STR16 pPersonnelAssignmentStrings[] = L"设施职员", L"饮食", // eating at a facility (cantina etc.) L"在设施里休养", + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"休息", L"无力中", L"战俘", @@ -1772,6 +1774,7 @@ STR16 pLongAssignmentStrings[] = L"学员", L"设施职员", //L"Staff Facility", L"休息", //L"Rest at Facility", + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"死亡", L"无力中", L"战俘", @@ -2598,7 +2601,8 @@ CHAR16 zHealthStr[][13] = L"受伤", //"WOUNDED", // >= 45 L"健康", //"HEALTHY", // >= 60 L"强壮", //"STRONG", // >= 75 - L"极好", //"EXCELLENT", // >= 90 + L"极好", //"EXCELLENT", // >= 90 + L"CAPTURED", // added by Flugente TODO.Translate }; STR16 gzHiddenHitCountStr[1] = @@ -2911,6 +2915,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3409,6 +3417,7 @@ STR16 pTransactionText[] = L"将装备卖给了当地人", L"工厂使用", // L"Facility Use", // HEADROCK HAM 3.6 L"民兵保养", // L"Militia upkeep", // HEADROCK HAM 3.6 + L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -6711,6 +6720,7 @@ STR16 gzFacilityAssignmentStrings[]= L"训练医疗", L"训练领导", L"训练爆破", + L"Interrogate Prisoners", // added by Flugente TODO.Translate }; STR16 Additional113Text[]= { @@ -7476,4 +7486,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //CHINESE diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 72914734..20892a7b 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -1638,6 +1638,7 @@ STR16 pAssignmentStrings[] = L"Staff", // operating a strategic facility // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Rest", // Resting at a facility // TODO.Translate + L"Prison", // Flugente: interrogate prisoners L"Dood", // dead L"Uitgesc.", // abbreviation for incapacitated L"POW", // Prisoner of war - captured @@ -1723,6 +1724,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Facility Staff", // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Resting at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Dood", // dead L"Uitgesc.", // abbreviation for incapacitated L"POW", // Prisoner of war - captured @@ -1768,6 +1770,7 @@ STR16 pLongAssignmentStrings[] = L"Student", // being trained by someone else L"Staff Facility", // TODO.Translate L"Rest at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Dood", // dead L"Uitgesc.", // abbreviation for incapacitated L"POW", // Prisoner of war - captured @@ -2596,6 +2599,7 @@ CHAR16 zHealthStr[][13] = L"GEZOND", // >= 60 L"STERK", // >= 75 L"EXCELLENT", // >= 90 + L"CAPTURED", // added by Flugente TODO.Translate }; STR16 gzHiddenHitCountStr[1] = @@ -2908,6 +2912,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3407,6 +3415,7 @@ STR16 pTransactionText[] = L"%s heeft geld gestort.", L"Facility Use", // HEADROCK HAM 3.6 // TODO.Translate L"Militia upkeep", // HEADROCK HAM 3.6 // TODO.Translate + L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -6703,6 +6712,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Trainer Mechanical", L"Trainer Leadership", L"Trainer Explosives", + L"Interrogate Prisoners", // added by Flugente TODO.Translate }; STR16 Additional113Text[]= @@ -7469,4 +7479,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //DUTCH diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index b3049be9..1c8f043d 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -1635,13 +1635,14 @@ STR16 pAssignmentStrings[] = L"In Trans", // in transit - abbreviated form L"Repair", // repairing L"Practice", // training themselves - L"Militia", // training a town to revolt + L"Militia", // training a town to revolt L"M.Militia", //training moving militia units L"Trainer", // training a teammate L"Student", // being trained by someone else L"Staff", // operating a strategic facility L"Eat", // eating at a facility (cantina etc.) L"Rest", // Resting at a facility + L"Prison", // Flugente: interrogate prisoners L"Dead", // dead L"Incap.", // abbreviation for incapacitated L"POW", // Prisoner of war - captured @@ -1727,6 +1728,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Facility Staff", // Missing L"Eat", // eating at a facility (cantina etc.) L"Resting at Facility", // Missing + L"Interrogate prisoners", // Flugente: interrogate prisoners L"Dead", L"Incap.", L"POW", @@ -1772,6 +1774,7 @@ STR16 pLongAssignmentStrings[] = L"Student", L"Staff Facility", // Missing L"Rest at Facility", // Missing + L"Interrogate prisoners", // Flugente: interrogate prisoners L"Dead", L"Incap.", L"POW", @@ -2592,12 +2595,13 @@ CHAR16 gMoneyStatsDesc[][ 14 ] = CHAR16 zHealthStr[][13] = { L"DYING", // >= 0 - L"CRITICAL", // >= 15 + L"CRITICAL", // >= 15 L"POOR", // >= 30 L"WOUNDED", // >= 45 L"HEALTHY", // >= 60 L"STRONG", // >= 75 - L"EXCELLENT", // >= 90 + L"EXCELLENT", // >= 90 + L"CAPTURED", // added by Flugente }; STR16 gzHiddenHitCountStr[1] = @@ -2910,6 +2914,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3408,6 +3416,7 @@ STR16 pTransactionText[] = L"Sold Item(s) to the Locals", L"Facility Use", // HEADROCK HAM 3.6 L"Militia upkeep", // HEADROCK HAM 3.6 + L"Ransom for released prisoners", // Flugente: prisoner system }; STR16 pTransactionAlternateText[] = @@ -6693,6 +6702,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Trainer Mechanical", L"Trainer Leadership", L"Trainer Explosives", + L"Interrogate Prisoners", // added by Flugente }; STR16 Additional113Text[]= { @@ -7457,4 +7467,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //ENGLISH diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index cca970bc..2d1fc041 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -1641,6 +1641,7 @@ STR16 pAssignmentStrings[] = L"Exploitation", // operating a strategic facility L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Repos", // Resting at a facility + L"Prison", // Flugente: interrogate prisoners L"Mort(e)", // dead L"Incap.", // abbreviation for incapacitated L"Capturé", // Prisoner of war - captured @@ -1726,6 +1727,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Exploitation infras.", L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Repos infras.", + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Mort(e)", L"Incap.", L"Capturé(e)", @@ -1771,6 +1773,7 @@ STR16 pLongAssignmentStrings[] = L"Elève", L"Exploitation infras.", L"Repos infras.", + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Mort(e)", L"Incap.", L"Capturé(e)", @@ -2598,6 +2601,7 @@ CHAR16 zHealthStr[][13] = L"EN FORME", // >= 60 L"BON", // >= 75 L"EXCELLENT", // >= 90 + L"CAPTURED", // added by Flugente TODO.Translate }; STR16 gzHiddenHitCountStr[1] = @@ -2910,6 +2914,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3411,6 +3419,7 @@ STR16 pTransactionText[] = L"Materiel vendu à la population", L"Infrastucture utilisée", // HEADROCK HAM 3.6 L"Entretien de la milice", // HEADROCK HAM 3.6 + L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -6679,6 +6688,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Entraineur Mécanique", L"Entraineur Commandement", L"Entraineur Explosif", + L"Interrogate Prisoners", // added by Flugente TODO.Translate }; STR16 Additional113Text[]= { @@ -7443,4 +7453,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //FRENCH diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 3e81dca0..b423a062 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -1651,6 +1651,7 @@ STR16 pAssignmentStrings[] = L"Betrieb", // operating a strategic facility L"Essen", // eating at a facility (cantina etc.) L"Pause", // Resting at a facility + L"Verhör", // Flugente: interrogate prisoners L"Tot", // dead L"Koma", // abbreviation for incapacitated //LOOTF - "Unfähig" klingt schlimm. Geändert auf Koma. Vorschläge? L"Gefangen", // Prisoner of war - captured @@ -1732,6 +1733,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Betriebspersonal", L"Essen", // eating at a facility (cantina etc.) L"Betriebspause", + L"Gefangene verhören", // Flugente: interrogate prisoners L"Tot", L"Koma", //LOOTF - s.o. L"Gefangen", @@ -1775,6 +1777,7 @@ STR16 pLongAssignmentStrings[] = L"Rekrut", L"Betriebspersonal", L"Betriebspause", + L"Gefangene verhören", // Flugente: interrogate prisoners L"Tot", L"Unfähig", L"Gefangen", @@ -2601,7 +2604,8 @@ CHAR16 zHealthStr[][13] = //used to be 10 L"VERWUNDET", // >= 45 L"GESUND", // >= 60 L"STARK", // >= 75 - L"SEHR GUT", // >= 90 + L"SEHR GUT", // >= 90 + L"GEFANGEN", // added by Flugente }; STR16 gzHiddenHitCountStr[1] = @@ -2913,6 +2917,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3382,6 +3390,7 @@ STR16 pTransactionText[] = L"%s hat Geld angelegt.", L"Betriebskosten", // HEADROCK HAM 3.6 L"Unterhaltskosten für Miliz", // HEADROCK HAM 3.6 + L"Lösegeld erpresst", // Flugente: prisoner system }; STR16 pTransactionAlternateText[] = @@ -6521,6 +6530,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Trainer Technik", L"Trainer Führungsqualität", L"Trainer Sprengstoff", + L"Gefangene verhören", // added by Flugente }; STR16 Additional113Text[]= @@ -7284,4 +7294,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //GERMAN diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 2d49b169..52ae167a 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -1627,13 +1627,14 @@ STR16 pAssignmentStrings[] = L"Transito", // in transit - abbreviated form L"Riparare", // repairing L"Esercit.", // training themselves - L"Esercit.", // training a town to revolt + L"Esercit.", // training a town to revolt L"M.Militia", //training moving militia units // TODO.Translate L"Istrutt.", // training a teammate L"Studente", // being trained by someone else L"Staff", // operating a strategic facility // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Rest", // Resting at a facility // TODO.Translate + L"Prison", // Flugente: interrogate prisoners L"Morto", // dead L"Incap.", // abbreviation for incapacitated L"PDG", // Prisoner of war - captured @@ -1719,6 +1720,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Facility Staff", // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Resting at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Morto", L"Incap.", L"PDG", @@ -1764,6 +1766,7 @@ STR16 pLongAssignmentStrings[] = L"Studente", L"Staff Facility", // TODO.Translate L"Rest at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Morto", L"Incap.", L"PDG", @@ -2590,7 +2593,8 @@ CHAR16 zHealthStr[][13] = L"FERITO", // >= 45 L"SANO", // >= 60 L"FORTE", // >= 75 - L"ECCELLENTE", // >= 90 + L"ECCELLENTE", // >= 90 + L"CAPTURED", // added by Flugente TODO.Translate }; STR16 gzHiddenHitCountStr[1] = @@ -2903,6 +2907,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3402,6 +3410,7 @@ STR16 pTransactionText[] = L"%s soldi depositati.", L"Facility Use", // HEADROCK HAM 3.6 // TODO.Translate L"Militia upkeep", // HEADROCK HAM 3.6 // TODO.Translate + L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -6690,6 +6699,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Trainer Mechanical", L"Trainer Leadership", L"Trainer Explosives", + L"Interrogate Prisoners", // added by Flugente TODO.Translate }; STR16 Additional113Text[]= @@ -7456,4 +7466,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //ITALIAN diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index ff32af93..e2b79959 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -1649,6 +1649,7 @@ STR16 pAssignmentStrings[] = L"Staff", // operating a strategic facility // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Rest", // Resting at a facility // TODO.Translate + L"Prison", // Flugente: interrogate prisoners L"Nie żyje", // dead L"Obezwł.", // abbreviation for incapacitated L"Jeniec", // Prisoner of war - captured @@ -1734,6 +1735,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Facility Staff", // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Resting at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Nie żyje", L"Obezwładniony", L"Jeniec", @@ -1779,6 +1781,7 @@ STR16 pLongAssignmentStrings[] = L"Uczeń", L"Staff Facility", // TODO.Translate L"Rest at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Nie żyje", L"Obezwładniony", L"Jeniec", @@ -2606,6 +2609,7 @@ CHAR16 zHealthStr[][13] = L"ZDROWY", // >= 60 L"SILNY", // >= 75 L"DOSKONAŁY", // >= 90 + L"CAPTURED", // added by Flugente TODO.Translate }; STR16 gzHiddenHitCountStr[1] = @@ -2918,6 +2922,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3418,6 +3426,7 @@ STR16 pTransactionText[] = L"Sprzedano rzecz(y) miejscowym", L"Wykorzystanie Placówki", // HEADROCK HAM 3.6 L"Utrzymanie Samoobr.", // HEADROCK HAM 3.6 + L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -6702,6 +6711,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Instruktor zn. mechaniki", L"Instruktor um. dowodzenia", L"Instruktor zn. mat. wybuchowych", + L"Interrogate Prisoners", // added by Flugente TODO.Translate }; STR16 Additional113Text[]= @@ -7470,4 +7480,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //POLISH diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index d9e98ca0..9a2a40b6 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -1642,6 +1642,7 @@ STR16 pAssignmentStrings[] = L"Штат", // operating a strategic facility //Staff L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Отдых", // Resting at a facility //Rest + L"Prison", // Flugente: interrogate prisoners L"Мертв", // dead L"Недеесп.", // abbreviation for incapacitated L"В плену", // Prisoner of war - captured @@ -1727,6 +1728,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Работает с населением", //Facility Staff L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Отдыхает", //Resting at Facility + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Мертв", L"Недеесп.", L"В плену", @@ -1772,6 +1774,7 @@ STR16 pLongAssignmentStrings[] = L"Обучается", L"Работает с населением", //Staff Facility L"Отдыхает в заведении", //Resting at Facility + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Мертв", L"Недееспособен", L"В плену", @@ -2599,6 +2602,7 @@ CHAR16 zHealthStr[][13] = L"ЗДОРОВ", // >= 60 L"СИЛЕН", // >= 75 L"ОТЛИЧНО", // >= 90 + L"CAPTURED", // added by Flugente TODO.Translate }; STR16 gzHiddenHitCountStr[1] = @@ -2911,6 +2915,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3411,6 +3419,7 @@ STR16 pTransactionText[] = L"Снаряжение продано населению", L"Оснащение персонала", // HEADROCK HAM 3.6 //Facility Use L"Содержание ополчения", // HEADROCK HAM 3.6 //Militia upkeep + L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -6657,6 +6666,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Тренер на Механику", L"Тренер на Лидерство", L"Тренер на Взрывчатку", + L"Interrogate Prisoners", // added by Flugente TODO.Translate }; STR16 Additional113Text[]= @@ -7422,4 +7432,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //RUSSIAN diff --git a/Utils/_TaiwaneseText.cpp b/Utils/_TaiwaneseText.cpp index 3a855d20..097429c8 100644 --- a/Utils/_TaiwaneseText.cpp +++ b/Utils/_TaiwaneseText.cpp @@ -1635,13 +1635,14 @@ STR16 pAssignmentStrings[] = L"In Trans", // in transit - abbreviated form L"Repair", // repairing L"Practice", // training themselves - L"Militia", // training a town to revolt + L"Militia", // training a town to revolt L"M.Militia", //training moving militia units // TODO.Translate L"Trainer", // training a teammate L"Student", // being trained by someone else L"Staff", // operating a strategic facility // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Rest", // Resting at a facility // TODO.Translate + L"Prison", // Flugente: interrogate prisoners L"Dead", // dead L"Incap.", // abbreviation for incapacitated L"POW", // Prisoner of war - captured @@ -1727,6 +1728,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Facility Staff", // TODO.Translate L"Eat", // eating at a facility (cantina etc.) // TODO.Translate L"Resting at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Dead", L"Incap.", L"POW", @@ -1772,6 +1774,7 @@ STR16 pLongAssignmentStrings[] = L"Student", L"Staff Facility", // TODO.Translate L"Rest at Facility", // TODO.Translate + L"Interrogate prisoners", // Flugente: interrogate prisoners TODO.Translate L"Dead", L"Incap.", L"POW", @@ -2599,7 +2602,8 @@ CHAR16 zHealthStr[][13] = L"WOUNDED", // >= 45 L"HEALTHY", // >= 60 L"STRONG", // >= 75 - L"EXCELLENT", // >= 90 + L"EXCELLENT", // >= 90 + L"CAPTURED", // added by Flugente TODO.Translate }; STR16 gzHiddenHitCountStr[1] = @@ -2912,6 +2916,10 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // Flugente: weapon cleaning // TODO.Translate L"%s cleaned %s", + + // added by Flugente: decide what to do with prisoners + L"You have no prison for these prisoners, you have to let them go", + L"Yes - Send prisoners to jail No - Let them go", }; //Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. @@ -3412,6 +3420,7 @@ STR16 pTransactionText[] = L"Sold Item(s) to the Locals", L"Facility Use", // HEADROCK HAM 3.6 // TODO.Translate L"Militia upkeep", // HEADROCK HAM 3.6 // TODO.Translate + L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate }; STR16 pTransactionAlternateText[] = @@ -6707,6 +6716,7 @@ STR16 gzFacilityAssignmentStrings[]= L"Trainer Mechanical", L"Trainer Leadership", L"Trainer Explosives", + L"Interrogate Prisoners", // added by Flugente TODO.Translate }; STR16 Additional113Text[]= @@ -7473,4 +7483,13 @@ STR16 szFoodTextStr[]= L"Sectorwide canteen filling not possible, Food System is off!" }; +STR16 szPrisonerTextStr[]= +{ + L"%d prisoners were interrogated.", + L"%d prisoners paid ransom money.", + L"%d prisoners revealed enemy positions.", + L"%d prisoners joined our cause.", + L"Prisoners start a massive riot in %s!", +}; + #endif //TAIWANESE