diff --git a/GameSettings.cpp b/GameSettings.cpp index 32aaee688..0dad6d039 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -2473,6 +2473,12 @@ void LoadSkillTraitsExternalSettings() gSkillTraitValues.bSNTLonerMercBonus = iniReader.ReadInteger("Snitch","LONER_MERC_BONUS", -10, -100, 100); gSkillTraitValues.bSNTSameAssignmentBonus = iniReader.ReadInteger("Snitch","LONER_MERC_BONUS", -20, -100, 100); gSkillTraitValues.bSNTMercOpinionAboutMercTreshold = iniReader.ReadInteger("Snitch","MERC_OPINION_ABOUT_MERC_TRESHOLD", -10, -25, 25); + + gSkillTraitValues.ubSNTPassiveReputationGain = iniReader.ReadInteger("Snitch","PASSIVE_REPUTATION_GAIN", 3, 0, 100); + gSkillTraitValues.ubSNTHearingRangeBonus = iniReader.ReadInteger("Snitch","HEARING_RANGE_BONUS", 1, 0, 100); + + gSkillTraitValues.fSNTPrisonSnitchInterrogationMultiplier = iniReader.ReadFloat("Snitch","PRISON_SNITCH_INTERROGATION_MULTIPLIER", 3.0, 0.0, 10.0); + gSkillTraitValues.fSNTPrisonSnitchGuardStrengthMultiplier = iniReader.ReadFloat("Snitch","PRISON_SNITCH_GUARD_STRENGTH_MULTIPLIER", 3.0, 0.0, 10.0); } //DBrot: Grids void LoadModSettings(){ @@ -3450,6 +3456,7 @@ void LoadMoraleSettings() gMoraleSettings.bValues[MORALE_PLAYER_INACTIVE_DAYS] = iniReader.ReadInteger("Strategic Morale Settings","MORALE_PLAYER_INACTIVE_DAYS", 3, 0, 100); gMoraleSettings.bValues[MORALE_PLAYER_INACTIVE_DAYS_AGGRESSIVE_BONUS] = iniReader.ReadInteger("Strategic Morale Settings","MORALE_PLAYER_INACTIVE_DAYS_AGGRESSIVE_BONUS", -1, -100, 100); gMoraleSettings.bValues[MORALE_PLAYER_INACTIVE_DAYS_PACIFIST_BONUS] = iniReader.ReadInteger("Strategic Morale Settings","MORALE_PLAYER_INACTIVE_DAYS_PACIFIST_BONUS", 2, -100, 100); + gMoraleSettings.bValues[MORALE_PREVENTED_MISBEHAVIOUR] = iniReader.ReadInteger("Strategic Morale Settings","MORALE_PREVENTED_MISBEHAVIOUR", -1, -100, 100); gMoraleSettings.bModifiers[MORALE_MOD_MAX] = iniReader.ReadInteger("Morale Modifiers Settings","MORALE_MOD_MAX", -1, 0, 100); diff --git a/GameSettings.h b/GameSettings.h index de2b5affa..5b813f4f9 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1799,7 +1799,10 @@ typedef struct INT8 bSNTLonerMercBonus; // Bonus to chance if merc is loner INT8 bSNTSameAssignmentBonus; // Bonus to chance if snitch and merc are on the same assignment INT8 bSNTMercOpinionAboutMercTreshold; // For reports "merc hates merc" final chance is proportional to dislike in range between treshold (0%) and -25(100%) - + UINT8 ubSNTPassiveReputationGain; // Reputation gain per day if snitch is happy + UINT8 ubSNTHearingRangeBonus; // Hearing range bonus + FLOAT fSNTPrisonSnitchInterrogationMultiplier; // Undercover snitch interrogation effectivness multiplier (compared to normal interrogation) + FLOAT fSNTPrisonSnitchGuardStrengthMultiplier; // Undercover snitch guarding effectivness multiplier (compared to normal guards) } SKILL_TRAIT_VALUES; // HEADROCK HAM 4: Constants used as coefficients by the various parts of the new CTH system. diff --git a/GameVersion.h b/GameVersion.h index 3032c2945..97550a002 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -21,6 +21,7 @@ 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 SNITCH_TRAIT_EXTENDED 151 // anv: more soldier flags, remembering exposition of snitch #define CAMPAIGNSTATS 150 // Flugente: store campaign statistics #define WALDO_CAN_REPAIR_HELICOPTER 149 // anv: have to refresh Waldo records #define ENCYCLOPEDIA_ITEM_VISIBILITY 148 // Moa: Items discovered during compain have to be saved. @@ -69,7 +70,7 @@ extern CHAR16 zTrackingNumber[16]; #define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes #define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system -#define SAVE_GAME_VERSION CAMPAIGNSTATS +#define SAVE_GAME_VERSION SNITCH_TRAIT_EXTENDED //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Laptop/personnel.cpp b/Laptop/personnel.cpp index 0ace76c7c..35b593343 100644 --- a/Laptop/personnel.cpp +++ b/Laptop/personnel.cpp @@ -8232,6 +8232,24 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve swprintf( apStr, L"" ); swprintf( atStr, gzIMPMinorTraitsHelpTextsSnitch[0]); wcscat( apStr, atStr ); + swprintf( atStr, gzIMPMinorTraitsHelpTextsSnitch[1]); + wcscat( apStr, atStr ); + swprintf( atStr, gzIMPMinorTraitsHelpTextsSnitch[2]); + wcscat( apStr, atStr ); + swprintf( atStr, gzIMPMinorTraitsHelpTextsSnitch[3]); + wcscat( apStr, atStr ); + swprintf( atStr, gzIMPMinorTraitsHelpTextsSnitch[4]); + wcscat( apStr, atStr ); + if( gSkillTraitValues.ubSNTPassiveReputationGain ) + { + swprintf( atStr, gzIMPMinorTraitsHelpTextsSnitch[5],gSkillTraitValues.ubSNTPassiveReputationGain); + wcscat( apStr, atStr ); + } + if( gSkillTraitValues.ubSNTHearingRangeBonus ) + { + swprintf( atStr, gzIMPMinorTraitsHelpTextsSnitch[6],gSkillTraitValues.ubSNTHearingRangeBonus); + wcscat( apStr, atStr ); + } break; } case NO_SKILLTRAIT_NT: diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index b48b71f07..63f4859f7 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -1505,22 +1505,34 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for // Flugente: backgrounds if(guiCurrentSaveGameVersion >= BACKGROUNDS) { - if(guiCurrentSaveGameVersion >= BACKGROUNDS_FIX_UINT8) - { - if ( !FileRead( hFile, &this->usBackground, sizeof(UINT16), &uiNumBytesRead ) ) + if(guiCurrentSaveGameVersion >= BACKGROUNDS_FIX_UINT8) + { + if ( !FileRead( hFile, &this->usBackground, sizeof(UINT16), &uiNumBytesRead ) ) + { + return(FALSE); + } + } + else + { + if ( !FileRead( hFile, &this->usBackground, sizeof(UINT8), &uiNumBytesRead ) ) { return(FALSE); } } - else - { - if ( !FileRead( hFile, &this->usBackground, sizeof(UINT8), &uiNumBytesRead ) ) + } + if(guiCurrentSaveGameVersion >= SNITCH_TRAIT_EXTENDED) + { + //if ( !FileRead( hFile, &this->ubExposedInSector, sizeof(ubExposedInSector), &uiNumBytesRead ) ) + //{ + // return(FALSE); + //} + if ( !FileRead( hFile, &this->ubSnitchExposedCooldown, sizeof(ubSnitchExposedCooldown), &uiNumBytesRead ) ) { return(FALSE); } } } - } + if ( this->uiProfileChecksum != this->GetChecksum() ) { return( FALSE ); @@ -1605,6 +1617,16 @@ BOOLEAN MERCPROFILESTRUCT::Save(HWFILE hFile) return(FALSE); } + //if ( !FileWrite( hFile, &this->ubExposedInSector, sizeof(ubExposedInSector), &uiNumBytesWritten ) ) + //{ + // return(FALSE); + //} + + if ( !FileWrite( hFile, &this->ubSnitchExposedCooldown, sizeof(ubSnitchExposedCooldown), &uiNumBytesWritten ) ) + { + return(FALSE); + } + return TRUE; } @@ -2203,6 +2225,20 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) buffer -= 6; } + if ( guiCurrentSaveGameVersion >= SNITCH_TRAIT_EXTENDED ) + { + numBytesRead = ReadFieldByField(hFile, &this->bSoldierFlagMask2, sizeof(bSoldierFlagMask2), sizeof(INT32), numBytesRead); + } + else + { + this->bSoldierFlagMask2 = 0; + + for(int i = 0; i < sizeof(bSoldierFlagMask2); ++i) + buffer++; + while((buffer%4) > 0) + buffer++; + } + /*if ( guiCurrentSaveGameVersion >= FOOD_CHANGES ) { numBytesRead = ReadFieldByField(hFile, &this->bFoodLevel, sizeof(bFoodLevel), sizeof(INT32), numBytesRead); diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 19e6c81c8..fa479880f 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -65,6 +65,7 @@ #include "Food.h" #include "Tactical Save.h" // added by Flugente #include "Campaign Types.h" // added by Flugente + #include "Strategic Town Loyalty.h" #endif #include #include @@ -194,6 +195,10 @@ INT32 ghMoveBox = -1; INT32 ghFacilityBox = -1; INT32 ghFacilityAssignmentBox = -1; //INT32 ghUpdateBox = -1; +// anv: snitch menus +INT32 ghSnitchBox = -1; +INT32 ghSnitchToggleBox = -1; +INT32 ghSnitchSectorBox = -1; // the x,y position of assignment pop up in tactical INT16 gsAssignmentBoxesX, gsAssignmentBoxesY; @@ -218,6 +223,10 @@ MOUSE_REGION gVehicleMenuRegion[ 20 ]; // HEADROCK HAM 3.6: Facility Menu MOUSE_REGION gFacilityMenuRegion[ MAX_NUM_FACILITY_TYPES ]; MOUSE_REGION gFacilityAssignmentMenuRegion[ NUM_FACILITY_ASSIGNMENTS ]; +// anv: snitch menus +MOUSE_REGION gSnitchMenuRegion[ MAX_SNITCH_MENU_STRING_COUNT ]; +MOUSE_REGION gSnitchToggleMenuRegion[ MAX_SNITCH_TOGGLE_MENU_STRING_COUNT ]; +MOUSE_REGION gSnitchSectorMenuRegion[ MAX_SNITCH_SECTOR_MENU_STRING_COUNT ]; MOUSE_REGION gAssignmentScreenMaskRegion; @@ -226,6 +235,10 @@ BOOLEAN fShowVehicleMenu = FALSE; BOOLEAN fShowRepairMenu = FALSE; BOOLEAN fShowMoveItemMenu = FALSE; BOOLEAN fShownContractMenu = FALSE; +// anv: snitch menus +BOOLEAN fShowSnitchMenu = FALSE; +BOOLEAN fShowSnitchToggleMenu = FALSE; +BOOLEAN fShowSnitchSectorMenu = FALSE; BOOLEAN fFirstClickInAssignmentScreenMask = FALSE; @@ -356,6 +369,9 @@ UINT8 gubFacilityLineForSubmenu; // Which line to highlight in the facility menu #define MIN_CONDITION_TO_FIX_SAM 20 */ +void MakeSoldierKnownAsMercInPrison(SOLDIERTYPE *pSoldier, INT16 sMapX, INT16 sMapY); + +BOOLEAN IsSoldierKnownAsMercInSector(SOLDIERTYPE *pSoldier, INT16 sMapX, INT16 sMapY); // how many points worth of tool kits does the character have? UINT16 ToolKitPoints(SOLDIERTYPE *pSoldier); @@ -437,6 +453,8 @@ void HandleRadioScanInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ); // reset scan flags in all sectors void ClearSectorScanResults(); +void HandleSpreadingPropagandaInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ); + // is the character between secotrs in mvt BOOLEAN CharacterIsBetweenSectors( SOLDIERTYPE *pSoldier ); @@ -470,6 +488,10 @@ void HandleShadingOfLinesForAttributeMenus( void ); // HEADROCK HAM 3.6: Shade Facility Box Lines void HandleShadingOfLinesForFacilityMenu( void ); void HandleShadingOfLinesForFacilityAssignmentMenu( void ); +// anv: snitch menus shading +void HandleShadingOfLinesForSnitchMenu( void ); +void HandleShadingOfLinesForSnitchToggleMenu( void ); +void HandleShadingOfLinesForSnitchSectorMenu( void ); // post message about contract void PostContractMessage( SOLDIERTYPE *pCharacter, INT32 iContract ); @@ -495,7 +517,10 @@ void CreateMoveItemBox( void ); // HEADROCK HAM 3.6: Facility Box. void CreateFacilityBox( void ); void CreateFacilityAssignmentBox( void ); - +// anv: snitch menus boxes +void CreateSnitchBox( void ); +void CreateSnitchToggleBox( void ); +void CreateSnitchSectorBox( void ); /* // get how fast the person regains sleep INT8 GetRegainDueToSleepNeeded( SOLDIERTYPE *pSoldier, INT32 iRateOfReGain ); @@ -530,6 +555,7 @@ UINT8 HandleRepairOfRobotBySoldier( SOLDIERTYPE *pSoldier, UINT8 ubRepairPts, BO BOOLEAN HandleAssignmentExpansionAndHighLightForAssignMenu( SOLDIERTYPE *pSoldier ); BOOLEAN HandleAssignmentExpansionAndHighLightForTrainingMenu( void ); BOOLEAN HandleAssignmentExpansionAndHighLightForFacilityMenu ( void ); // Facility menu and submenu expansion +BOOLEAN HandleAssignmentExpansionAndHighLightForSnitchMenu ( void ); BOOLEAN HandleShowingOfMovementBox( void ); //BOOLEAN HandleShowingOfUpBox( void ); void ReportTrainersTraineesWithoutPartners( void ); @@ -2200,6 +2226,121 @@ INT8 CanCharacterSquad( SOLDIERTYPE *pSoldier, INT8 bSquadValue ) return ( CHARACTER_CAN_JOIN_SQUAD ); } +BOOLEAN CanCharacterSnitch( SOLDIERTYPE *pSoldier ) +{ + AssertNotNIL(pSoldier); + + // has character a snitch trait + if( ProfileHasSkillTrait( pSoldier->ubProfile, SNITCH_NT ) ) + { + return( TRUE ); + } + return( FALSE ); +} + +BOOLEAN CanCharacterSpreadPropaganda( SOLDIERTYPE *pSoldier ) +{ + AssertNotNIL(pSoldier); + + if ( !CanCharacterSnitch( pSoldier ) ) + { + return( FALSE ); + } + // underground propaganda is not allowed (code doesn't support and it's a reasonable enough limitation) + if( pSoldier->bSectorZ != 0 ) + { + return( FALSE ); + } + // is there a town really here + if( GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY ) == BLANK_SECTOR ) + { + return( FALSE ); + } + // it's not a major city (Tixa, Estoni, Orta) + if( !gfTownUsesLoyalty[GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY )] ) + { + return( FALSE ); + } + if( NumEnemiesInAnySector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) ) + { + return( FALSE ); + } + return( TRUE ); +} + +BOOLEAN CanCharacterGatherInformation( SOLDIERTYPE *pSoldier ) +{ + AssertNotNIL(pSoldier); + + if ( !CanCharacterSnitch( pSoldier ) ) + { + return( FALSE ); + } + // underground propaganda is not allowed (code doesn't support and it's a reasonable enough limitation) + if( pSoldier->bSectorZ != 0 ) + { + return( FALSE ); + } + // is there a town really here + if( GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY ) == BLANK_SECTOR ) + { + return( FALSE ); + } + // it's not a major city (Tixa, Estoni, Orta) + if( !gfTownUsesLoyalty[GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY )] ) + { + return( FALSE ); + } + if( NumEnemiesInAnySector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) ) + { + return( FALSE ); + } + return( TRUE ); +} + +BOOLEAN CanCharacterSnitchInPrison( SOLDIERTYPE *pSoldier ) +{ + AssertNotNIL(pSoldier); + + if ( !CanCharacterSnitch( pSoldier ) ) + { + return( FALSE ); + } + if( NumEnemiesInAnySector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) ) + { + return( FALSE ); + } + if( IsSoldierKnownAsMercInSector(pSoldier, pSoldier->sSectorX, pSoldier->sSectorY ) ) + { + return( FALSE ); + } + // check if there's prison in sector + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) + { + // Is this facility here? + if (gFacilityLocations[SECTOR( pSoldier->sSectorX, pSoldier->sSectorY )][cnt].fFacilityHere) + { + // we determine wether this is a prison by checking for usPrisonBaseLimit + if (gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > 0) + { + // Are there any prisoners in this prison? note that there are no underground prisons + if ( !pSoldier->bSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] ); + + UINT8 tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0; + if ( GetNumberOfPrisoners(pSectorInfo, &tmp1, &tmp2, &tmp3, &tmp4) > 0 ) + return TRUE; + } + } + } + } + + + + return( FALSE ); +} + BOOLEAN IsCharacterInTransit( SOLDIERTYPE *pSoldier ) { AssertNotNIL(pSoldier); @@ -2288,6 +2429,8 @@ void UpdateAssignments() // handle training of character in sector HandleRadioScanInSector( sX, sY, bZ ); + HandleSpreadingPropagandaInSector( sX, sY, bZ ); + // handle processing of prisoners HandlePrisonerProcessingInSector( sX, sY, bZ ); @@ -2733,6 +2876,10 @@ UINT32 CalculatePrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) if ( pSoldier->flags.fMercAsleep ) return 0; + // anv: undercover snitches don't count as guards as they don't guard in traditional sense + if ( pSoldier->bAssignment == FACILITY_PRISON_SNITCH ) + return 0; + usValue = 15 * EffectiveExpLevel( pSoldier ) + EffectiveLeadership( pSoldier ) / 2 + 2 * EffectiveStrength( pSoldier, FALSE); if (gGameOptions.fNewTraitSystem) @@ -2753,6 +2900,438 @@ UINT32 CalculatePrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) return( usValue ); } +UINT32 CalculateSnitchGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) +{ + // this is an assignment + UINT32 usValue = 0; + + // for max points we display the maximum amount of prisoners instead + *pusMaxPts = 0; + + if ( pSoldier->flags.fMercAsleep ) + return 0; + + // only undercover snitches count + if ( !pSoldier->bAssignment == FACILITY_PRISON_SNITCH ) + return 0; + + usValue = 15 * EffectiveExpLevel( pSoldier ) + EffectiveLeadership( pSoldier ) / 2 + 2 * EffectiveWisdom( pSoldier ); + + // snitch trait doesn't give bonus, as it's required to take assignment anyway + if (gGameOptions.fNewTraitSystem) + { + usValue += 25 * NUM_SKILL_TRAITS( pSoldier, COVERT_NT ) + 10 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_NT ); + } + else + { + usValue += 25 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_OT ); + } + + if( gMercProfiles[ pSoldier->ubProfile ].bDisability == DEAF ) + { + usValue = usValue/2; + } + // adjust for fatigue + ReducePointsForFatigue( pSoldier, &usValue ); + + // return current snitch pts + return( usValue ); +} + +UINT32 CalculateAllGuardsValueInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) +{ + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); + UINT32 prisonguardvalue = 0; + + // count any mercs found here, and sum up their guard values + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt = 0; + 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 ) + { + UINT16 tmp; + prisonguardvalue += CalculatePrisonGuardValue(pSoldier, &tmp ); + } + } + + // add militia strength + prisonguardvalue += 100 * pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + 150 * pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + 200 * pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + + return( prisonguardvalue ); +} + +UINT32 CalculateAllSnitchesGuardValueInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) +{ + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); + UINT32 prisonguardvalue = 0; + + // count any mercs found here, and sum up their guard values + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt = 0; + 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 ) + { + UINT16 tmp; + prisonguardvalue += CalculateSnitchGuardValue(pSoldier, &tmp ); + } + } + + // add militia strength + prisonguardvalue += 100 * pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + 150 * pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + 200 * pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + + return( prisonguardvalue ); +} + +UINT32 CalculateAllGuardsNumberInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) +{ + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); + UINT8 numprisonguards = 0; + + // count any mercs found here + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt = 0; + 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 ) + { + // anv: undercover snitches don't count as guards as they don't guard in traditional sense + if ( !(pSoldier->bAssignment == FACILITY_PRISON_SNITCH) ) + ++numprisonguards; + } + } + + // add militia strength + numprisonguards += pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + + return( numprisonguards ); +} + +// anv: totally not a copy of CalculateInterrogationValue +UINT32 CalculateSnitchInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) +{ + UINT32 usInterrogationPoints = 0; + + // for max points we display the maximum amount of prisoners instead + *pusMaxPts = 0; + + // no soldier (how does that happen?) or underground -> no interrogation points, as there are no underground prisons + if ( !pSoldier || pSoldier->bSectorZ ) + return 0; + + if ( !CanCharacterSnitchInPrison(pSoldier) ) + return 0; + + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] ); + + UINT8 prisonersspecial = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0; + *pusMaxPts = GetNumberOfPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin ); + + // no prisoners -> no interrogation (this should not happen) + if ( !*pusMaxPts ) + return 0; + + usInterrogationPoints = 50 + 10 * EffectiveExpLevel( pSoldier ) + EffectiveLeadership( pSoldier ) + EffectiveWisdom( pSoldier ); + + // no bonuses for snitch trait, as merc has to have it to take this assignment anyway + if (gGameOptions.fNewTraitSystem) + { + usInterrogationPoints += 10 * NUM_SKILL_TRAITS( pSoldier, COVERT_NT ); + } + + // adjust for friendly value + INT32 friendlyvalue = ( ( EffectiveLeadership( pSoldier ) + EffectiveWisdom( pSoldier ) ) /2 ) * gMercProfiles[pSoldier->ubProfile].usApproachFactor[0]; + + if ( gGameOptions.fNewTraitSystem ) + { + if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE ) + friendlyvalue += 30; + } + + friendlyvalue = (friendlyvalue * (100 + pSoldier->GetBackgroundValue(BG_PERC_APPROACH_FRIENDLY))) / 100; + + usInterrogationPoints *= friendlyvalue; + + //usInterrogationPoints = (usInterrogationPoints * (100 + pSoldier->GetBackgroundValue(BG_PERC_INTERROGATION))) / 100; + + UINT16 performancemodifier = 100; + for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt) + { + // Is this facility here? + if (gFacilityLocations[SECTOR( pSoldier->sSectorX, pSoldier->sSectorY )][cnt].fFacilityHere) + { + // we determine wether this is a snitchable prison by checking for ubStaffLimit + if (gFacilityTypes[cnt].AssignmentData[FAC_PRISON_SNITCH].ubStaffLimit > 0) + { + performancemodifier = gFacilityTypes[cnt].AssignmentData[FAC_PRISON_SNITCH].usPerformance; + break; + } + } + } + + performancemodifier = min(1000, max(10, (UINT32)(gSkillTraitValues.fSNTPrisonSnitchInterrogationMultiplier * performancemodifier) ) ); + + usInterrogationPoints = (usInterrogationPoints * performancemodifier) / (650000); + + // adjust for fatigue + ReducePointsForFatigue( pSoldier, &usInterrogationPoints ); + + // return current repair pts + return( usInterrogationPoints ); +} + +// anv: totally not a copy of CalculatePrisonGuardValue +UINT32 CalculateSnitchPrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) +{ + UINT32 usValue = 0; + + // for max points we display the maximum amount of prisoners instead + *pusMaxPts = 0; + + if ( pSoldier->flags.fMercAsleep ) + return 0; + + if ( !CanCharacterSnitchInPrison(pSoldier) ) + return 0; + + usValue = ( 15 * EffectiveExpLevel( pSoldier ) + 2 * EffectiveLeadership( pSoldier ) + EffectiveWisdom( pSoldier ) ); + + // no bonuses for snitch trait, as merc has to have it to take this assignment anyway + if (gGameOptions.fNewTraitSystem) + { + usValue += 25 * NUM_SKILL_TRAITS( pSoldier, COVERT_NT ) + 10 * HAS_SKILL_TRAIT( pSoldier, STEALTHY_NT ); + } + else + { + usValue += 10 * HAS_SKILL_TRAIT( pSoldier, STEALTHY_OT ); + } + + usValue = (UINT32)(gSkillTraitValues.fSNTPrisonSnitchGuardStrengthMultiplier * usValue); + + // adjust for fatigue + ReducePointsForFatigue( pSoldier, &usValue ); + + // return current repair pts + return( usValue ); +} + +// anv: handle prisoners exposing snitch as a snitch +BOOL HandleSnitchExposition(SOLDIERTYPE *pSoldier) +{ + UINT32 uiSuspicion = 0; + UINT32 uiCoverQuality = 0; + SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] ); + UINT8 prisonersspecial = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0; + UINT16 numprisoners = GetNumberOfPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin ); + + uiCoverQuality = ( 10 * EffectiveExpLevel( pSoldier ) + 2 * EffectiveLeadership( pSoldier ) + EffectiveWisdom( pSoldier ) ) / 4; + + uiSuspicion = 10 + prisonerselite + prisonersspecial; + + // no bonuses for snitch trait, as merc has to have it to take this assignment anyway + if (gGameOptions.fNewTraitSystem) + { + uiCoverQuality += 25 * NUM_SKILL_TRAITS( pSoldier, COVERT_NT ) + 10 * HAS_SKILL_TRAIT( pSoldier, STEALTHY_NT ); + } + else + { + uiCoverQuality += 10 * HAS_SKILL_TRAIT( pSoldier, STEALTHY_OT ); + } + + if( Random( (UINT32)uiSuspicion ) > Random( (UINT32)uiCoverQuality ) ) + { + // yes, he was exposed! + + // remember that he was exposed in this prison/sector, and by how many people (so when they all are processed he can be a snitch again) + MakeSoldierKnownAsMercInPrison( pSoldier, pSoldier->sSectorX, pSoldier->sSectorY ); + + // handle aftermath + + // check if he managed to get out + if( EffectiveWisdom( pSoldier )/10 > PreRandom(100) ) // he noticed being exposed + { + ScreenMsg( FONT_GRAY2, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_FINE_WISDOM ], pSoldier->GetName() ); + } + else if( EffectiveLeadership( pSoldier )/10 > PreRandom(100) ) // he talked his way out + { + ScreenMsg( FONT_GRAY2, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_FINE_LEADERSHIP ], pSoldier->GetName() ); + } + else if( EffectiveExpLevel( pSoldier ) > PreRandom(100) ) // he avoided ambush + { + ScreenMsg( FONT_GRAY2, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_FINE_EXPLEVEL ], pSoldier->GetName() ); + } + else if( CalculateAllGuardsValueInPrison( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) > PreRandom(100) ) // guards prevented assassination + { + ScreenMsg( FONT_GRAY2, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_FINE_GUARDS], pSoldier->GetName() ); + } + else // no, he didn't + { + // calculate how long it will take guards to react + UINT8 ubReactionTime = numprisoners / max(1, CalculateAllGuardsValueInPrison( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ) ); + UINT16 usDamageTaken = 0; + + // decide prisoners' action + switch( PreRandom(4) ) + { + case 0: + // drowning + while( ubReactionTime > 0 && usDamageTaken < pSoldier->bBreathMax ) + { + ubReactionTime--; + if ( gGameOptions.fNewTraitSystem ) + { + if( ( pSoldier->stats.bStrength + NUM_SKILL_TRAITS( pSoldier, ATHLETICS_NT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + else + { + if( ( pSoldier->stats.bStrength + NUM_SKILL_TRAITS( pSoldier, HANDTOHAND_OT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + } + // instead of normal damage take breath damage + //pSoldier->SoldierTakeDamage( 0, 0, 0, usDamageTaken, TAKE_DAMAGE_HANDTOHAND, NOBODY, NOWHERE, 0, TRUE ); + pSoldier->bBreath = max( 0, pSoldier->bBreath - usDamageTaken ); + // he drowned? + if( pSoldier->bBreath = 0 ) + { + // dead + pSoldier->SoldierTakeDamage( 0, 100, 0, 100, TAKE_DAMAGE_HANDTOHAND, NOBODY, NOWHERE, 0, TRUE ); + ScreenMsg( FONT_DKRED, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_DEAD_DROWN], pSoldier->GetName() ); + } + else + { + ScreenMsg( FONT_DKYELLOW, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_WOUNDED_DROWN], pSoldier->GetName() ); + } + break; + case 1: + // beating + while( ubReactionTime > 0 && usDamageTaken < pSoldier->bBreathMax ) + { + ubReactionTime--; + if ( gGameOptions.fNewTraitSystem ) + { + if( ( ( pSoldier->stats.bAgility + pSoldier->stats.bStrength )/2 + NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + else + { + if( ( ( pSoldier->stats.bAgility + pSoldier->stats.bStrength )/2 + NUM_SKILL_TRAITS( pSoldier, MARTIALARTS_OT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + } + // he's dead? + pSoldier->SoldierTakeDamage( 0, usDamageTaken, 0, usDamageTaken, TAKE_DAMAGE_HANDTOHAND, NOBODY, NOWHERE, 0, TRUE ); + if( pSoldier->stats.bLife == 0 ) + { + ScreenMsg( FONT_DKRED, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_DEAD_BEATEN], pSoldier->GetName() ); + } + else + { + ScreenMsg( FONT_DKYELLOW, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_WOUNDED_BEATEN], pSoldier->GetName() ); + } + break; + case 2: + // knifing + while( ubReactionTime > 0 && usDamageTaken < pSoldier->stats.bLife ) + { + ubReactionTime--; + if ( gGameOptions.fNewTraitSystem ) + { + if( ( pSoldier->stats.bAgility + NUM_SKILL_TRAITS( pSoldier, MELEE_NT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + else + { + if( ( pSoldier->stats.bAgility + NUM_SKILL_TRAITS( pSoldier, KNIFING_OT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + } + pSoldier->SoldierTakeDamage( 0, usDamageTaken, 0, usDamageTaken, TAKE_DAMAGE_BLADE, NOBODY, NOWHERE, 0, TRUE ); + // he's dead? + if( pSoldier->stats.bLife == 0 ) + { + ScreenMsg( FONT_DKRED, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_DEAD_KNIFED], pSoldier->GetName() ); + } + else + { + ScreenMsg( FONT_DKYELLOW, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_WOUNDED_KNIFED], pSoldier->GetName() ); + } + break; + case 3: + // strangulation + while( ubReactionTime > 0 && usDamageTaken < pSoldier->bBreathMax ) + { + ubReactionTime--; + if ( gGameOptions.fNewTraitSystem ) + { + if( ( pSoldier->stats.bStrength + NUM_SKILL_TRAITS( pSoldier, BODYBUILDING_NT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + else + { + if( ( pSoldier->stats.bStrength + NUM_SKILL_TRAITS( pSoldier, HANDTOHAND_OT )* 20 ) /2 < Random( 100 ) ) + usDamageTaken += Random(10); + } + } + // instead of normal damage take breath damage + //pSoldier->SoldierTakeDamage( 0, 0, 0, usDamageTaken, TAKE_DAMAGE_HANDTOHAND, NOBODY, NOWHERE, 0, TRUE ); + pSoldier->bBreath = max( 0, pSoldier->bBreath - usDamageTaken ); + // he's strangled? + if( pSoldier->bBreath == 0 ) + { + // dead + pSoldier->SoldierTakeDamage( 0, 100, 0, 100, TAKE_DAMAGE_HANDTOHAND, NOBODY, NOWHERE, 0, TRUE ); + ScreenMsg( FONT_DKRED, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_DEAD_STRANGLED], pSoldier->GetName() ); + } + else + { + ScreenMsg( FONT_DKYELLOW, MSG_INTERFACE, pSnitchPrisonExposedStrings[ SNITCH_PRISON_EXPOSED_WOUNDED_STRANGLED], pSoldier->GetName() ); + } + break; + } + } + } + else + { + // he's fine, carry on + return( FALSE ); + } +} + +void MakeSoldierKnownAsMercInPrison(SOLDIERTYPE *pSoldier, INT16 sMapX, INT16 sMapY) +{ + //SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); + //UINT8 prisonersspecial = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0; + //UINT16 numprisoners = GetNumberOfPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin ); + //gMercProfiles[pSoldier->ubProfile].ubExposedInSector[ SECTOR(sMapX, sMapY)] = numprisoners; + + gMercProfiles[pSoldier->ubProfile].ubSnitchExposedCooldown += 24; +} + +BOOLEAN IsSoldierKnownAsMercInSector(SOLDIERTYPE *pSoldier, INT16 sMapX, INT16 sMapY) +{ + //if( gMercProfiles[pSoldier->ubProfile].ubExposedInSector[ SECTOR(sMapX, sMapY)] ) + //{ + // return( TRUE ); + //} + //else + //{ + // return( FALSE ); + //} + if( gMercProfiles[pSoldier->ubProfile].ubSnitchExposedCooldown > 0 ) + return( TRUE ); + else + return( FALSE ); +} + UINT16 ToolKitPoints(SOLDIERTYPE *pSoldier) { UINT16 usKitpts=0; @@ -4642,6 +5221,8 @@ void FatigueCharacter( SOLDIERTYPE *pSoldier ) break; case TRAIN_BY_OTHER: case TRAIN_SELF: + case SNITCH_SPREAD_PROPAGANDA: + case SNITCH_GATHER_RUMOURS: if ( Chance( 20 ) ) HandleMoraleEvent( pSoldier, MORALE_PACIFIST_GAIN_NONCOMBAT, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); break; @@ -5036,6 +5617,213 @@ void ClearSectorScanResults() } } +// handle snitch spreading propaganda assignment +// totally not a copy of HandleRadioScanInSector +void HandleSpreadingPropagandaInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) +{ + SOLDIERTYPE *pSnitch = NULL; + UINT32 uiCnt=0; + UINT8 ubTownSnitches = 0; + UINT32 uiPropagandaEffect = 0; + + UINT8 ubTownId = GetTownIdForSector( sMapX, sMapY ); + + // if sector not under our control, has enemies in it, or is currently in combat mode + if (!SectorOursAndPeaceful( sMapX, sMapY, bZ )) + return; + + // if not a town, stop + if ( !ubTownId ) + return; + + // we will count the number of snitches in this sector that have spread propaganda successfully this hour. The higher this number, the higher loyalty increase! + // search team for snitches in this sector that performed this assignemnt successfully + for ( uiCnt = 0, pSnitch = MercPtrs[ uiCnt ]; uiCnt <= gTacticalStatus.Team[ MercPtrs[0]->bTeam ].bLastID; uiCnt++, pSnitch++) + { + if( ( pSnitch->bActive && pSnitch->flags.fMercAsleep == FALSE && EnoughTimeOnAssignment( pSnitch ) ) && + ( pSnitch->bAssignment == SNITCH_SPREAD_PROPAGANDA || pSnitch->bAssignment == FACILITY_SPREAD_PROPAGANDA || pSnitch->bAssignment == FACILITY_SPREAD_PROPAGANDA_GLOBAL ) && + ( ( pSnitch->sSectorX == sMapX && pSnitch->sSectorY == sMapY && pSnitch->bSectorZ == bZ ) || pSnitch->bAssignment == FACILITY_SPREAD_PROPAGANDA_GLOBAL ) ) + { + uiPropagandaEffect += GAIN_PTS_PER_LOYALTY_PT * + ( ( 50 + EffectiveLeadership(pSnitch) / 2 ) / 100.0 ) * + ( ( 75 + EffectiveWisdom(pSnitch) / 4 ) / 100.0 ) * + ( ( 75 + ( gMercProfiles[ pSnitch->ubProfile ].usApproachFactor[3] + pSnitch->GetBackgroundValue(BG_PERC_APPROACH_RECRUIT) ) / 4 ) / 100.0 ) ; + if( pSnitch->sFacilityTypeOperated && // Soldier is operating facility + GetSoldierFacilityAssignmentIndex( pSnitch ) != -1) + { + UINT8 ubFacilityType = (UINT8)pSnitch->sFacilityTypeOperated; + UINT8 ubAssignmentType = (UINT8)GetSoldierFacilityAssignmentIndex( pSnitch ); + uiPropagandaEffect *= ( GetFacilityModifier(FACILITY_PERFORMANCE_MOD, ubFacilityType, ubAssignmentType ) / 100.0 ); + } + } + } + + if ( !uiPropagandaEffect ) + return; + + IncrementTownLoyalty( ubTownId, uiPropagandaEffect ); + + // award experience to all snitches + for ( uiCnt = 0, pSnitch = MercPtrs[ uiCnt ]; uiCnt <= gTacticalStatus.Team[ MercPtrs[0]->bTeam ].bLastID; uiCnt++, pSnitch++) + { + if( pSnitch->bActive && ( pSnitch->sSectorX == sMapX ) && ( pSnitch->sSectorY == sMapY ) && ( pSnitch->bSectorZ == bZ) ) + { + if( ( pSnitch->bAssignment == SNITCH_SPREAD_PROPAGANDA ) && ( EnoughTimeOnAssignment( pSnitch ) ) && ( pSnitch->flags.fMercAsleep == FALSE ) ) + { + StatChange( pSnitch, WISDOMAMT, 1, TRUE ); + StatChange( pSnitch, LDRAMT, 2, TRUE ); + StatChange( pSnitch, EXPERAMT, 1, TRUE ); + } + } + } +} + +UINT32 HandlePropagandaBlockingBadNewsInTown( INT8 bTownId, UINT32 uiLoyaltyDecrease ) +{ + SOLDIERTYPE *pSnitch = NULL; + UINT32 uiCnt=0; + FLOAT fPropagandaEffect; + UINT32 uiNewLoyaltyDecrease = uiLoyaltyDecrease; + + // search team for snitches in this sector that performed this assignment successfully + for ( uiCnt = 0, pSnitch = MercPtrs[ uiCnt ]; uiCnt <= gTacticalStatus.Team[ MercPtrs[0]->bTeam ].bLastID; uiCnt++, pSnitch++) + { + if( ( pSnitch->bActive && pSnitch->flags.fMercAsleep == FALSE && EnoughTimeOnAssignment( pSnitch ) ) && + ( pSnitch->bAssignment == SNITCH_SPREAD_PROPAGANDA || pSnitch->bAssignment == FACILITY_SPREAD_PROPAGANDA || pSnitch->bAssignment == FACILITY_SPREAD_PROPAGANDA_GLOBAL ) && + ( GetTownIdForSector( pSnitch->sSectorX, pSnitch->sSectorY ) == bTownId || pSnitch->bAssignment == FACILITY_SPREAD_PROPAGANDA_GLOBAL ) ) + { + fPropagandaEffect = 0.5 * + ( ( 50 + EffectiveLeadership(pSnitch) / 2 ) / 100.0 ) * + ( ( 75 + EffectiveWisdom(pSnitch) / 4 ) / 100.0 ) * + ( ( 75 + ( gMercProfiles[ pSnitch->ubProfile ].usApproachFactor[3] + pSnitch->GetBackgroundValue(BG_PERC_APPROACH_RECRUIT) ) / 4 ) / 100.0 ); + + if( pSnitch->sFacilityTypeOperated && // Soldier is operating facility + GetSoldierFacilityAssignmentIndex( pSnitch ) != -1) + { + UINT8 ubFacilityType = (UINT8)pSnitch->sFacilityTypeOperated; + UINT8 ubAssignmentType = (UINT8)GetSoldierFacilityAssignmentIndex( pSnitch ); + fPropagandaEffect *= ( GetFacilityModifier(FACILITY_PERFORMANCE_MOD, ubFacilityType, ubAssignmentType ) / 100.0 ); + } + + uiNewLoyaltyDecrease *= ( 1.0 - fPropagandaEffect ); + } + } + return uiNewLoyaltyDecrease; +} + +// anv: handle snitch gathering information assignment +// totally not a copy of HandleRadioScanInSector +void HandleGatheringInformationBySoldier( SOLDIERTYPE* pSoldier ) +{ + UINT32 uiCnt=0; + + // if sector not under our control, has enemies in it, or is currently in combat mode + if (!SectorOursAndPeaceful( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ )) + return; + + if( !(pSoldier->bActive) || !EnoughTimeOnAssignment( pSoldier ) || pSoldier->flags.fMercAsleep == TRUE || pSoldier->flags.fBetweenSectors == TRUE ) + { + if( pSoldier->bAssignment != SNITCH_GATHER_RUMOURS && pSoldier->bAssignment != FACILITY_GATHER_RUMOURS ) + { + return; + } + } + + UINT16 usNormalGroupSize = 0; + switch( gGameOptions.ubDifficultyLevel ) + { + case DIF_LEVEL_EASY: + usNormalGroupSize = gGameExternalOptions.ubMinEnemyGroupSizeNovice; + break; + case DIF_LEVEL_MEDIUM: + usNormalGroupSize = gGameExternalOptions.ubMinEnemyGroupSizeExperienced; + break; + case DIF_LEVEL_HARD: + usNormalGroupSize = gGameExternalOptions.ubMinEnemyGroupSizeExpert; + break; + case DIF_LEVEL_INSANE: + default: + usNormalGroupSize = gGameExternalOptions.ubMinEnemyGroupSizeInsane; + break; + } + + usNormalGroupSize *= 2; + + FLOAT fBaseChance = ( EffectiveLeadership(pSoldier) + EffectiveWisdom(pSoldier) + EffectiveExpLevel(pSoldier) * 10 ) / 3000.0; + + if( gMercProfiles[ pSoldier->ubProfile ].bDisability == DEAF ) + { + fBaseChance /= 2.0; + } + + if( pSoldier->sFacilityTypeOperated && // Soldier is operating facility + GetSoldierFacilityAssignmentIndex( pSoldier ) != -1) + { + UINT8 ubFacilityType = (UINT8)pSoldier->sFacilityTypeOperated; + UINT8 ubAssignmentType = (UINT8)GetSoldierFacilityAssignmentIndex( pSoldier ); + fBaseChance *= ( GetFacilityModifier(FACILITY_PERFORMANCE_MOD, ubFacilityType, ubAssignmentType ) / 100.0 ); + } + + FLOAT fDetectSizeFactor = .0; + FLOAT fChance = .0; + FLOAT fBlooperChance = ( ( 100 - EffectiveWisdom( pSoldier ) ) / 100.0 ) * .01 + .01; + + UINT16 usPatrolSize = 0; + UINT16 usDetectedLocations = 0; + + // run through sectors and handle each type in sector + for(INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) + { + for(INT16 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) + { + if( SectorInfo[ SECTOR( sX, sY ) ].uiFlags & ( SF_ASSIGN_NOTICED_ENEMIES_HERE | SF_ASSIGN_NOTICED_ENEMIES_KNOW_NUMBER | SF_ASSIGN_NOTICED_ENEMIES_KNOW_DIRECTION ) ) + { + // no point if we already know about enemies there + continue; + } + if( SectorIsImpassable( SECTOR( sX, sY ) ) ) + { + // only passable sectors matter + continue; + } + usPatrolSize = NumEnemiesInSector( sX, sY ); + + // no enemies + if ( usPatrolSize < 1 ) + { + if( fBlooperChance * 100 > Random(100) ) + { + // enemy patrol detected - except it's not really there! + SectorInfo[ SECTOR( sX, sY ) ].uiFlags |= SF_ASSIGN_NOTICED_ENEMIES_HERE; + usDetectedLocations++; + } + } + else + { + fDetectSizeFactor = sqrt((FLOAT)(usPatrolSize) / (FLOAT)(usNormalGroupSize)); + + fChance = fBaseChance * fDetectSizeFactor; + + if ( fChance * 100 > Random(100) ) + { + // enemy patrol detected + SectorInfo[ SECTOR( sX, sY ) ].uiFlags |= SF_ASSIGN_NOTICED_ENEMIES_HERE; + usDetectedLocations++; + } + } + } + } + + if ( usDetectedLocations ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pSnitchGatheringRumoursResultStrings[SNITCH_GATHERING_RUMOURS_RESULT], pSoldier->GetName(), usDetectedLocations ); + // award experience + StatChange( pSoldier, WISDOMAMT, 1, TRUE ); + StatChange( pSoldier, LDRAMT, 2, TRUE ); + StatChange( pSoldier, EXPERAMT, 3, TRUE ); + } + +} int TownTrainerQsortCompare(const void *pArg1, const void *pArg2) { if (((TOWN_TRAINER_TYPE *)pArg1)->sTrainingPts > ((TOWN_TRAINER_TYPE *)pArg2)->sTrainingPts) @@ -5770,6 +6558,21 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) UINT16 tmp; interrogationpoints += CalculateInterrogationValue(pSoldier, &tmp ); } + else if( ( pSoldier->bAssignment == FACILITY_PRISON_SNITCH ) && CanCharacterSnitchInPrison(pSoldier) && EnoughTimeOnAssignment( pSoldier ) && ( pSoldier->flags.fMercAsleep == FALSE ) ) + { + // first check if he wasn't exposed + if( HandleSnitchExposition(pSoldier) ) + { + //exposition fallout handled in HandleSnitchExposition + } + else + { + ++numinterrogators; + + UINT16 tmp; + interrogationpoints += CalculateSnitchInterrogationValue(pSoldier, &tmp ); + } + } } } @@ -5900,6 +6703,9 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RANSOM], ransomscollected ); } + // remove interrogated prisoners... + ChangeNumberOfPrisoners( pSectorInfo, -interrogatedprisoners[PRISONER_SPECIAL], -interrogatedprisoners[PRISONER_ELITE], -interrogatedprisoners[PRISONER_REGULAR], -interrogatedprisoners[PRISONER_ADMIN], sMapX, sMapY ); + // give experience rewards to the interrogators // total experience to share if ( !oldinterrogationpoints ) @@ -5925,9 +6731,6 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ) } } } - - // remove interrogated prisoners... - ChangeNumberOfPrisoners( pSectorInfo, -interrogatedprisoners[PRISONER_SPECIAL], -interrogatedprisoners[PRISONER_ELITE], -interrogatedprisoners[PRISONER_REGULAR], -interrogatedprisoners[PRISONER_ADMIN] ); } // Flugente: prisons can riot if there aren't enough guards around @@ -6003,25 +6806,15 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) UINT32 prisonguardvalue = 0; // count any interrogators found here, and sum up their interrogation values - SOLDIERTYPE *pSoldier = NULL; - UINT32 uiCnt = 0; - 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; + numprisonguards = CalculateAllGuardsNumberInPrison( sMapX, sMapY, bZ ); + prisonguardvalue = CalculateAllGuardsValueInPrison( sMapX, sMapY, bZ ); - UINT16 tmp; - prisonguardvalue += CalculatePrisonGuardValue(pSoldier, &tmp ); - } + // anv: snitches can only prevent mutiny if there are normal guards to cooperate with + if( !numprisonguards ) + { + prisonguardvalue += CalculateAllSnitchesGuardValueInPrison( sMapX, sMapY, bZ ); } - // add militia strength - prisonguardvalue += 100 * pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + 150 * pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + 200 * pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; - numprisonguards += pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; - if ( !numprisonguards ) fBeginRiot = TRUE; @@ -6051,7 +6844,7 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) pSectorInfo->ubNumAdmins = min(255, pSectorInfo->ubNumAdmins + escapedadmins); // reduce prisoner count! - ChangeNumberOfPrisoners( pSectorInfo, -prisonersspecial, -escapedelites, -escapedregulars, -escapedadmins ); + ChangeNumberOfPrisoners( pSectorInfo, -prisonersspecial, -escapedelites, -escapedregulars, -escapedadmins, sMapX, sMapY ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RIOT], wSectorName ); } @@ -8027,6 +8820,17 @@ void HandleShadingOfLinesForAssignmentMenus( void ) { ShadeStringInBox( ghAssignmentBox, ASSIGN_MENU_FACILITY ); } + // snitch + if( CanCharacterSnitch( pSoldier ) ) + { + // unshade line + UnShadeStringInBox( ghAssignmentBox, ASSIGN_MENU_SNITCH ); + } + else + { + // shade line + ShadeStringInBox( ghAssignmentBox, ASSIGN_MENU_SNITCH ); + } } } @@ -8053,6 +8857,11 @@ void HandleShadingOfLinesForAssignmentMenus( void ) // HEADROCK HAM 3.6: Facility Submenu HandleShadingOfLinesForFacilityAssignmentMenu( ); + // anv: snitch menus shading + HandleShadingOfLinesForSnitchMenu( ); + HandleShadingOfLinesForSnitchToggleMenu( ); + HandleShadingOfLinesForSnitchSectorMenu( ); + return; } @@ -8104,6 +8913,8 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) fShowMoveItemMenu = FALSE; // HEADROCK HAM 3.6: Reset Facility menu fShowFacilityMenu = FALSE; + // anv: reset show snitch menu + fShowSnitchMenu = FALSE; // destroy mask, if needed CreateDestroyScreenMaskForAssignmentAndContractMenus( ); @@ -8120,6 +8931,10 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) // HEADROCK HAM 3.6: Facility Menu, Submenu CreateDestroyMouseRegionForFacilityMenu( ); CreateDestroyMouseRegionsForFacilityAssignmentMenu( ); + // anv: snitch menus + CreateDestroyMouseRegionsForSnitchMenu( ); + CreateDestroyMouseRegionsForSnitchToggleMenu( ); + CreateDestroyMouseRegionsForSnitchSectorMenu( ); // hide all boxes being shown if ( IsBoxShown( ghEpcBox ) ) @@ -8178,7 +8993,25 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) fTeamPanelDirty = TRUE; gfRenderPBInterface = TRUE; } - + // anv: snitch menus + if ( IsBoxShown( ghSnitchBox ) ) + { + HideBox( ghSnitchBox ); + fTeamPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + } + if ( IsBoxShown( ghSnitchToggleBox ) ) + { + HideBox( ghSnitchToggleBox ); + fTeamPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + } + if ( IsBoxShown( ghSnitchSectorBox ) ) + { + HideBox( ghSnitchSectorBox ); + fTeamPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + } // do we really want ot hide this box? if( fShowContractMenu == FALSE ) { @@ -8212,6 +9045,9 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) CreateDestroyMouseRegionsForSquadMenu( TRUE ); CreateDestroyMouseRegionForRepairMenu( ); CreateDestroyMouseRegionForMoveItemMenu(); + CreateDestroyMouseRegionsForSnitchMenu( ); + CreateDestroyMouseRegionsForSnitchToggleMenu( ); + CreateDestroyMouseRegionsForSnitchSectorMenu( ); if( ( ( Menptr[gCharactersList[ bSelectedInfoChar ].usSolID].stats.bLife == 0 )||( Menptr[gCharactersList[bSelectedInfoChar].usSolID].bAssignment == ASSIGNMENT_POW ) ) && ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) ) ) { @@ -8366,7 +9202,58 @@ void DetermineWhichAssignmentMenusCanBeShown( void ) } CreateDestroyMouseRegionsForFacilityAssignmentMenu( ); + // SNITCH menu + if( fShowSnitchMenu == TRUE ) + { + HandleShadingOfLinesForSnitchMenu( ); + ShowBox( ghSnitchBox ); + } + else + { + if( IsBoxShown( ghSnitchBox ) ) + { + HideBox( ghSnitchBox ); + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + // SetRenderFlags(RENDER_FLAG_FULL); + } + } + // SNITCH sub-menu 1 + if( fShowSnitchToggleMenu == TRUE ) + { + HandleShadingOfLinesForSnitchToggleMenu( ); + ShowBox( ghSnitchToggleBox ); + } + else + { + if( IsBoxShown( ghSnitchToggleBox ) ) + { + HideBox( ghSnitchToggleBox ); + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + // SetRenderFlags(RENDER_FLAG_FULL); + } + } + // SNITCH sub-menu 2 + if( fShowSnitchSectorMenu == TRUE ) + { + HandleShadingOfLinesForSnitchSectorMenu( ); + ShowBox( ghSnitchSectorBox ); + } + else + { + if( IsBoxShown( ghSnitchSectorBox ) ) + { + HideBox( ghSnitchSectorBox ); + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + gfRenderPBInterface = TRUE; + // SetRenderFlags(RENDER_FLAG_FULL); + } + } return; } @@ -8470,6 +9357,9 @@ void ClearScreenMaskForMapScreenExit( void ) CreateDestroyMouseRegionForMoveItemMenu(); // HEADROCK HAM 3.6: Facility Menu CreateDestroyMouseRegionForFacilityMenu( ); + CreateDestroyMouseRegionsForSnitchMenu( ); + CreateDestroyMouseRegionsForSnitchToggleMenu( ); + CreateDestroyMouseRegionsForSnitchSectorMenu( ); return; } @@ -9121,7 +10011,323 @@ void CreateDestroyMouseRegionsForSquadMenu( BOOLEAN fPositionBox ) } } +void CreateDestroyMouseRegionsForSnitchMenu( void ) +{ + static BOOLEAN fCreated = FALSE; + UINT32 iCounter = 0; + INT32 iFontHeight = 0; + INT32 iBoxXPosition = 0; + INT32 iBoxYPosition = 0; + SGPPoint pPosition; + INT32 iBoxWidth = 0; + SGPRect pDimensions; + // will create/destroy mouse regions for the map screen assignment main menu + + if( ( fShowSnitchMenu == TRUE ) && ( fCreated == FALSE ) ) + { + // Moa: removed, this missplaces popups when screensize>3. + //if( ( fShowTrainingMenu ) && ( guiCurrentScreen == MAP_SCREEN ) ) + //{ + //SetBoxPosition( ghTrainingBox, TrainPosition ); + //} + // + //HandleShadingOfLinesForTrainingMenu( ); + // + //CheckAndUpdateTacticalAssignmentPopUpPositions( ); + + // grab height of font + iFontHeight = GetLineSpace( ghSnitchBox ) + GetFontHeight( GetBoxFont( ghSnitchBox ) ); + + // get x.y position of box + GetBoxPosition( ghSnitchBox, &pPosition); + + // grab box x and y position + iBoxXPosition = pPosition.iX; + iBoxYPosition = pPosition.iY; + + // get dimensions..mostly for width + GetBoxSize( ghSnitchBox, &pDimensions ); + SetBoxSecondaryShade( ghSnitchBox, FONT_YELLOW ); + + // get width + iBoxWidth = pDimensions.iRight; + + SetCurrentBox( ghSnitchBox ); + + // define regions + for( iCounter = 0; iCounter < GetNumberOfLinesOfTextInBox( ghSnitchBox ); iCounter++ ) + { + // add mouse region for each line of text..and set user data + + + MSYS_DefineRegion( &gSnitchMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghSnitchBox ) + ( iFontHeight ) * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghSnitchBox ) + ( iFontHeight ) * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST - 3 , + MSYS_NO_CURSOR, SnitchMenuMvtCallBack, SnitchMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gSnitchMenuRegion[ iCounter ], 0, iCounter ); + + // Add tooltip for region + if (wcscmp(pSnitchToggleMenuDescStrings[ iCounter ], L"") != 0) + { + SetRegionFastHelpText( &gSnitchMenuRegion[ iCounter ], pSnitchMenuDescStrings[ iCounter ] ); + } + } + + // created + fCreated = TRUE; + + // unhighlight all strings in box + UnHighLightBox( ghSnitchBox ); + + } + else if( ( ( fShowAssignmentMenu == FALSE ) || ( fShowSnitchMenu == FALSE ) ) && ( fCreated == TRUE ) ) + { + // destroy + for( iCounter = 0; iCounter < GetNumberOfLinesOfTextInBox( ghSnitchBox ); iCounter++ ) + { + MSYS_RemoveRegion( &gSnitchMenuRegion[ iCounter ] ); + } + + // stop showing training menu + if( fShowAssignmentMenu == FALSE ) + { + fShowSnitchMenu = FALSE; + } + + RestorePopUpBoxes( ); + + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty= TRUE; + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + HideBox( ghSnitchBox ); + SetRenderFlags( RENDER_FLAG_FULL ); + + // not created + fCreated = FALSE; + + if ( fShowAssignmentMenu ) + { + // remove highlight on the parent menu + UnHighLightBox( ghAssignmentBox ); + } + } +} + +void CreateDestroyMouseRegionsForSnitchToggleMenu( void ) +{ + static BOOLEAN fCreated = FALSE; + UINT32 iCounter = 0; + INT32 iFontHeight = 0; + INT32 iBoxXPosition = 0; + INT32 iBoxYPosition = 0; + SGPPoint pPosition; + INT32 iBoxWidth = 0; + SGPRect pDimensions; + + // will create/destroy mouse regions for the map screen assignment main menu + + if( ( fShowSnitchToggleMenu == TRUE ) && ( fCreated == FALSE ) ) + { + // Moa: removed, this missplaces popups when screensize>3. + //if( ( fShowTrainingMenu ) && ( guiCurrentScreen == MAP_SCREEN ) ) + //{ + //SetBoxPosition( ghTrainingBox, TrainPosition ); + //} + // + //HandleShadingOfLinesForTrainingMenu( ); + // + //CheckAndUpdateTacticalAssignmentPopUpPositions( ); + + // grab height of font + iFontHeight = GetLineSpace( ghSnitchToggleBox ) + GetFontHeight( GetBoxFont( ghSnitchToggleBox ) ); + + // get x.y position of box + GetBoxPosition( ghSnitchToggleBox, &pPosition); + + // grab box x and y position + iBoxXPosition = pPosition.iX; + iBoxYPosition = pPosition.iY; + + // get dimensions..mostly for width + GetBoxSize( ghSnitchToggleBox, &pDimensions ); + SetBoxSecondaryShade( ghSnitchToggleBox, FONT_YELLOW ); + + // get width + iBoxWidth = pDimensions.iRight; + + SetCurrentBox( ghSnitchToggleBox ); + + // define regions + for( iCounter = 0; iCounter < GetNumberOfLinesOfTextInBox( ghSnitchToggleBox ); iCounter++ ) + { + // add mouse region for each line of text..and set user data + + + MSYS_DefineRegion( &gSnitchToggleMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghSnitchToggleBox ) + ( iFontHeight ) * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghSnitchToggleBox ) + ( iFontHeight ) * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST - 3 , + MSYS_NO_CURSOR, SnitchToggleMenuMvtCallBack, SnitchToggleMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gSnitchToggleMenuRegion[ iCounter ], 0, iCounter ); + + // Add tooltip for region + if (wcscmp(pSnitchToggleMenuDescStrings[ iCounter ], L"") != 0) + { + SetRegionFastHelpText( &gSnitchToggleMenuRegion[ iCounter ], pSnitchToggleMenuDescStrings[ iCounter ] ); + } + } + + // created + fCreated = TRUE; + + // unhighlight all strings in box + UnHighLightBox( ghSnitchToggleBox ); + + } + else if( ( ( fShowAssignmentMenu == FALSE ) || ( fShowSnitchMenu == FALSE ) || ( fShowSnitchToggleMenu == FALSE ) ) && ( fCreated == TRUE ) ) + { + // destroy + for( iCounter = 0; iCounter < GetNumberOfLinesOfTextInBox( ghSnitchToggleBox ); iCounter++ ) + { + MSYS_RemoveRegion( &gSnitchToggleMenuRegion[ iCounter ] ); + } + + // stop showing training menu + if( fShowAssignmentMenu == FALSE ) + { + fShowSnitchMenu = FALSE; + } + if( fShowSnitchMenu == FALSE ) + { + fShowSnitchToggleMenu = FALSE; + } + RestorePopUpBoxes( ); + + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty= TRUE; + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + HideBox( ghSnitchToggleBox ); + SetRenderFlags( RENDER_FLAG_FULL ); + + // not created + fCreated = FALSE; + + if ( fShowSnitchMenu ) + { + // remove highlight on the parent menu + UnHighLightBox( ghSnitchBox ); + } + } +} + +void CreateDestroyMouseRegionsForSnitchSectorMenu( void ) +{ + static BOOLEAN fCreated = FALSE; + UINT32 iCounter = 0; + INT32 iFontHeight = 0; + INT32 iBoxXPosition = 0; + INT32 iBoxYPosition = 0; + SGPPoint pPosition; + INT32 iBoxWidth = 0; + SGPRect pDimensions; + + // will create/destroy mouse regions for the map screen assignment main menu + + if( ( fShowSnitchSectorMenu == TRUE ) && ( fCreated == FALSE ) ) + { + // Moa: removed, this missplaces popups when screensize>3. + //if( ( fShowTrainingMenu ) && ( guiCurrentScreen == MAP_SCREEN ) ) + //{ + //SetBoxPosition( ghTrainingBox, TrainPosition ); + //} + // + //HandleShadingOfLinesForTrainingMenu( ); + // + //CheckAndUpdateTacticalAssignmentPopUpPositions( ); + + // grab height of font + iFontHeight = GetLineSpace( ghSnitchSectorBox ) + GetFontHeight( GetBoxFont( ghSnitchSectorBox ) ); + + // get x.y position of box + GetBoxPosition( ghSnitchSectorBox, &pPosition); + + // grab box x and y position + iBoxXPosition = pPosition.iX; + iBoxYPosition = pPosition.iY; + + // get dimensions..mostly for width + GetBoxSize( ghSnitchSectorBox, &pDimensions ); + SetBoxSecondaryShade( ghSnitchSectorBox, FONT_YELLOW ); + + // get width + iBoxWidth = pDimensions.iRight; + + SetCurrentBox( ghSnitchSectorBox ); + + // define regions + for( iCounter = 0; iCounter < GetNumberOfLinesOfTextInBox( ghSnitchSectorBox ); iCounter++ ) + { + // add mouse region for each line of text..and set user data + + + MSYS_DefineRegion( &gSnitchSectorMenuRegion[ iCounter ], ( INT16 )( iBoxXPosition ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghSnitchSectorBox ) + ( iFontHeight ) * iCounter ), ( INT16 )( iBoxXPosition + iBoxWidth ), ( INT16 )( iBoxYPosition + GetTopMarginSize( ghSnitchSectorBox ) + ( iFontHeight ) * ( iCounter + 1 ) ), MSYS_PRIORITY_HIGHEST - 3 , + MSYS_NO_CURSOR, SnitchSectorMenuMvtCallBack, SnitchSectorMenuBtnCallback ); + + // set user defines + MSYS_SetRegionUserData( &gSnitchSectorMenuRegion[ iCounter ], 0, iCounter ); + + // Add tooltip for region + if (wcscmp(pSnitchSectorMenuDescStrings[ iCounter ], L"") != 0) + { + SetRegionFastHelpText( &gSnitchSectorMenuRegion[ iCounter ], pSnitchSectorMenuDescStrings[ iCounter ] ); + } + } + + // created + fCreated = TRUE; + + // unhighlight all strings in box + UnHighLightBox( ghSnitchSectorBox ); + + } + else if( ( ( fShowAssignmentMenu == FALSE ) || ( fShowSnitchMenu == FALSE ) || ( fShowSnitchSectorMenu == FALSE ) ) && ( fCreated == TRUE ) ) + { + // destroy + for( iCounter = 0; iCounter < GetNumberOfLinesOfTextInBox( ghSnitchSectorBox ); iCounter++ ) + { + MSYS_RemoveRegion( &gSnitchSectorMenuRegion[ iCounter ] ); + } + + // stop showing training menu + if( fShowAssignmentMenu == FALSE ) + { + fShowSnitchMenu = FALSE; + } + if( fShowSnitchMenu == FALSE ) + { + fShowSnitchSectorMenu = FALSE; + } + RestorePopUpBoxes( ); + + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty= TRUE; + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + HideBox( ghSnitchSectorBox ); + SetRenderFlags( RENDER_FLAG_FULL ); + + // not created + fCreated = FALSE; + + if ( fShowSnitchMenu ) + { + // remove highlight on the parent menu + UnHighLightBox( ghSnitchBox ); + } + } +} void AssignmentMenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason ) { @@ -9774,8 +10980,80 @@ void SquadMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) return; } +void SnitchMenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason ) +{ + // mvt callback handler for assignment region + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + + if( HandleAssignmentExpansionAndHighLightForSnitchMenu( ) == TRUE ) + { + return; + } + + if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) + { + // highlight string + + // do not highlight current balance + if( GetBoxShadeFlag( ghSnitchBox, iValue ) == FALSE ) + { + // get the string line handle + HighLightBoxLine( ghSnitchBox, iValue ); + } + } + else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) + { + // unhighlight all strings in box + UnHighLightBox( ghSnitchBox ); + } +} +void SnitchToggleMenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason ) +{ + // mvt callback handler for assignment region + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + + if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) + { + // highlight string + + // do not highlight current balance + if( GetBoxShadeFlag( ghSnitchToggleBox, iValue ) == FALSE ) + { + // get the string line handle + HighLightBoxLine( ghSnitchToggleBox, iValue ); + } + } + else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) + { + // unhighlight all strings in box + UnHighLightBox( ghSnitchToggleBox ); + } +} + +void SnitchSectorMenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason ) +{ + // mvt callback handler for assignment region + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + + if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE ) + { + // highlight string + + // do not highlight current balance + if( GetBoxShadeFlag( ghSnitchSectorBox, iValue ) == FALSE ) + { + // get the string line handle + HighLightBoxLine( ghSnitchSectorBox, iValue ); + } + } + else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE ) + { + // unhighlight all strings in box + UnHighLightBox( ghSnitchSectorBox ); + } +} void TrainingMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) { @@ -10047,6 +11325,223 @@ void AttributesMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) }; +void SnitchMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) +{ + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + SOLDIERTYPE* pSoldier = GetSelectedAssignSoldier( FALSE ); + + if( ( fShowSnitchToggleMenu )||( fShowSnitchSectorMenu ) ) + { + return; + } + + if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) + { + if( iValue == SNITCH_MENU_CANCEL ) + { + // cancel, leave + + // stop showing menu + fShowSnitchMenu = FALSE; + + // unhighlight the training box + UnHighLightBox( ghSnitchBox ); + + } + else if( iValue == SNITCH_MENU_TOGGLE ) + { + if ( CanCharacterSnitch( pSoldier ) ) + { + fShowSnitchToggleMenu = TRUE; + DetermineBoxPositions( ); + } + } + else if( iValue == SNITCH_MENU_SECTOR) + { + if ( CanCharacterSnitch( pSoldier ) ) + { + fShowSnitchSectorMenu = TRUE; + DetermineBoxPositions( ); + } + } + // rerender tactical stuff + gfRenderPBInterface = TRUE; + + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + } +} + +void SnitchToggleMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) +{ + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + SOLDIERTYPE* pSoldier = GetSelectedAssignSoldier( FALSE ); + + if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) + { + if( iValue == SNITCH_MENU_TOGGLE_CANCEL ) + { + // cancel, leave + + // stop showing menu + fShowSnitchToggleMenu = FALSE; + + // unhighlight the training box + UnHighLightBox( ghSnitchToggleBox ); + + } + else if( iValue == SNITCH_MENU_TOGGLE_ON ) + { + if ( pSoldier->bSoldierFlagMask2 & SOLDIER_SNITCHING_OFF ) + { + pSoldier->bSoldierFlagMask2 &= ~SOLDIER_SNITCHING_OFF; + fShowSnitchToggleMenu = FALSE; + fShowSnitchMenu = FALSE; + fShowAssignmentMenu = FALSE; + giAssignHighLine = -1; + } + } + else if( iValue == SNITCH_MENU_TOGGLE_OFF ) + { + if ( !(pSoldier->bSoldierFlagMask2 & SOLDIER_SNITCHING_OFF) ) + { + pSoldier->bSoldierFlagMask2 |= SOLDIER_SNITCHING_OFF; + fShowSnitchToggleMenu = FALSE; + fShowSnitchMenu = FALSE; + fShowAssignmentMenu = FALSE; + giAssignHighLine = -1; + + } + } + else if( iValue == SNITCH_MENU_MISBEHAVIOUR_ON ) + { + if ( pSoldier->bSoldierFlagMask2 & SOLDIER_PREVENT_MISBEHAVIOUR_OFF ) + { + pSoldier->bSoldierFlagMask2 &= ~SOLDIER_PREVENT_MISBEHAVIOUR_OFF; + fShowSnitchToggleMenu = FALSE; + fShowSnitchMenu = FALSE; + fShowAssignmentMenu = FALSE; + giAssignHighLine = -1; + } + } + else if( iValue == SNITCH_MENU_MISBEHAVIOUR_OFF) + { + if ( !(pSoldier->bSoldierFlagMask2 & SOLDIER_PREVENT_MISBEHAVIOUR_OFF) ) + { + pSoldier->bSoldierFlagMask2 |= SOLDIER_PREVENT_MISBEHAVIOUR_OFF; + fShowSnitchToggleMenu = FALSE; + fShowSnitchMenu = FALSE; + fShowAssignmentMenu = FALSE; + giAssignHighLine = -1; + + } + } + // rerender tactical stuff + gfRenderPBInterface = TRUE; + + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + } +} + +void SnitchSectorMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) +{ + INT32 iValue = MSYS_GetRegionUserData( pRegion, 0 ); + SOLDIERTYPE* pSoldier = GetSelectedAssignSoldier( FALSE ); + + if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) + { + if( iValue == SNITCH_MENU_SECTOR_CANCEL ) + { + // cancel, leave + + // stop showing menu + fShowSnitchSectorMenu = FALSE; + + // unhighlight the training box + UnHighLightBox( ghSnitchSectorBox ); + + } + else if( iValue == SNITCH_MENU_SECTOR_PROPAGANDA ) + { + if ( CanCharacterSpreadPropaganda( pSoldier ) ) + { + fShowSnitchSectorMenu = FALSE; + + // stop showing menu + fShowAssignmentMenu = FALSE; + giAssignHighLine = -1; + + MakeSoldiersTacticalAnimationReflectAssignment( pSoldier ); + + // set dirty flag + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + + // remove from squad + + if ( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + RemoveCharacterFromSquads( pSoldier ); + ChangeSoldiersAssignment( pSoldier, SNITCH_SPREAD_PROPAGANDA ); + AssignMercToAMovementGroup( pSoldier ); + + // set assignment for group + SetAssignmentForList( ( INT8 ) SNITCH_SPREAD_PROPAGANDA, 0 ); + } + } + else if( iValue == SNITCH_MENU_SECTOR_GATHER_RUMOURS ) + { + if ( CanCharacterGatherInformation( pSoldier ) ) + { + fShowSnitchSectorMenu = FALSE; + + // stop showing menu + fShowAssignmentMenu = FALSE; + giAssignHighLine = -1; + + MakeSoldiersTacticalAnimationReflectAssignment( pSoldier ); + + // set dirty flag + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + + // remove from squad + + if ( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + RemoveCharacterFromSquads( pSoldier ); + ChangeSoldiersAssignment( pSoldier, SNITCH_GATHER_RUMOURS ); + AssignMercToAMovementGroup( pSoldier ); + + // set assignment for group + SetAssignmentForList( ( INT8 ) SNITCH_GATHER_RUMOURS, 0 ); + } + } + // rerender tactical stuff + gfRenderPBInterface = TRUE; + + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + } +} + +void SetShowAllMenus( BOOLEAN fShowMenu ) +{ + //fShowAssignmentMenu = fShowMenu; + fShowSquadMenu = fShowMenu; + fShowTrainingMenu = fShowMenu; + fShowVehicleMenu = fShowMenu; + fShowFacilityMenu = fShowMenu; + fShowRepairMenu = fShowMenu; + fShowMoveItemMenu = fShowMenu; + fShowSnitchMenu = fShowMenu; +} + void AssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) { // btn callback handler for assignment region @@ -10059,7 +11554,7 @@ void AssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) { // HEADROCK HAM 3.6: Added facility menu. - if( ( fShowAttributeMenu )||( fShowTrainingMenu ) || ( fShowRepairMenu ) || fShowMoveItemMenu || ( fShowVehicleMenu ) ||( fShowSquadMenu ) || ( fShowFacilityMenu ) || ( fShowFacilityAssignmentMenu ) ) + if( ( fShowAttributeMenu )||( fShowTrainingMenu ) || ( fShowRepairMenu ) || fShowMoveItemMenu || ( fShowVehicleMenu ) ||( fShowSquadMenu ) || ( fShowFacilityMenu ) || ( fShowFacilityAssignmentMenu ) || ( fShowSnitchMenu ) ) { return; } @@ -10468,6 +11963,26 @@ void AssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) SetAssignmentForList( ( INT8 ) RADIO_SCAN, 0 ); } break; + case( ASSIGN_MENU_SNITCH ): + if ( CanCharacterSnitch( pSoldier ) ) + { + //SetShowAllMenus(FALSE); + + //DisplaySnitchMenu( pSoldier ); + fShowSnitchMenu = TRUE; + //ShowBox( ghSnitchBox ); + DetermineBoxPositions( ); + fShowSquadMenu = FALSE; + fShowVehicleMenu = FALSE; + fShowRepairMenu = FALSE; + fShowTrainingMenu = FALSE; + fShowMoveItemMenu = FALSE; + fShowFacilityMenu = FALSE; + + fTeamPanelDirty = TRUE; + fMapScreenBottomDirty = TRUE; + } + break; case( ASSIGN_MENU_TRAIN ): if( CanCharacterPractise( pSoldier ) ) { @@ -10478,6 +11993,7 @@ void AssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) fShowRepairMenu = FALSE; fShowMoveItemMenu = FALSE; fShowFacilityMenu = FALSE; // HEADROCK HAM 3.6: Facility Menu + fShowSnitchMenu = FALSE; fTeamPanelDirty = TRUE; fMapScreenBottomDirty = TRUE; @@ -10565,7 +12081,7 @@ void AssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) else if( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) { // HEADROCK HAM 3.6: Added facility menu - if( ( fShowAttributeMenu )||( fShowTrainingMenu ) || ( fShowRepairMenu ) || fShowMoveItemMenu || ( fShowVehicleMenu ) ||( fShowSquadMenu ) || ( fShowFacilityMenu ) || ( fShowFacilityAssignmentMenu ) ) + if( ( fShowAttributeMenu )||( fShowTrainingMenu ) || ( fShowRepairMenu ) || fShowMoveItemMenu || ( fShowVehicleMenu ) ||( fShowSquadMenu ) || ( fShowFacilityMenu ) || ( fShowFacilityAssignmentMenu ) || ( fShowSnitchMenu ) ) { fShowAttributeMenu = FALSE; fShowTrainingMenu = FALSE; @@ -10924,6 +12440,201 @@ void CreateMoveItemBox() SetBoxPosition( ghMoveItemBox, pPoint ); } +void CreateSnitchBox() +{ + UINT32 hStringHandle; + UINT32 uiCounter; + + // will create attribute pop up menu for mapscreen assignments + SnitchPosition.iX = OrigSnitchPosition.iX; + + if( giBoxY != 0 ) + { + SnitchPosition.iY = giBoxY + ( ASSIGN_MENU_SNITCH * GetFontHeight( MAP_SCREEN_FONT ) ); + } + + // create basic box + CreatePopUpBox(&ghSnitchBox, SnitchDimensions, SnitchPosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_CENTER_TEXT|POPUP_BOX_FLAG_RESIZE )); + + // which buffer will box render to + SetBoxBuffer(ghSnitchBox, FRAME_BUFFER); + + // border type? + SetBorderType(ghSnitchBox,guiPOPUPBORDERS); + + // background texture + SetBackGroundSurface(ghSnitchBox, guiPOPUPTEX); + + // margin sizes + SetMargins(ghSnitchBox, 6, 6, 4, 4 ); + + // space between lines + SetLineSpace(ghSnitchBox, 2); + + // set current box to this one + SetCurrentBox( ghSnitchBox ); + + + // add strings for box + for(uiCounter=0; uiCounter < MAX_SNITCH_MENU_STRING_COUNT; uiCounter++) + { + AddMonoString(&hStringHandle, pSnitchMenuStrings[uiCounter]); + + // make sure it is unhighlighted + UnHighLightLine(hStringHandle); + } + + // set font type + SetBoxFont(ghSnitchBox, MAP_SCREEN_FONT); + + // set highlight color + SetBoxHighLight(ghSnitchBox, FONT_WHITE); + + // unhighlighted color + SetBoxForeground(ghSnitchBox, FONT_LTGREEN); + + // background color + SetBoxBackground(ghSnitchBox, FONT_BLACK); + + // shaded color..for darkened text + SetBoxShade( ghSnitchBox, FONT_GRAY7 ); + + // resize box to text + ResizeBoxToText( ghSnitchBox ); + + DetermineBoxPositions( ); +} + +void CreateSnitchToggleBox() +{ + UINT32 hStringHandle; + UINT32 uiCounter; + + // will create attribute pop up menu for mapscreen assignments + SnitchTogglePosition.iX = OrigSnitchTogglePosition.iX; + + if( giBoxY != 0 ) + { + SnitchTogglePosition.iY = giBoxY + ( SNITCH_MENU_TOGGLE * GetFontHeight( MAP_SCREEN_FONT ) ); + } + + // create basic box + CreatePopUpBox(&ghSnitchToggleBox, SnitchToggleDimensions, SnitchTogglePosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_CENTER_TEXT|POPUP_BOX_FLAG_RESIZE )); + + // which buffer will box render to + SetBoxBuffer(ghSnitchToggleBox, FRAME_BUFFER); + + // border type? + SetBorderType(ghSnitchToggleBox,guiPOPUPBORDERS); + + // background texture + SetBackGroundSurface(ghSnitchToggleBox, guiPOPUPTEX); + + // margin sizes + SetMargins(ghSnitchToggleBox, 6, 6, 4, 4 ); + + // space between lines + SetLineSpace(ghSnitchToggleBox, 2); + + // set current box to this one + SetCurrentBox( ghSnitchToggleBox ); + + + // add strings for box + for(uiCounter=0; uiCounter < MAX_SNITCH_TOGGLE_MENU_STRING_COUNT; uiCounter++) + { + AddMonoString(&hStringHandle, pSnitchToggleMenuStrings[uiCounter]); + + // make sure it is unhighlighted + UnHighLightLine(hStringHandle); + } + + // set font type + SetBoxFont(ghSnitchToggleBox, MAP_SCREEN_FONT); + + // set highlight color + SetBoxHighLight(ghSnitchToggleBox, FONT_WHITE); + + // unhighlighted color + SetBoxForeground(ghSnitchToggleBox, FONT_LTGREEN); + + // background color + SetBoxBackground(ghSnitchToggleBox, FONT_BLACK); + + // shaded color..for darkened text + SetBoxShade( ghSnitchToggleBox, FONT_GRAY7 ); + + // resize box to text + ResizeBoxToText( ghSnitchToggleBox ); + + DetermineBoxPositions( ); +} + +void CreateSnitchSectorBox() +{ + UINT32 hStringHandle; + UINT32 uiCounter; + + // will create attribute pop up menu for mapscreen assignments + + SnitchSectorPosition.iX = OrigSnitchSectorPosition.iX; + + if( giBoxY != 0 ) + { + SnitchSectorPosition.iY = giBoxY + ( SNITCH_MENU_SECTOR * GetFontHeight( MAP_SCREEN_FONT ) ); + } + // create basic box + CreatePopUpBox(&ghSnitchSectorBox, SnitchSectorDimensions, SnitchSectorPosition, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_CENTER_TEXT|POPUP_BOX_FLAG_RESIZE )); + + // which buffer will box render to + SetBoxBuffer(ghSnitchSectorBox, FRAME_BUFFER); + + // border type? + SetBorderType(ghSnitchSectorBox,guiPOPUPBORDERS); + + // background texture + SetBackGroundSurface(ghSnitchSectorBox, guiPOPUPTEX); + + // margin sizes + SetMargins(ghSnitchSectorBox, 6, 6, 4, 4 ); + + // space between lines + SetLineSpace(ghSnitchSectorBox, 2); + + // set current box to this one + SetCurrentBox( ghSnitchSectorBox ); + + + // add strings for box + for(uiCounter=0; uiCounter < MAX_SNITCH_SECTOR_MENU_STRING_COUNT; uiCounter++) + { + AddMonoString(&hStringHandle, pSnitchSectorMenuStrings[uiCounter]); + + // make sure it is unhighlighted + UnHighLightLine(hStringHandle); + } + + // set font type + SetBoxFont(ghSnitchSectorBox, MAP_SCREEN_FONT); + + // set highlight color + SetBoxHighLight(ghSnitchSectorBox, FONT_WHITE); + + // unhighlighted color + SetBoxForeground(ghSnitchSectorBox, FONT_LTGREEN); + + // background color + SetBoxBackground(ghSnitchSectorBox, FONT_BLACK); + + // shaded color..for darkened text + SetBoxShade( ghSnitchSectorBox, FONT_GRAY7 ); + + // resize box to text + ResizeBoxToText( ghSnitchSectorBox ); + + DetermineBoxPositions( ); +} + void CreateContractBox( SOLDIERTYPE *pCharacter ) { UINT32 hStringHandle; @@ -11354,7 +13065,10 @@ BOOLEAN CreateDestroyAssignmentPopUpBoxes( void ) // HEADROCK HAM 3.6: Facility Menu CreateFacilityBox( ); CreateFacilityAssignmentBox( ); - + // anv: snitch menus + CreateSnitchBox( ); + CreateSnitchToggleBox( ); + CreateSnitchSectorBox( ); UpdateMapScreenAssignmentPositions( ); fCreated = TRUE; @@ -11396,6 +13110,16 @@ BOOLEAN CreateDestroyAssignmentPopUpBoxes( void ) RemoveBox(ghFacilityAssignmentBox); ghFacilityAssignmentBox = -1; + // anv: remove snitch menus + RemoveBox(ghSnitchBox); + ghSnitchBox = -1; + + RemoveBox(ghSnitchToggleBox); + ghSnitchToggleBox = -1; + + RemoveBox(ghSnitchSectorBox); + ghSnitchSectorBox = -1; + fCreated = FALSE; gfIgnoreScrolling = FALSE; RebuildCurrentSquad( ); @@ -11521,6 +13245,39 @@ void DetermineBoxPositions( void ) SetBoxPosition( ghFacilityAssignmentBox, pNewPoint ); } } + + if( ( fShowSnitchMenu == TRUE ) && ( ghSnitchBox != -1 ) ) + { + //CreateDestroyMouseRegionForSnitchMenu( ); + pNewPoint.iY += ( ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_SNITCH ); + + SetBoxPosition( ghSnitchBox, pNewPoint ); + SnitchPosition.iX = pNewPoint.iX; + SnitchPosition.iY = pNewPoint.iY; + OrigSnitchPosition.iY = pNewPoint.iY; + OrigSnitchPosition.iX = pNewPoint.iX; + + ResizeBoxToText( ghSnitchBox ); + + GetBoxSize( ghSnitchBox, &pDimensions ); + GetBoxPosition( ghSnitchBox, &pPoint ); + + if( ( fShowSnitchToggleMenu == TRUE ) && ( ghSnitchToggleBox != -1 ) ) + { + // hang it right beside the training box menu + pNewPoint.iX = pPoint.iX + pDimensions.iRight; + pNewPoint.iY = pPoint.iY; + SetBoxPosition( ghSnitchToggleBox, pNewPoint ); + } + else if( ( fShowSnitchSectorMenu == TRUE ) && ( ghSnitchSectorBox != -1 ) ) + { + // hang it right beside the training box menu + pNewPoint.iX = pPoint.iX + pDimensions.iRight; + pNewPoint.iY = pPoint.iY; + SetBoxPosition( ghSnitchSectorBox, pNewPoint ); + } + } + return; } @@ -12741,11 +14498,83 @@ void SetSoldierAssignment( SOLDIERTYPE *pSoldier, INT8 bAssignment, INT32 iParam SetTimeOfAssignmentChangeForMerc( pSoldier ); } + MakeSoldierKnownAsMercInPrison( pSoldier, pSoldier->sSectorX, pSoldier->sSectorY ); ChangeSoldiersAssignment( pSoldier, FACILITY_INTERROGATE_PRISONERS ); AssignMercToAMovementGroup( pSoldier ); } break; + case( FACILITY_PRISON_SNITCH ): + if( CanCharacterSnitchInPrison(pSoldier) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + // remove from squad + RemoveCharacterFromSquads( pSoldier ); + + // remove from any vehicle + if( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + if ( pSoldier->bAssignment != bAssignment ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, bAssignment ); + AssignMercToAMovementGroup( pSoldier ); + } + break; + case( SNITCH_SPREAD_PROPAGANDA ): + case( FACILITY_SPREAD_PROPAGANDA ): + case( FACILITY_SPREAD_PROPAGANDA_GLOBAL ): + if( CanCharacterSpreadPropaganda(pSoldier) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + + // remove from squad + RemoveCharacterFromSquads( pSoldier ); + + // remove from any vehicle + if( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + if ( pSoldier->bAssignment != bAssignment ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, bAssignment ); + AssignMercToAMovementGroup( pSoldier ); + } + break; + case( SNITCH_GATHER_RUMOURS ): + case( FACILITY_GATHER_RUMOURS ): + if( CanCharacterGatherInformation(pSoldier) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + + // remove from squad + RemoveCharacterFromSquads( pSoldier ); + + // remove from any vehicle + if( pSoldier->bOldAssignment == VEHICLE ) + { + TakeSoldierOutOfVehicle( pSoldier ); + } + + if ( pSoldier->bAssignment != bAssignment ) + { + SetTimeOfAssignmentChangeForMerc( pSoldier ); + } + + ChangeSoldiersAssignment( pSoldier, bAssignment ); + AssignMercToAMovementGroup( pSoldier ); + } + break; case( VEHICLE ): if( CanCharacterVehicle( pSoldier ) && IsThisVehicleAccessibleToSoldier( pSoldier, iParam1 ) ) { @@ -12956,7 +14785,12 @@ BOOLEAN HandleAssignmentExpansionAndHighLightForAssignMenu( SOLDIERTYPE *pSoldie HighLightBoxLine( ghAssignmentBox, ASSIGN_MENU_FACILITY ); return( TRUE ); } - + else if( fShowSnitchMenu ) + { + // highlight the snitch line in the previous menu + HighLightBoxLine( ghSnitchBox, ASSIGN_MENU_SNITCH ); + return( TRUE ); + } return( FALSE ); } @@ -12986,7 +14820,23 @@ BOOLEAN HandleAssignmentExpansionAndHighLightForTrainingMenu( void ) return( FALSE ); } +BOOLEAN HandleAssignmentExpansionAndHighLightForSnitchMenu( void ) +{ + if( fShowSnitchToggleMenu ) + { + // highlight the snitch line in the previous menu + HighLightBoxLine( ghSnitchBox, SNITCH_MENU_TOGGLE ); + return( TRUE ); + } + else if( fShowSnitchSectorMenu ) + { + // highlight the snitch line in the previous menu + HighLightBoxLine( ghSnitchBox, SNITCH_MENU_SECTOR ); + return( TRUE ); + } + return( FALSE ); +} /* BOOLEAN HandleShowingOfUpBox( void ) @@ -13198,6 +15048,104 @@ void HandleShadingOfLinesForAttributeMenus( void ) return; } +void HandleShadingOfLinesForSnitchMenu( void ) +{ + SOLDIERTYPE *pSoldier = NULL; + + // check if valid + if( ( fShowSnitchMenu == FALSE ) || ( ghSnitchBox == - 1 ) ) + { + return; + } + + pSoldier = GetSelectedAssignSoldier( FALSE ); + + // can character snitch? + if( CanCharacterSnitch( pSoldier ) == TRUE ) + { + UnShadeStringInBox( ghSnitchBox, SNITCH_MENU_TOGGLE); + + if( CanCharacterSpreadPropaganda( pSoldier ) || CanCharacterGatherInformation( pSoldier ) ) + { + UnShadeStringInBox( ghSnitchBox, SNITCH_MENU_SECTOR ); + UnSecondaryShadeStringInBox( ghSnitchBox, SNITCH_MENU_SECTOR ); + } + else + { + ShadeStringInBox( ghSnitchBox, SNITCH_MENU_SECTOR ); + UnSecondaryShadeStringInBox( ghSnitchBox, SNITCH_MENU_SECTOR ); + } + } + else + { + // shouldn't even get that far + ShadeStringInBox( ghSnitchBox, SNITCH_MENU_TOGGLE ); + ShadeStringInBox( ghSnitchBox, SNITCH_MENU_SECTOR ); + } + //UnSecondaryShadeStringInBox( ghTrainingBox, TRAIN_MENU_TOWN ); + return; +} + +void HandleShadingOfLinesForSnitchToggleMenu( void ) +{ + SOLDIERTYPE *pSoldier = NULL; + + // check if valid + if( ( fShowSnitchToggleMenu == FALSE ) || ( ghSnitchToggleBox == - 1 ) ) + { + return; + } + + pSoldier = GetSelectedAssignSoldier( FALSE ); + + if( pSoldier->bSoldierFlagMask2 & SOLDIER_SNITCHING_OFF ) + { + UnShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_TOGGLE_ON ); + ShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_TOGGLE_OFF ); + } + else + { + ShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_TOGGLE_ON ); + UnShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_TOGGLE_OFF ); + } + + if( pSoldier->bSoldierFlagMask2 & SOLDIER_PREVENT_MISBEHAVIOUR_OFF ) + { + UnShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_MISBEHAVIOUR_ON ); + ShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_MISBEHAVIOUR_OFF ); + } + else + { + ShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_MISBEHAVIOUR_ON ); + UnShadeStringInBox( ghSnitchToggleBox, SNITCH_MENU_MISBEHAVIOUR_OFF ); + } + return; +} + +void HandleShadingOfLinesForSnitchSectorMenu( void ) +{ + SOLDIERTYPE *pSoldier = NULL; + + // check if valid + if( ( fShowSnitchSectorMenu == FALSE ) || ( ghSnitchSectorBox == - 1 ) ) + { + return; + } + + pSoldier = GetSelectedAssignSoldier( FALSE ); + + if( !CanCharacterSpreadPropaganda(pSoldier) ) + { + ShadeStringInBox( ghSnitchSectorBox, SNITCH_MENU_SECTOR_PROPAGANDA ); + } + + if( !CanCharacterGatherInformation(pSoldier) ) + { + ShadeStringInBox( ghSnitchSectorBox, SNITCH_MENU_SECTOR_GATHER_RUMOURS ); + } + + return; +} /*void ResetAssignmentsForAllSoldiersInSectorWhoAreTrainingTown( SOLDIERTYPE *pSoldier ) { @@ -13823,11 +15771,26 @@ void ReEvaluateEveryonesNothingToDo() break; case RADIO_SCAN: - fNothingToDo = !pSoldier->CanUseRadio(); + fNothingToDo = !(pSoldier->CanUseRadio()); break; case FACILITY_INTERROGATE_PRISONERS: - fNothingToDo = !pSoldier->CanProcessPrisoners(); + fNothingToDo = !(pSoldier->CanProcessPrisoners()); + break; + + case FACILITY_PRISON_SNITCH: + fNothingToDo = !CanCharacterSnitchInPrison(pSoldier); + break; + + case FACILITY_SPREAD_PROPAGANDA: + case FACILITY_SPREAD_PROPAGANDA_GLOBAL: + case SNITCH_SPREAD_PROPAGANDA: + fNothingToDo = !CanCharacterSpreadPropaganda(pSoldier); + break; + + case FACILITY_GATHER_RUMOURS: + case SNITCH_GATHER_RUMOURS: + fNothingToDo = !CanCharacterGatherInformation(pSoldier); break; case TRAIN_TOWN: @@ -14063,7 +16026,26 @@ void SetAssignmentForList( INT8 bAssignment, INT8 bParam ) fItWorked = TRUE; } break; - + + case SNITCH_SPREAD_PROPAGANDA: + if( CanCharacterSpreadPropaganda( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, SNITCH_SPREAD_PROPAGANDA, bParam, 0,0 ); + fItWorked = TRUE; + } + break; + + case SNITCH_GATHER_RUMOURS: + if( CanCharacterGatherInformation( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, SNITCH_GATHER_RUMOURS, bParam, 0,0 ); + fItWorked = TRUE; + } + break; + + // HEADROCK HAM 3.6: Facility Staffing case FACILITY_STAFF: if ( CanCharacterFacility( pSoldier, bParam, FAC_STAFF ) ) @@ -14079,12 +16061,46 @@ void SetAssignmentForList( INT8 bAssignment, INT8 bParam ) if ( CanCharacterFacility( pSoldier, bParam, FAC_INTERROGATE_PRISONERS ) && pSoldier->CanProcessPrisoners() ) { pSoldier->bOldAssignment = pSoldier->bAssignment; + MakeSoldierKnownAsMercInPrison( pSoldier, pSoldier->sSectorX, pSoldier->sSectorY ); ChangeSoldiersAssignment( pSoldier, FACILITY_INTERROGATE_PRISONERS ); pSoldier->sFacilityTypeOperated = bParam; fItWorked = TRUE; } break; + case FACILITY_PRISON_SNITCH: + if( CanCharacterFacility( pSoldier, bParam, FAC_PRISON_SNITCH ) && CanCharacterSnitchInPrison( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, FACILITY_PRISON_SNITCH, bParam, 0,0 ); + fItWorked = TRUE; + } + break; + + case FACILITY_SPREAD_PROPAGANDA: + if( CanCharacterFacility( pSoldier, bParam, FAC_SPREAD_PROPAGANDA ) && CanCharacterSpreadPropaganda( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, FACILITY_SPREAD_PROPAGANDA, bParam, 0,0 ); + fItWorked = TRUE; + } + break; + case FACILITY_SPREAD_PROPAGANDA_GLOBAL: + if( CanCharacterFacility( pSoldier, bParam, FAC_SPREAD_PROPAGANDA_GLOBAL ) && CanCharacterSpreadPropaganda( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, FACILITY_SPREAD_PROPAGANDA_GLOBAL, bParam, 0,0 ); + fItWorked = TRUE; + } + break; + case FACILITY_GATHER_RUMOURS: + if( CanCharacterFacility( pSoldier, bParam, FAC_GATHER_RUMOURS ) && CanCharacterGatherInformation( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, FACILITY_GATHER_RUMOURS, bParam, 0,0 ); + fItWorked = TRUE; + } + break; case( SQUAD_1 ): case( SQUAD_2 ): case( SQUAD_3 ): @@ -16030,6 +18046,15 @@ BOOLEAN DisplayFacilityAssignmentMenu( SOLDIERTYPE *pSoldier, UINT8 ubFacilityTy AddMonoString((UINT32 *)&hStringHandle, gzFacilityAssignmentStrings[ FAC_REPAIR_ROBOT ] ); } } + else if ( iCounter == FAC_PRISON_SNITCH || iCounter == FAC_SPREAD_PROPAGANDA || iCounter == FAC_SPREAD_PROPAGANDA_GLOBAL || iCounter == FAC_GATHER_RUMOURS ) + { + // anv: is character a snitch? + if( CanCharacterSnitch( pSoldier ) ) + { + // yeah, show snitch line then + AddMonoString((UINT32 *)&hStringHandle, gzFacilityAssignmentStrings[ iCounter ] ); + } + } else { AddMonoString((UINT32 *)&hStringHandle, gzFacilityAssignmentStrings[ iCounter ]); @@ -16558,6 +18583,27 @@ BOOLEAN CanCharacterFacility( SOLDIERTYPE *pSoldier, UINT8 ubFacilityType, UINT8 break; } } + if ( ubAssignmentType == FAC_PRISON_SNITCH ) + { + if( !CanCharacterSnitchInPrison(pSoldier) ) + { + return( FALSE ); + } + } + if ( ubAssignmentType == FAC_SPREAD_PROPAGANDA || ubAssignmentType == FAC_SPREAD_PROPAGANDA_GLOBAL ) + { + if( !CanCharacterSpreadPropaganda(pSoldier) ) + { + return( FALSE ); + } + } + if ( ubAssignmentType == FAC_GATHER_RUMOURS ) + { + if( !CanCharacterGatherInformation(pSoldier) ) + { + return( FALSE ); + } + } // If we've reached this, then all is well. return( TRUE ); @@ -16911,6 +18957,22 @@ BOOLEAN CanCharacterFacilityWithErrorReport( SOLDIERTYPE *pSoldier, UINT8 ubFaci } } + if( ubAssignmentType == FAC_PRISON_SNITCH ) + { + if( IsSoldierKnownAsMercInSector( pSoldier, pSoldier->sSectorX, pSoldier->sSectorY ) ) + { + //swprintf( sString, gzFacilityErrorMessage[32], pSoldier->GetName() ); + swprintf( sString, gzFacilityErrorMessage[33], pSoldier->GetName(), gMercProfiles[pSoldier->ubProfile].ubSnitchExposedCooldown ); + DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL ); + return( FALSE ); + } + else if( !CanCharacterSnitchInPrison(pSoldier) ) + { + return( FALSE ); + } + + } + // If we've reached this, then all is well. return( TRUE ); @@ -17235,6 +19297,11 @@ void CreateDestroyMouseRegionsForFacilityAssignmentMenu( void ) uiMenuLine++; } } + else if( ( iCounter == FAC_PRISON_SNITCH || iCounter == FAC_SPREAD_PROPAGANDA || iCounter == FAC_SPREAD_PROPAGANDA_GLOBAL || iCounter == FAC_GATHER_RUMOURS ) && + !CanCharacterSnitch( pSoldier )) + { + // anv: don't show line then + } else { // add mouse region for each remaining assignment type @@ -17550,8 +19617,21 @@ void FacilityAssignmentMenuBtnCallback ( MOUSE_REGION * pRegion, INT32 iReason ) ChangeSoldiersAssignment( pSoldier, TRAIN_TEAMMATE ); break; case FAC_INTERROGATE_PRISONERS: + MakeSoldierKnownAsMercInPrison( pSoldier, pSoldier->sSectorX, pSoldier->sSectorY ); ChangeSoldiersAssignment( pSoldier, FACILITY_INTERROGATE_PRISONERS ); break; + case FAC_PRISON_SNITCH: + ChangeSoldiersAssignment( pSoldier, FACILITY_PRISON_SNITCH ); + break; + case FAC_SPREAD_PROPAGANDA: + ChangeSoldiersAssignment( pSoldier, FACILITY_SPREAD_PROPAGANDA ); + break; + case FAC_SPREAD_PROPAGANDA_GLOBAL: + ChangeSoldiersAssignment( pSoldier, FACILITY_SPREAD_PROPAGANDA_GLOBAL ); + break; + case FAC_GATHER_RUMOURS: + ChangeSoldiersAssignment( pSoldier, FACILITY_GATHER_RUMOURS ); + 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 @@ -17692,6 +19772,28 @@ void HandleShadingOfLinesForFacilityAssignmentMenu( void ) } iNumLine++; } + else if ( iCounter == FAC_PRISON_SNITCH || iCounter == FAC_SPREAD_PROPAGANDA || iCounter == FAC_SPREAD_PROPAGANDA_GLOBAL || iCounter == FAC_GATHER_RUMOURS ) + { + // is character a snitch + if ( CanCharacterSnitch( pSoldier ) ) + { + if ( CanCharacterFacility( pSoldier, ubFacilityType, iCounter ) ) + { + UnShadeStringInBox( ghFacilityAssignmentBox, iNumLine ); + UnSecondaryShadeStringInBox( ghFacilityAssignmentBox, iNumLine ); + } + else + { + UnShadeStringInBox( ghFacilityAssignmentBox, iNumLine ); + SecondaryShadeStringInBox( ghFacilityAssignmentBox, iNumLine ); + } + iNumLine++; + } + else + { + // Line won't appear in the menu, so don't bother shading it. + } + } else if ( !BasicCanCharacterFacility( pSoldier ) ) { // Character cannot perform facility work at all. This shouldn't happen, actually. diff --git a/Strategic/Assignments.h b/Strategic/Assignments.h index 0e1f78666..2ffd4216b 100644 --- a/Strategic/Assignments.h +++ b/Strategic/Assignments.h @@ -71,10 +71,44 @@ enum ASSIGNMENT_UNCONCIOUS, // unused ASSIGNMENT_POW, ASSIGNMENT_HOSPITAL, - ASSIGNMENT_EMPTY, + ASSIGNMENT_EMPTY, + FACILITY_PRISON_SNITCH, + FACILITY_SPREAD_PROPAGANDA, + FACILITY_SPREAD_PROPAGANDA_GLOBAL, + FACILITY_GATHER_RUMOURS, + SNITCH_SPREAD_PROPAGANDA, + SNITCH_GATHER_RUMOURS, NUM_ASSIGNMENTS, }; +// strings for snitch exposition +enum +{ + SNITCH_PRISON_EXPOSED_FINE_WISDOM, + SNITCH_PRISON_EXPOSED_FINE_LEADERSHIP, + SNITCH_PRISON_EXPOSED_FINE_EXPLEVEL, + SNITCH_PRISON_EXPOSED_FINE_GUARDS, + + SNITCH_PRISON_EXPOSED_WOUNDED_DROWN, + SNITCH_PRISON_EXPOSED_WOUNDED_BEATEN, + SNITCH_PRISON_EXPOSED_WOUNDED_KNIFED, + SNITCH_PRISON_EXPOSED_WOUNDED_STRANGLED, + + SNITCH_PRISON_EXPOSED_DEAD_DROWN, + SNITCH_PRISON_EXPOSED_DEAD_BEATEN, + SNITCH_PRISON_EXPOSED_DEAD_KNIFED, + SNITCH_PRISON_EXPOSED_DEAD_STRANGLED, + + NUM_SNITCH_PRISON_EXPOSED, +}; + +// strings for snitch gathering rumours +enum +{ + SNITCH_GATHERING_RUMOURS_RESULT, + NUM_SNITCH_GATHERING_RUMOURS_RESULT, +}; + #define NO_ASSIGNMENT 127 //used when no pSoldier->ubDesiredSquad // Train stats defines (must match ATTRIB_MENU_ defines, and pAttributeMenuStrings ) @@ -150,6 +184,9 @@ BOOLEAN CanCharacterVehicle( SOLDIERTYPE *pCharacter ); // can character be added to squad INT8 CanCharacterSquad( SOLDIERTYPE *pCharacter, INT8 bSquadValue ); +// can character snitch +BOOLEAN CanCharacterSnitch( SOLDIERTYPE *pCharacter ); + // if merc could train militia here, do they have sufficient loyalty? BOOLEAN DoesSectorMercIsInHaveSufficientLoyaltyToTrainMilitia( SOLDIERTYPE *pSoldier ); BOOLEAN DoesTownHaveRatingToTrainMilitia( INT8 bTownId ); @@ -196,6 +233,8 @@ UINT8 CalculateRepairPointsForRepairman(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts UINT32 CalculateInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ); UINT32 CalculatePrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ); +UINT32 CalculateSnitchInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ); + // Flugente: determine max items we can move, and the sector distance // get bonus tarining pts due to an instructor for this student @@ -230,6 +269,10 @@ extern INT32 ghMoveBox; extern INT32 ghFacilityBox; extern INT32 ghFacilityAssignmentBox; //extern INT32 ghUpdateBox; +// anv: snitch menus +extern INT32 ghSnitchBox; +extern INT32 ghSnitchToggleBox; +extern INT32 ghSnitchSectorBox; extern MOUSE_REGION gAssignmentScreenMaskRegion; @@ -301,6 +344,17 @@ void CreateDestroyMouseRegionsForFacilityAssignmentMenu( void ); void FacilityAssignmentMenuMvtCallBack( MOUSE_REGION * pRegion, INT32 iReason ); void FacilityAssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); +// anv: snitch menus +void CreateDestroyMouseRegionsForSnitchMenu( void ); +void SnitchMenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason ); +void SnitchMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); +void CreateDestroyMouseRegionsForSnitchToggleMenu( void ); +void SnitchToggleMenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason ); +void SnitchToggleMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); +void CreateDestroyMouseRegionsForSnitchSectorMenu( void ); +void SnitchSectorMenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason ); +void SnitchSectorMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); + // contract menu void CreateDestroyMouseRegionsForContractMenu( void ); void ContractMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ); @@ -392,6 +446,11 @@ extern SOLDIERTYPE *gpFacilityStaffer; // SANDRO - function to award record points for militia training void RecordNumMilitiaTrainedForMercs( INT16 sX, INT16 sY, INT8 sZ, UINT8 ubMilitiaTrained, BOOLEAN fMobile ); +// anv: decrease town loyalty hits +UINT32 HandlePropagandaBlockingBadNewsInTown( INT8 bTownId, UINT32 uiLoyaltyDecrease ); + +void HandleGatheringInformationBySoldier( SOLDIERTYPE* pSoldier ); + #endif diff --git a/Strategic/Campaign Types.h b/Strategic/Campaign Types.h index b4005c62c..7cb761d44 100644 --- a/Strategic/Campaign Types.h +++ b/Strategic/Campaign Types.h @@ -187,6 +187,10 @@ enum FAC_TRAINER_LEADERSHIP, FAC_TRAINER_EXPLOSIVES, FAC_INTERROGATE_PRISONERS, + FAC_PRISON_SNITCH, + FAC_SPREAD_PROPAGANDA, + FAC_SPREAD_PROPAGANDA_GLOBAL, + FAC_GATHER_RUMOURS, NUM_FACILITY_ASSIGNMENTS, }; diff --git a/Strategic/Facilities.cpp b/Strategic/Facilities.cpp index 9cd68014b..8eaef3f68 100644 --- a/Strategic/Facilities.cpp +++ b/Strategic/Facilities.cpp @@ -769,7 +769,7 @@ INT8 GetSoldierFacilityAssignmentIndex( SOLDIERTYPE *pSoldier ) bAssignment == IN_TRANSIT || bAssignment == TRAIN_TOWN || bAssignment == TRAIN_MOBILE || - bAssignment > FACILITY_REST ) + ( bAssignment > FACILITY_REST && ( bAssignment < FACILITY_PRISON_SNITCH || bAssignment > FACILITY_GATHER_RUMOURS ) )) { // Soldier is performing a distinctly NON-FACILITY assignment. return (-1); @@ -921,6 +921,18 @@ INT8 GetSoldierFacilityAssignmentIndex( SOLDIERTYPE *pSoldier ) case FACILITY_INTERROGATE_PRISONERS: bAssignmentIndex = FAC_INTERROGATE_PRISONERS; break; + case FACILITY_PRISON_SNITCH: + bAssignmentIndex = FAC_PRISON_SNITCH; + break; + case FACILITY_SPREAD_PROPAGANDA: + bAssignmentIndex = FAC_SPREAD_PROPAGANDA; + break; + case FACILITY_SPREAD_PROPAGANDA_GLOBAL: + bAssignmentIndex = FAC_SPREAD_PROPAGANDA; + break; + case FACILITY_GATHER_RUMOURS: + bAssignmentIndex = FAC_GATHER_RUMOURS; + break; default: bAssignmentIndex = -1; break; diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index d0a7b47d0..19587c2c6 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -39,6 +39,7 @@ void HourlyQuestUpdate(); void HourlyLarryUpdate(); void HourlyStealUpdate(); // Flugente: certain characters might steal equipment (backgrounds) +void HourlySnitchUpdate(); // anv: decreasing cooldown after exposition extern INT32 GetCurrentBalance( void ); extern void PayOffSkyriderDebtIfAny( ); @@ -54,6 +55,8 @@ void HourlyCheckIfSlayAloneSoHeCanLeave(); void HourlyHelicopterRepair(); #endif +void HourlyGatheringInformation(); + void UpdateRegenCounters( void ); void HandleMinuteUpdate() @@ -113,6 +116,10 @@ CHAR16 zString[128]; HourlyStealUpdate(); + HourlySnitchUpdate(); + + HourlyGatheringInformation(); + #ifdef JA2UB // no UB #else @@ -334,6 +341,7 @@ UINT16 LarryItems[ NUM_LARRY_ITEMS ][ 3 ] = void HourlyLarryUpdate() { SOLDIERTYPE * pSoldier = NULL; + SOLDIERTYPE * pOtherSoldier = NULL; INT8 bSlot = NO_SLOT, bBoozeSlot; INT8 bLarryItemLoop; UINT16 usTemptation = 0; @@ -386,6 +394,41 @@ void HourlyLarryUpdate() if ( usTemptation > 0 ) { + + // anv: snitches stop mercs from getting wasted + for( INT32 cnt2 = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; cnt2 <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++cnt2 ) + { + pOtherSoldier = MercPtrs[ cnt ]; + // note - snitches stop others, but can get wasted themselves (if they have drug use specifically set in background...) + if( pOtherSoldier && !pOtherSoldier->flags.fBetweenSectors && pOtherSoldier->bActive && pOtherSoldier->bInSector && !pOtherSoldier->flags.fMercAsleep && pSoldier->ubProfile != pOtherSoldier->ubProfile ) + { + if ( ProfileHasSkillTrait( pOtherSoldier->ubProfile, SNITCH_NT ) && !( pSoldier->bSoldierFlagMask2 & SOLDIER_PREVENT_MISBEHAVIOUR_OFF ) ) + { + if( pSoldier->sSectorX == pOtherSoldier->sSectorX && pSoldier->sSectorY == pOtherSoldier->sSectorY && pSoldier->bSectorZ == pOtherSoldier->bSectorZ ) + { + UINT16 bPreventChance = ( EffectiveLeadership( pOtherSoldier ) + EffectiveExpLevel( pOtherSoldier ) / 2); + if (gGameOptions.fNewTraitSystem) + { + bPreventChance += 25 * NUM_SKILL_TRAITS( pOtherSoldier, SQUADLEADER_NT ); + bPreventChance -= 25 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_NT ); + } + else + { + bPreventChance -= 25 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_OT ); + } + // keep 1% chance no matter what + bPreventChance = max( 0, min( 99, bPreventChance ) ); + if( bPreventChance > PreRandom( 100 ) ) + { + // merc is not amused by being prevented + HandleMoraleEvent( pSoldier, MORALE_PREVENTED_MISBEHAVIOUR, pSoldier->sSectorX, pSoldier->sSectorX, pSoldier->bSectorZ ); + // also here would be a place for dynamic relationship decrease between them + continue; + } + } + } + } + } if ( pSoldier->ubProfile == LARRY_DRUNK ) { // NB store all drunkenness info in LARRY_NORMAL profile (to use same values) @@ -449,10 +492,20 @@ void HourlyLarryUpdate() } } -// Flugente: certain characters might steal equipment (backgrounds) +// anv: decrease exposed snitch cooldown (for simplified exposition handling) +void HourlySnitchUpdate() +{ + for( INT32 cnt = 0; cnt <= NUM_PROFILES; ++cnt ) + { + if( gMercProfiles[cnt].ubSnitchExposedCooldown > 0 ) + gMercProfiles[cnt].ubSnitchExposedCooldown--; + } +} + void HourlyStealUpdate() { SOLDIERTYPE * pSoldier = NULL; + SOLDIERTYPE * pOtherSoldier = NULL; INT8 bSlot = NO_SLOT; UINT16 usTemptation = 0; BOOLEAN fBar = FALSE; @@ -469,6 +522,40 @@ void HourlyStealUpdate() // 20% chance that we'll steal something if ( Chance(20) ) { + // anv: snitches prevent scrounging in the same sector + for( INT32 cnt2 = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; cnt2 <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++cnt2 ) + { + pOtherSoldier = MercPtrs[ cnt ]; + // note - snitches stop others, but can scrounge themselves (if they have scrounging specifically set in background...) + if( pOtherSoldier && !pOtherSoldier->flags.fBetweenSectors && pOtherSoldier->bActive && pOtherSoldier->bInSector && !pOtherSoldier->flags.fMercAsleep && pSoldier->ubProfile != pOtherSoldier->ubProfile ) + { + if ( ProfileHasSkillTrait( pOtherSoldier->ubProfile, SNITCH_NT ) && !( pSoldier->bSoldierFlagMask2 & SOLDIER_PREVENT_MISBEHAVIOUR_OFF ) ) + { + if( pSoldier->sSectorX == pOtherSoldier->sSectorX && pSoldier->sSectorY == pOtherSoldier->sSectorY && pSoldier->bSectorZ == pOtherSoldier->bSectorZ ) + { + UINT16 bPreventChance = ( EffectiveLeadership( pOtherSoldier ) + EffectiveExpLevel( pOtherSoldier ) / 2); + if (gGameOptions.fNewTraitSystem) + { + bPreventChance += 25 * NUM_SKILL_TRAITS( pOtherSoldier, SQUADLEADER_NT ); + bPreventChance -= 25 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_NT ); + } + else + { + bPreventChance -= 25 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_OT ); + } + // keep 1% chance no matter what + bPreventChance = max( 0, min( 99, bPreventChance ) ); + if( bPreventChance > PreRandom( 100 ) ) + { + // merc is not amused by being prevented + HandleMoraleEvent( pSoldier, MORALE_PREVENTED_MISBEHAVIOUR, pSoldier->sSectorX, pSoldier->sSectorX, pSoldier->bSectorZ ); + // also here would be a place for dynamic relationship decrease between them + continue; + } + } + } + } + } // we loop over this sector's inventory and look for something shiny. We will pick it up if we hae enough space in our inventory // open sector inv UINT32 uiTotalNumberOfRealItems = 0; @@ -611,3 +698,18 @@ void HourlyHelicopterRepair() } } #endif + +void HourlyGatheringInformation() +{ + SOLDIERTYPE *pSoldier; + INT32 cnt=0; + + // go through list of characters, find all snicthes gathering info + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; cnt++,pSoldier++) + { + if( ( pSoldier->bActive ) && ( pSoldier->bAssignment == SNITCH_GATHER_RUMOURS || pSoldier->bAssignment == FACILITY_GATHER_RUMOURS ) ) + { + HandleGatheringInformationBySoldier( pSoldier ); + } + } +} diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index dcf97d4d0..fb2fbd74f 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -6396,7 +6396,8 @@ void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bS if( !sNumberOfEnemies ) { // nope - display nothing - return; + // anv: probability of false enemy reports! + //return; } diff --git a/Strategic/Map Screen Interface.cpp b/Strategic/Map Screen Interface.cpp index 3f67ed138..67f978bef 100644 --- a/Strategic/Map Screen Interface.cpp +++ b/Strategic/Map Screen Interface.cpp @@ -342,6 +342,13 @@ SGPPoint FacilityAssignmentPosition={220,150}; SGPPoint RepairPosition={160,150}; SGPRect RepairDimensions={0,0,80,80}; +SGPPoint SnitchPosition={160,150}; +SGPRect SnitchDimensions={0,0,80,80}; +SGPPoint SnitchTogglePosition={320,150}; +SGPRect SnitchToggleDimensions={0,0,80,80}; +SGPPoint SnitchSectorPosition={320,150}; +SGPRect SnitchSectorDimensions={0,0,80,80}; + //lal SGPPoint MilitiaControlPosition={120,150}; SGPRect MilitiaControlDimensions={0,0,100,95}; @@ -366,6 +373,9 @@ SGPPoint OrigMilitiaControlPosition = { 120, 150 }; //lal SGPPoint OrigFacilityPosition = { 160, 150 }; // HEADROCK HAM 3.6 SGPPoint OrigFacilityAssignmentPosition = { 220,150 }; // HEADROCK HAM 3.6 //SGPPoint OrigTalkToAllPosition = { 160, 150 }; +SGPPoint OrigSnitchPosition={160,150}; +SGPPoint OrigSnitchTogglePosition={320,150}; +SGPPoint OrigSnitchSectorPosition={320,150}; SQUAD_NAMES SquadNames[20]; @@ -917,7 +927,18 @@ void RestoreBackgroundForAssignmentGlowRegionList( void ) { ForceUpDateOfBox( ghTrainingBox ); } - + else if( fShowSnitchMenu == TRUE ) + { + ForceUpDateOfBox( ghSnitchBox ); + if( fShowSnitchToggleMenu == TRUE ) + { + ForceUpDateOfBox( ghSnitchToggleBox ); + } + else if( fShowSnitchSectorMenu == TRUE ) + { + ForceUpDateOfBox( ghSnitchSectorBox ); + } + } } if( fDisableDueToBattleRoster ) diff --git a/Strategic/Map Screen Interface.h b/Strategic/Map Screen Interface.h index 2934b2034..5291eb561 100644 --- a/Strategic/Map Screen Interface.h +++ b/Strategic/Map Screen Interface.h @@ -126,6 +126,7 @@ enum { ASSIGN_MENU_VEHICLE, ASSIGN_MENU_REPAIR, ASSIGN_MENU_RADIO_SCAN, // added by Flugente + ASSIGN_MENU_SNITCH, ASSIGN_MENU_TRAIN, ASSIGN_MENU_MOVE_ITEMS, // added by Flugente ASSIGN_MENU_FACILITY, // HEAROCK HAM 3.6: Facility List menu @@ -133,6 +134,29 @@ enum { MAX_ASSIGN_STRING_COUNT, }; +// snitch menu defines +enum{ + SNITCH_MENU_TOGGLE = 0, + SNITCH_MENU_SECTOR, + SNITCH_MENU_CANCEL, + MAX_SNITCH_MENU_STRING_COUNT, +}; + +enum { + SNITCH_MENU_TOGGLE_ON = 0, + SNITCH_MENU_TOGGLE_OFF, + SNITCH_MENU_MISBEHAVIOUR_ON, + SNITCH_MENU_MISBEHAVIOUR_OFF, + SNITCH_MENU_TOGGLE_CANCEL, + MAX_SNITCH_TOGGLE_MENU_STRING_COUNT, +}; + +enum { + SNITCH_MENU_SECTOR_PROPAGANDA = 0, + SNITCH_MENU_SECTOR_GATHER_RUMOURS, + SNITCH_MENU_SECTOR_CANCEL, + MAX_SNITCH_SECTOR_MENU_STRING_COUNT, +}; // training assignment menu defines enum { @@ -276,6 +300,10 @@ extern BOOLEAN fShowMilitiaControlMenu ; //lal //extern BOOLEAN fShowTalkToAllMenu ; extern BOOLEAN fShowFacilityMenu; // HEADROCK HAM 3.6 extern BOOLEAN fShowFacilityAssignmentMenu; // HEADROCK HAM 3.6 +// anv: snitch menus +extern BOOLEAN fShowSnitchMenu; +extern BOOLEAN fShowSnitchToggleMenu; +extern BOOLEAN fShowSnitchSectorMenu; extern BOOLEAN fFirstTimeInMapScreen; extern BOOLEAN fLockOutMapScreenInterface; @@ -330,6 +358,13 @@ extern SGPRect FacilityAssignmentDimensions; extern SGPPoint RepairPosition; extern SGPRect RepairDimensions; +extern SGPPoint SnitchPosition; +extern SGPRect SnitchDimensions; +extern SGPPoint SnitchTogglePosition; +extern SGPRect SnitchToggleDimensions; +extern SGPPoint SnitchSectorPosition; +extern SGPRect SnitchSectorDimensions; + extern SGPPoint MilitiaControlPosition; //lal extern SGPRect MilitiaControlDimensions; @@ -346,6 +381,9 @@ extern SGPPoint OrigMilitiaControlPosition ; //lal extern SGPPoint OrigFacilityPosition; // HEADROCK HAM 3.6: Facility Menu extern SGPPoint OrigFacilityAssignmentPosition; // HEADROCK HAM 3.6 //extern SGPPoint OrigTalkToAllPosition ; +extern SGPPoint OrigSnitchPosition; +extern SGPPoint OrigSnitchTogglePosition; +extern SGPPoint OrigSnitchSectorPosition; // disble team info panel due to showing of battle roster extern BOOLEAN fDisableDueToBattleRoster; diff --git a/Strategic/Strategic Merc Handler.cpp b/Strategic/Strategic Merc Handler.cpp index 230803f10..46adb0e82 100644 --- a/Strategic/Strategic Merc Handler.cpp +++ b/Strategic/Strategic Merc Handler.cpp @@ -356,6 +356,10 @@ void MercDailyUpdate() } } + if( !MercThinksHisMoraleIsTooLow( pSoldier ) && ProfileHasSkillTrait( pSoldier->ubProfile, SNITCH_NT ) ) + { + ModifyPlayerReputation( gSkillTraitValues.ubSNTPassiveReputationGain ); + } DailyMoraleUpdate( pSoldier ); diff --git a/Strategic/Strategic Town Loyalty.cpp b/Strategic/Strategic Town Loyalty.cpp index a43920003..f7c0b38bc 100644 --- a/Strategic/Strategic Town Loyalty.cpp +++ b/Strategic/Strategic Town Loyalty.cpp @@ -342,6 +342,9 @@ void DecrementTownLoyalty( INT8 bTownId, UINT32 uiLoyaltyDecrease ) return; } + // anv: snitches spreading propaganda affect decrease amount + uiLoyaltyDecrease = HandlePropagandaBlockingBadNewsInTown( bTownId, uiLoyaltyDecrease ); + // modify loyalty change by town's individual attitude toward rebelling (20 is typical) uiLoyaltyDecrease *= 100; uiLoyaltyDecrease /= (5 * gubTownRebelSentiment[ bTownId ]); diff --git a/Strategic/XML_FacilityTypes.cpp b/Strategic/XML_FacilityTypes.cpp index e979a6460..2c4590124 100644 --- a/Strategic/XML_FacilityTypes.cpp +++ b/Strategic/XML_FacilityTypes.cpp @@ -832,7 +832,27 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name) { //pData->curAssignmentType = (INT16) atol(pData->szCharData); pData->curAssignmentType = FAC_INTERROGATE_PRISONERS; - } + } + else if (strcmp(pData->szCharData, "PRISON_SNITCH") == 0) + { + //pData->curAssignmentType = (INT16) atol(pData->szCharData); + pData->curAssignmentType = FAC_PRISON_SNITCH; + } + else if (strcmp(pData->szCharData, "SPREAD_PROPAGANDA") == 0) + { + //pData->curAssignmentType = (INT16) atol(pData->szCharData); + pData->curAssignmentType = FAC_SPREAD_PROPAGANDA; + } + else if (strcmp(pData->szCharData, "SPREAD_PROPAGANDA_GLOBAL") == 0) + { + //pData->curAssignmentType = (INT16) atol(pData->szCharData); + pData->curAssignmentType = FAC_SPREAD_PROPAGANDA_GLOBAL; + } + else if (strcmp(pData->szCharData, "GATHER_RUMOURS") == 0) + { + //pData->curAssignmentType = (INT16) atol(pData->szCharData); + pData->curAssignmentType = FAC_GATHER_RUMOURS; + } else { CHAR16 sErrorString[256]; diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index 320ae5c15..3994f8e8d 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -2335,6 +2335,27 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE fShowNumber = TRUE; fShowMaximum = TRUE; break; + + case FACILITY_PRISON_SNITCH: + sIconIndex_Assignment = 27; + fDoIcon_Assignment = TRUE; + sPtsAvailable = (INT16)( CalculateSnitchInterrogationValue(pSoldier, &usMaximumPts ) ); + fShowNumber = TRUE; + fShowMaximum = TRUE; + break; + + case SNITCH_SPREAD_PROPAGANDA: + case FACILITY_SPREAD_PROPAGANDA: + case FACILITY_SPREAD_PROPAGANDA_GLOBAL: + sIconIndex_Assignment = 25; + fDoIcon_Assignment = TRUE; + break; + + case SNITCH_GATHER_RUMOURS: + case FACILITY_GATHER_RUMOURS: + sIconIndex_Assignment = 26; + fDoIcon_Assignment = TRUE; + break; } // Check for being serviced... diff --git a/Tactical/LOS.h b/Tactical/LOS.h index 2c4c0d1eb..dec208206 100644 --- a/Tactical/LOS.h +++ b/Tactical/LOS.h @@ -251,5 +251,6 @@ extern INT8 EffectiveExpLevel( SOLDIERTYPE * pSoldier ); extern INT16 EffectiveDexterity( SOLDIERTYPE * pSoldier, BOOLEAN fTrainer ); extern INT16 EffectiveStrength( SOLDIERTYPE * pSoldier, BOOLEAN fTrainer ); extern INT16 EffectiveAgility( SOLDIERTYPE * pSoldier, BOOLEAN fTrainer ); +extern INT8 EffectiveLeadership( SOLDIERTYPE * pSoldier ); // anv: and passed to Hourly Update.cpp apparently, so added this one too #endif \ No newline at end of file diff --git a/Tactical/Morale.cpp b/Tactical/Morale.cpp index 7c3973679..07eb41b16 100644 --- a/Tactical/Morale.cpp +++ b/Tactical/Morale.cpp @@ -105,6 +105,7 @@ MoraleEvent gbMoraleEvent[NUM_MORALE_EVENTS] = { STRATEGIC_MORALE_EVENT, -2}, //MORALE_BAD_EQUIPMENT, { STRATEGIC_MORALE_EVENT, -3}, //MORALE_OWED_MONEY, { STRATEGIC_MORALE_EVENT, -3}, //MORALE_PLAYER_INACTIVE, + { STRATEGIC_MORALE_EVENT, -1}, //MORALE_PREVENTED_MISBEHAVIOUR, }; BOOLEAN gfSomeoneSaidMoraleQuote = FALSE; @@ -1384,6 +1385,12 @@ void HandleSnitchesReports( SnitchEvent *SnitchEvents, UINT8 ubSnitchEventsCount bSnitchID = SnitchEvents[bCounter].ubSnitchID; pSnitch = FindSoldierByProfileID(bSnitchID,TRUE); + if( pSnitch == NULL ) + continue; + + if( !(pSnitch->bActive) ) + continue; + if( pSnitch->flags.fMercAsleep ) fSleepingSnitch = TRUE; @@ -1399,6 +1406,18 @@ void HandleSnitchesReports( SnitchEvent *SnitchEvents, UINT8 ubSnitchEventsCount { if( SnitchEvents[bCounter2].ubSnitchID == bSnitchID ) { + // check if relevant mercs are well + SOLDIERTYPE *pSoldier, *pOtherSoldier; + pSoldier = FindSoldierByProfileID(SnitchEvents[bCounter2].ubTargetProfile,TRUE); + if( pSoldier == NULL || !(pSoldier->bActive) ) + continue; + + if( SnitchEvents[bCounter2].ubEventType == SNITCH_HATED_PERSON ) + { + pOtherSoldier = FindSoldierByProfileID(SnitchEvents[bCounter2].ubSecondaryTargetProfile,TRUE); + if( pOtherSoldier == NULL || !(pOtherSoldier->bActive) ) + continue; + } // say this info SnitchTacticalCharacterDialogue(FindSoldierByProfileID(bSnitchID,TRUE),SnitchEvents[bCounter2].ubEventType,SnitchEvents[bCounter2].ubEventType, SnitchEvents[bCounter2].ubTargetProfile,SnitchEvents[bCounter2].ubSecondaryTargetProfile); @@ -1497,6 +1516,10 @@ UINT8 RememberSnitchableEvent( UINT8 ubTargetProfile, UINT8 ubSecondaryTargetPro (FLOAT)( gSkillTraitValues.bSNTMercOpinionAboutMercTreshold - HATED_OPINION ) ) ); } } + if ( gMercProfiles[pSnitch->ubProfile].bDisability == DEAF ) + { + sSnitchingChance /= 2; + } sSnitchingChance = max(0, sSnitchingChance); if( Random(100) < (UINT8)sSnitchingChance ) { diff --git a/Tactical/Morale.h b/Tactical/Morale.h index df642ad92..be83fbb39 100644 --- a/Tactical/Morale.h +++ b/Tactical/Morale.h @@ -63,9 +63,10 @@ typedef enum MORALE_OWED_MONEY, MORALE_OWED_MONEY_DAYS, MORALE_PLAYER_INACTIVE, - MORALE_PLAYER_INACTIVE_DAYS, + MORALE_PLAYER_INACTIVE_DAYS, //50 MORALE_PLAYER_INACTIVE_DAYS_AGGRESSIVE_BONUS, MORALE_PLAYER_INACTIVE_DAYS_PACIFIST_BONUS, + MORALE_PREVENTED_MISBEHAVIOUR, NUM_MORALE_EVENTS, } MoraleEventNames; diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index f567cfa4c..b3f71d8f7 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -10525,7 +10525,7 @@ UINT16 GetNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* apSpeci return (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN]); } -void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin ) +void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin, INT16 sX, INT16 sY ) { if ( !pSectorInfo ) return; @@ -10534,6 +10534,19 @@ void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aEl pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + aElite) ); pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + aRegular) ); pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN] + aAdmin) ); + + // anv: handle change of number of prisoners knowing snitch's identity + //if( sX != 0 && sY != 0 ) + //{ + // for( UINT8 cnt = 0; cnt < NUM_PROFILES; cnt++ ) + // { + // if( gMercProfiles[ cnt ].ubExposedInSector[ SECTOR(sX, sY) ] != 0 ) + // { + // gMercProfiles[ cnt ].ubExposedInSector[ SECTOR(sX, sY) ] = max( 0, min( 255, gMercProfiles[ cnt ].ubExposedInSector[ SECTOR(sX, sY) ] + aSpecial + aElite + aRegular + aAdmin ) ); + // } + // } + //} + } void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin ) diff --git a/Tactical/Overhead.h b/Tactical/Overhead.h index d51ea67cf..31c5c6a94 100644 --- a/Tactical/Overhead.h +++ b/Tactical/Overhead.h @@ -376,7 +376,7 @@ BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr); UINT16 GetNumberOfPrisoners( SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin ); UINT16 GetNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin ); -void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin ); +void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin, INT16 sX = 0, INT16 sY = 0 ); void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin ); void DeleteAllPrisoners( SECTORINFO *pSectorInfo ); diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index d2af71fc5..700f680a2 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -393,6 +393,11 @@ enum #define WH40K_SOLDIER_KILLTHISTURN 0x80000000 //2147483648 // Soldier is on a kill streak*/ // ---------------------------------------------------------------- +// ------------------- more flags for soldiers -------------------- +#define SOLDIER_SNITCHING_OFF 0x00000001 //1 // isn't allowed to snitch +#define SOLDIER_PREVENT_MISBEHAVIOUR_OFF 0x00000002 //2 // isn't allowed to prevent misbehaviour +// ---------------------------------------------------------------- + // -------- added by Flugente: background property flags -------- // easier than adding 32 differently named variables. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!! // a merc's background info reveals data about his previous life, like former regiments. These backgrounds add small abilities/disabilities. Nothing substantial, just small bits do @@ -1453,6 +1458,9 @@ public: // Flugente: Decrease this filler by 1 for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!! // Note that we also have to account for padding, so you might need to substract more than just the size of the new variables UINT8 ubFiller[20]; + + INT32 bSoldierFlagMask2; // anv: another bSoldierFlagMask + #ifdef JA2UB //ja25 diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index 5e2b22ff8..2cada8842 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -1566,6 +1566,8 @@ INT8 DecideHearing( SOLDIERTYPE * pSoldier ) { if (HAS_SKILL_TRAIT( pSoldier, NIGHT_OPS_NT )) bHearing += gSkillTraitValues.ubNOHearingRangeBonus; + if (HAS_SKILL_TRAIT( pSoldier, SNITCH_NT )) + bHearing += gSkillTraitValues.ubSNTHearingRangeBonus; } else { diff --git a/Tactical/soldier profile type.h b/Tactical/soldier profile type.h index 26b42739b..f84086825 100644 --- a/Tactical/soldier profile type.h +++ b/Tactical/soldier profile type.h @@ -3,6 +3,7 @@ #include "overhead types.h" #include "Soldier Control.h" +#include "mapscreen.h" #define NUM_PROFILES 255 //170 new profiles by Jazz #define NUM_PROFILES_v111 170 @@ -945,6 +946,12 @@ public: // Flugente: background UINT16 usBackground; + // anv: for snitches, remember if he was exposed and by how many people (could be used for covert purposes too) + //UINT8 ubExposedInSector[MAP_WORLD_X * MAP_WORLD_Y]; + + // anv: simplified ubExposedInSector, hours until snitch can go undercover after exposition + UINT8 ubSnitchExposedCooldown; + }; // MERCPROFILESTRUCT; // WANNE - BMP: DONE! diff --git a/Utils/ExportStrings.cpp b/Utils/ExportStrings.cpp index a25c0dec2..7b02a982c 100644 --- a/Utils/ExportStrings.cpp +++ b/Utils/ExportStrings.cpp @@ -136,6 +136,16 @@ bool Loc::ExportStrings() ExportSection(props, L"AttributeMenu", Loc::pAttributeMenuStrings, 0, MAX_ATTRIBUTE_STRING_COUNT); ExportSection(props, L"TrainingMenu", Loc::pTrainingMenuStrings, 0, MAX_TRAIN_STRING_COUNT); ExportSection(props, L"SquadMenu", Loc::pSquadMenuStrings, 0, MAX_SQUAD_MENU_STRING_COUNT); + + ExportSection(props, L"SnitchMenu", Loc::pSnitchMenuStrings, 0, MAX_SNITCH_MENU_STRING_COUNT); + ExportSection(props, L"SnitchMenuDesc", Loc::pSnitchMenuDescStrings, 0, MAX_SNITCH_MENU_STRING_COUNT-1); + ExportSection(props, L"SnitchToggleMenu", Loc::pSnitchToggleMenuStrings, 0, MAX_SNITCH_TOGGLE_MENU_STRING_COUNT); + ExportSection(props, L"SnitchToggleMenuDesc", Loc::pSnitchToggleMenuDescStrings, 0, MAX_SNITCH_TOGGLE_MENU_STRING_COUNT-1); + ExportSection(props, L"SnitchSectorMenu", Loc::pSnitchSectorMenuStrings, 0, MAX_SNITCH_SECTOR_MENU_STRING_COUNT); + ExportSection(props, L"SnitchSectorMenuDesc", Loc::pSnitchSectorMenuDescStrings, 0, MAX_SNITCH_SECTOR_MENU_STRING_COUNT-1); + ExportSection(props, L"SnitchPrisonExposed", Loc::pSnitchPrisonExposedStrings, 0, NUM_SNITCH_PRISON_EXPOSED); + ExportSection(props, L"SnitchGatheringRumoursResult", Loc::pSnitchGatheringRumoursResultStrings, 0, NUM_SNITCH_GATHERING_RUMOURS_RESULT); + ExportSection(props, L"PersonnelTitle", Loc::pPersonnelTitle, 0, 1); ExportSection(props, L"PersonnelScreen", Loc::pPersonnelScreenStrings, 0, TEXT_NUM_PRSNL); diff --git a/Utils/MercTextBox.cpp b/Utils/MercTextBox.cpp index 779d14592..38192b729 100644 --- a/Utils/MercTextBox.cpp +++ b/Utils/MercTextBox.cpp @@ -27,7 +27,7 @@ #define MERC_TEXT_POPUP_WINDOW_TEXT_OFFSET_Y 10 #define MERC_BACKGROUND_WIDTH 350 -#define MERC_BACKGROUND_HEIGHT 200 +#define MERC_BACKGROUND_HEIGHT 207 // the max number of pop up boxes availiable to user #define MAX_NUMBER_OF_POPUP_BOXES 10 diff --git a/Utils/Text.h b/Utils/Text.h index 394816f29..8b3cd2ca1 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -156,6 +156,14 @@ extern STR16 pTraitSkillsMenuStrings[]; //Flugente extern STR16 pTraitSkillsMenuDescStrings[]; //Flugente extern STR16 pTraitSkillsDenialStrings[]; //Flugente //extern STR16 pTalkToAllMenuStrings[]; +extern STR16 pSnitchMenuStrings[]; +extern STR16 pSnitchMenuDescStrings[]; +extern STR16 pSnitchToggleMenuStrings[]; +extern STR16 pSnitchToggleMenuDescStrings[]; +extern STR16 pSnitchSectorMenuStrings[]; +extern STR16 pSnitchSectorMenuDescStrings[]; +extern STR16 pSnitchPrisonExposedStrings[]; +extern STR16 pSnitchGatheringRumoursResultStrings[]; extern STR16 pAssignMenuStrings[]; extern STR16 pTrainingStrings[]; extern STR16 pTrainingMenuStrings[]; diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 7c2edfc3a..9c7b15539 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -1933,6 +1933,12 @@ STR16 pPersonnelAssignmentStrings[] = L"战俘", L"医院", L"空车", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gathering Rumours",// TODO.Translate // facility: gather rumours + L"Spreading Propaganda",// TODO.Translate // spread propaganda + L"Gathering Rumours",// TODO.Translate // gather information }; @@ -1981,6 +1987,12 @@ STR16 pLongAssignmentStrings[] = L"战俘", L"医院",// patient in a hospital L"空车", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gather Rumours",// TODO.Translate // facility: gather rumours + L"Spread Propaganda",// TODO.Translate // spread propaganda + L"Gather Rumours",// TODO.Translate // gather information }; @@ -2097,6 +2109,7 @@ STR16 pAssignMenuStrings[] = L"交通工具", L"修理", L"无线电扫描", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // TODO.Translate // anv: snitch actions L"训练", L"搬运物品", // move items L"设施", // L"Facility", // the merc is using/staffing a facility //ham3.6 @@ -2168,6 +2181,82 @@ STR16 pTraitSkillsDenialStrings[] = L" - 恶魔的财产", //L" - posession by a demon" }; +// TODO.Translate +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; +// /TODO.Translate + STR16 pRemoveMercStrings[] = { L"移除佣兵", // remove dead merc from current team @@ -7007,6 +7096,8 @@ STR16 gzFacilityErrorMessage[]= L"%s在%s负伤了。", // <--- This is a log message string. // 31 - 35 L"%s在%s负了重伤。", //<--- This is a log message string. + L"There are currently prisoners here who are aware of %s's identity.", // TODO.Translate + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", // TODO.Translate }; diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index edbc86d73..15c2372be 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -1930,6 +1930,12 @@ STR16 pPersonnelAssignmentStrings[] = L"POW", // Prisoner of war - captured L"Kliniek", // patient in a hospital L"Leeg", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gathering Rumours",// TODO.Translate // facility: gather rumours + L"Spreading Propaganda",// TODO.Translate // spread propaganda + L"Gathering Rumours",// TODO.Translate // gather information }; @@ -1978,6 +1984,12 @@ STR16 pLongAssignmentStrings[] = L"POW", // Prisoner of war - captured L"Kliniek", // patient in a hospital L"Leeg", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gather Rumours",// TODO.Translate // facility: gather rumours + L"Spread Propaganda",// TODO.Translate // spread propaganda + L"Gather Rumours",// TODO.Translate // gather information }; @@ -2094,6 +2106,7 @@ STR16 pAssignMenuStrings[] = L"Vehicle", // the merc is in a vehicle L"Repair", // the merc is repairing items L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // TODO.Translate // anv: snitch actions L"Train", // the merc is training L"Move Item", // move items // TODO.Translate L"Facility", // the merc is using/staffing a facility // TODO.Translate @@ -2165,6 +2178,82 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", }; +// TODO.Translate +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; +// /TODO.Translate + STR16 pRemoveMercStrings[] = { L"Verw.Huurl.", // remove dead merc from current team @@ -7013,6 +7102,8 @@ STR16 gzFacilityErrorMessage[]= L"%s was injured in sector %s.", // <--- This is a log message string. // 31 - 35 L"%s was severely injured in sector %s.", //<--- This is a log message string. + L"There are currently prisoners here who are aware of %s's identity.", // TODO.Translate + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", // TODO.Translate }; diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index a1b389edc..ff2ba288b 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -1844,7 +1844,13 @@ STR16 pAssignmentStrings[] = L"Incap.", // abbreviation for incapacitated L"POW", // Prisoner of war - captured L"Hospital", // patient in a hospital - L"Empty", // Vehicle is empty + L"Empty", // Vehicle is empty + L"Snitch", // facility: undercover prisoner (snitch) + L"Propag.", // facility: spread propaganda + L"Propag.", // facility: spread propaganda (globally) + L"Rumours", // facility: gather information + L"Propag.", // spread propaganda + L"Rumours", // gather information }; @@ -1934,6 +1940,12 @@ STR16 pPersonnelAssignmentStrings[] = L"POW", L"Hospital", L"Empty", // Vehicle is empty + L"Undercover Snitch", // facility: undercover prisoner (snitch) + L"Spreading Propaganda", // facility: spread propaganda + L"Spreading Propaganda", // facility: spread propaganda (globally) + L"Gathering Rumours", // facility: gather rumours + L"Spreading Propaganda", // spread propaganda + L"Gathering Rumours", // gather information }; @@ -1973,7 +1985,7 @@ STR16 pLongAssignmentStrings[] = L"Train Mobiles", // Missing L"Train Teammate", L"Student", - L"MoveItem", // move items + L"Move Item", // move items L"Staff Facility", // Missing L"Rest at Facility", // Missing L"Interrogate prisoners", // Flugente: interrogate prisoners @@ -1982,6 +1994,12 @@ STR16 pLongAssignmentStrings[] = L"POW", L"Hospital", // patient in a hospital L"Empty", // Vehicle is empty + L"Undercover Snitch", // facility: undercover prisoner (snitch) + L"Spread Propaganda", // facility: spread propaganda + L"Spread Propaganda", // facility: spread propaganda (globally) + L"Gather Rumours", // facility: gather rumours + L"Spread Propaganda", // spread propaganda + L"Gather Rumours", // gather information }; @@ -2098,8 +2116,9 @@ STR16 pAssignMenuStrings[] = L"Vehicle", // the merc is in a vehicle L"Repair", // the merc is repairing items L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // anv: snitch actions L"Train", // the merc is training - L"MoveItem", // move items + L"Move Item", // move items L"Facility", // the merc is using/staffing a facility L"Cancel", // cancel this menu }; @@ -2169,6 +2188,80 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", }; +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; + STR16 pRemoveMercStrings[] = { L"Remove Merc", // remove dead merc from current team @@ -7006,6 +7099,8 @@ STR16 gzFacilityErrorMessage[]= L"%s was injured in sector %s.", // <--- This is a log message string. // 31 - 35 L"%s was severely injured in sector %s.", //<--- This is a log message string. + L"There are currently prisoners here who are aware of %s's identity.", + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", }; @@ -7070,6 +7165,11 @@ STR16 gzFacilityAssignmentStrings[]= L"Trainer Leadership", L"Trainer Explosives", L"Interrogate Prisoners", // added by Flugente + L"Undercover Snitch", + // 36-40 + L"Spread Propaganda", + L"Spread Propaganda", // spread propaganda (globally) + L"Gather Rumours", }; STR16 Additional113Text[]= { @@ -7885,10 +7985,10 @@ STR16 szFoodTextStr[]= STR16 szPrisonerTextStr[]= { - L"%d elites, %d regulars and %d amins were interrogated.", + L"%d elites, %d regulars and %d admins were interrogated.", L"%d prisoners paid ransom money.", L"%d prisoners revealed enemy positions.", - L"%d elites, %d regulars and %d amins joined our cause.", + L"%d elites, %d regulars and %d admins joined our cause.", L"Prisoners start a massive riot in %s!", L"%d prisoners were sent to %s!", L"Prisoners have been released!", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 067118b7d..560cbfa70 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -1937,6 +1937,12 @@ STR16 pPersonnelAssignmentStrings[] = L"Capturé(e)", L"Hôpital", L"Vide", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gathering Rumours",// TODO.Translate // facility: gather rumours + L"Spreading Propaganda",// TODO.Translate // spread propaganda + L"Gathering Rumours",// TODO.Translate // gather information }; @@ -1985,6 +1991,12 @@ STR16 pLongAssignmentStrings[] = L"Capturé(e)", L"Hôpital", // patient in a hospital L"Vide", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gather Rumours",// TODO.Translate // facility: gather rumours + L"Spread Propaganda",// TODO.Translate // spread propaganda + L"Gather Rumours",// TODO.Translate // gather information }; @@ -2101,6 +2113,7 @@ STR16 pAssignMenuStrings[] = L"Transport", // the merc is in a vehicle L"Réparat.", // the merc is repairing items L"Radio", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // TODO.Translate // anv: snitch actions L"Formation", // the merc is training L"Dépl obj.", // move items L"Affectat.", // the merc is using/staffing a facility @@ -2172,6 +2185,82 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession par un démon", }; +// TODO.Translate +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; +// /TODO.Translate + STR16 pRemoveMercStrings[] = { L"Enlever Merc", // remove dead merc from current team @@ -7007,6 +7096,8 @@ STR16 gzFacilityErrorMessage[]= L"%s a été blessé dans le secteur %s.", // <--- This is a log message string. // 31 - 35 L"%s a été gravement blessé dans le secteur %s.", //<--- This is a log message string. + L"There are currently prisoners here who are aware of %s's identity.", // TODO.Translate + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", // TODO.Translate }; diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index ef303d4fe..0f7196ea7 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -1938,6 +1938,12 @@ STR16 pPersonnelAssignmentStrings[] = L"Gefangen", L"Hospital", L"Leer", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gathering Rumours",// TODO.Translate // facility: gather rumours + L"Spreading Propaganda",// TODO.Translate // spread propaganda + L"Gathering Rumours",// TODO.Translate // gather information }; // refer to above for comments @@ -1984,6 +1990,12 @@ STR16 pLongAssignmentStrings[] = L"Gefangen", L"Hospital", // patient in a hospital L"Leer", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gather Rumours",// TODO.Translate // facility: gather rumours + L"Spread Propaganda",// TODO.Translate // spread propaganda + L"Gather Rumours",// TODO.Translate // gather information }; // the contract options @@ -2096,6 +2108,7 @@ STR16 pAssignMenuStrings[] = L"Fahrzeug", // the merc is in a vehicle L"Repar.", // the merc is repairing items L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // TODO.Translate // anv: snitch actions L"Training", // the merc is training L"Umzug", // move items L"Betrieb", // the merc is using/staffing a facility @@ -2167,6 +2180,82 @@ STR16 pTraitSkillsDenialStrings[] = L" - besessen von einem Dämon", }; +// TODO.Translate +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; +// /TODO.Translate + STR16 pRemoveMercStrings[] ={ L"Söldner entfernen", // remove dead merc from current team L"Abbrechen", @@ -6831,6 +6920,8 @@ STR16 gzFacilityErrorMessage[]= L"%s wurde verletzt in Sektor %s.", // <--- This is a log message string. // 31 - 35 L"%s wurde ernsthaft im Sektor %s verletzt.", //<--- This is a log message string. + L"There are currently prisoners here who are aware of %s's identity.", // TODO.Translate + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", // TODO.Translate }; diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index e1b290748..8f5a20fe1 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -1926,6 +1926,12 @@ STR16 pPersonnelAssignmentStrings[] = L"PDG", L"Ospedale", L"Vuoto", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gathering Rumours",// TODO.Translate // facility: gather rumours + L"Spreading Propaganda",// TODO.Translate // spread propaganda + L"Gathering Rumours",// TODO.Translate // gather information }; @@ -1974,6 +1980,12 @@ STR16 pLongAssignmentStrings[] = L"PDG", L"Ospedale", // patient in a hospital L"Vuoto", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gather Rumours",// TODO.Translate // facility: gather rumours + L"Spread Propaganda",// TODO.Translate // spread propaganda + L"Gather Rumours",// TODO.Translate // gather information }; @@ -2090,6 +2102,7 @@ STR16 pAssignMenuStrings[] = L"Veicolo", // the merc is in a vehicle L"Ripara", // the merc is repairing items L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // TODO.Translate // anv: snitch actions L"Si esercita", // the merc is training L"Move Item", // move items // TODO.Translate L"Facility", // the merc is using/staffing a facility // TODO.Translate @@ -2161,6 +2174,82 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", }; +// TODO.Translate +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; +// /TODO.Translate + STR16 pRemoveMercStrings[] = { L"Rimuovi Mercenario", // remove dead merc from current team @@ -7004,6 +7093,8 @@ STR16 gzFacilityErrorMessage[]= L"%s was injured in sector %s.", // <--- This is a log message string. // 31 - 35 L"%s was severely injured in sector %s.", //<--- This is a log message string. + L"There are currently prisoners here who are aware of %s's identity.", // TODO.Translate + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", // TODO.Translate }; diff --git a/Utils/_Ja25ChineseText.cpp b/Utils/_Ja25ChineseText.cpp index d82362a74..3aaace7d9 100644 --- a/Utils/_Ja25ChineseText.cpp +++ b/Utils/_Ja25ChineseText.cpp @@ -374,9 +374,16 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= L"防止血猫偷袭你的队伍\n",// L"Prevents the bloodcats to ambush your squad\n", }; + STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { - L"有时候会告诉你所在队伍队员的意见。\n", // TODO.Translate + L"Will occasionally inform you about his teammates' opinions.\n", // TODO.Translate + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", // TODO.Translate + L"Can spread propaganda in towns.\n", // TODO.Translate + L"Can gather rumours in towns.\n", // TODO.Translate + L"Can be put undercover in prisons.\n", // TODO.Translate + L"Increases your reputation by %d every day if in good morale.\n", // TODO.Translate + L"+%d to effective hearing range\n", // TODO.Translate }; STR16 gzIMPMinorTraitsHelpTextsNone[]= diff --git a/Utils/_Ja25DutchText.cpp b/Utils/_Ja25DutchText.cpp index 2c4514c82..8ab9c98e1 100644 --- a/Utils/_Ja25DutchText.cpp +++ b/Utils/_Ja25DutchText.cpp @@ -379,6 +379,12 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Will occasionally inform you about his teammates' opinions.\n", // TODO.Translate + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", // TODO.Translate + L"Can spread propaganda in towns.\n", // TODO.Translate + L"Can gather rumours in towns.\n", // TODO.Translate + L"Can be put undercover in prisons.\n", // TODO.Translate + L"Increases your reputation by %d every day if in good morale.\n", // TODO.Translate + L"+%d to effective hearing range\n", // TODO.Translate }; STR16 gzIMPMinorTraitsHelpTextsNone[]= diff --git a/Utils/_Ja25EnglishText.cpp b/Utils/_Ja25EnglishText.cpp index 45d6f4edb..26614a214 100644 --- a/Utils/_Ja25EnglishText.cpp +++ b/Utils/_Ja25EnglishText.cpp @@ -376,10 +376,15 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= L"Prevents enemy ambushes on your squad\n", L"Prevents bloodcat ambushes on your squad\n", }; - STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Will occasionally inform you about his teammates' opinions.\n", + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", + L"Can spread propaganda in towns.\n", + L"Can gather rumours in towns.\n", + L"Can be put undercover in prisons.\n", + L"Increases your reputation by %d every day if in good morale.\n", + L"+%d to effective hearing range\n", }; STR16 gzIMPMinorTraitsHelpTextsNone[]= diff --git a/Utils/_Ja25FrenchText.cpp b/Utils/_Ja25FrenchText.cpp index 1fb27dd71..4a46498b8 100644 --- a/Utils/_Ja25FrenchText.cpp +++ b/Utils/_Ja25FrenchText.cpp @@ -373,11 +373,16 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= L"Si vous êtes dans le secteur, vous saurez la présence au non d'ennemis dans les secteurs alentours\n", L"Empêche l'ennemi de prendre en embuscade votre escouade\n", L"Empêche les chats sauvages de prendre en embuscade votre escouade\n", - }; STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Vous informera à l'occasion sur les opinions de ses coéquipiers.\n", + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", // TODO.Translate + L"Can spread propaganda in towns.\n", // TODO.Translate + L"Can gather rumours in towns.\n", // TODO.Translate + L"Can be put undercover in prisons.\n", // TODO.Translate + L"Increases your reputation by %d every day if in good morale.\n", // TODO.Translate + L"+%d to effective hearing range\n", // TODO.Translate }; STR16 gzIMPMinorTraitsHelpTextsNone[]= { diff --git a/Utils/_Ja25GermanText.cpp b/Utils/_Ja25GermanText.cpp index 2979471f0..27930bdc1 100644 --- a/Utils/_Ja25GermanText.cpp +++ b/Utils/_Ja25GermanText.cpp @@ -370,11 +370,16 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= L"Auf der Weltkarte wird in angrenzenden Sektoren die Präsenz von vorhandenem Feind enthüllt\n", L"Verhindert, dass der Feind die Gruppe in den Hinterhalt lockt\n", L"Verhindert, das Umzingeln der Gruppe durch Bloodcats\n", - }; STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Will occasionally inform you about his teammates' opinions.\n", // TODO.Translate + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", // TODO.Translate + L"Can spread propaganda in towns.\n", // TODO.Translate + L"Can gather rumours in towns.\n", // TODO.Translate + L"Can be put undercover in prisons.\n", // TODO.Translate + L"Increases your reputation by %d every day if in good morale.\n", // TODO.Translate + L"+%d to effective hearing range\n", // TODO.Translate }; STR16 gzIMPMinorTraitsHelpTextsNone[]= { diff --git a/Utils/_Ja25ItalianText.cpp b/Utils/_Ja25ItalianText.cpp index 517dd41b5..94fec4ed6 100644 --- a/Utils/_Ja25ItalianText.cpp +++ b/Utils/_Ja25ItalianText.cpp @@ -377,6 +377,12 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Will occasionally inform you about his teammates' opinions.\n", // TODO.Translate + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", // TODO.Translate + L"Can spread propaganda in towns.\n", // TODO.Translate + L"Can gather rumours in towns.\n", // TODO.Translate + L"Can be put undercover in prisons.\n", // TODO.Translate + L"Increases your reputation by %d every day if in good morale.\n", // TODO.Translate + L"+%d to effective hearing range\n", // TODO.Translate }; STR16 gzIMPMinorTraitsHelpTextsNone[]= { diff --git a/Utils/_Ja25PolishText.cpp b/Utils/_Ja25PolishText.cpp index a1937ee19..3257f1825 100644 --- a/Utils/_Ja25PolishText.cpp +++ b/Utils/_Ja25PolishText.cpp @@ -379,6 +379,13 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Okazyjnie poinformuje cię o opiniach kolegów z oddziału.\n", + L"Zapobiega złemu zachowaniu kolegów z oddziału (narkotyki, alkohol, kradzieże).\n", + L"Może szerzyć propagandę w miastach.\n", + L"Może zbierać plotki w miastach.\n", + L"Może zostać umieszczony w więzieniu jako tajniak.\n", + L"Jeżeli w dobrym nastroju, poprawia twoją reputację o %d każdego dnia.\n", + L"+%d zasięg słuchu\n", + }; STR16 gzIMPMinorTraitsHelpTextsNone[]= { diff --git a/Utils/_Ja25RussianText.cpp b/Utils/_Ja25RussianText.cpp index 69ca173f9..9f555a98f 100644 --- a/Utils/_Ja25RussianText.cpp +++ b/Utils/_Ja25RussianText.cpp @@ -371,11 +371,17 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= L"Если в секторе, в смежных секторах будет показано наличие врагов\n", L"Предотвращает попадание отряда во вражеские засады\n", L"Предотвращает попадание отряда в засады кошек-убийц\n", - }; STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Will occasionally inform you about his teammates' opinions.\n", // TODO.Translate + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", // TODO.Translate + L"Can spread propaganda in towns.\n", // TODO.Translate + L"Can gather rumours in towns.\n", // TODO.Translate + L"Can be put undercover in prisons.\n", // TODO.Translate + L"Increases your reputation by %d every day if in good morale.\n", // TODO.Translate + L"+%d to effective hearing range\n", // TODO.Translate + }; STR16 gzIMPMinorTraitsHelpTextsNone[]= { diff --git a/Utils/_Ja25TaiwaneseText.cpp b/Utils/_Ja25TaiwaneseText.cpp index e93783df6..925410cab 100644 --- a/Utils/_Ja25TaiwaneseText.cpp +++ b/Utils/_Ja25TaiwaneseText.cpp @@ -380,6 +380,12 @@ STR16 gzIMPMinorTraitsHelpTextsScouting[]= STR16 gzIMPMinorTraitsHelpTextsSnitch[]= { L"Will occasionally inform you about his teammates' opinions.\n", // TODO.Translate + L"Prevents teammates' misbehaviour (drugs, alcohol, scrounging).\n", // TODO.Translate + L"Can spread propaganda in towns.\n", // TODO.Translate + L"Can gather rumours in towns.\n", // TODO.Translate + L"Can be put undercover in prisons.\n", // TODO.Translate + L"Increases your reputation by %d every day if in good morale.\n", // TODO.Translate + L"+%d to effective hearing range\n", // TODO.Translate }; STR16 gzIMPMinorTraitsHelpTextsNone[]= { diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index fa66ca9ac..392ee481a 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -1942,6 +1942,12 @@ STR16 pPersonnelAssignmentStrings[] = L"Jeniec", L"Szpital", L"Pusty", // Vehicle is empty + L"Więzienny kapuś", // facility: undercover prisoner (snitch) + L"Szerzy propagandę", // facility: spread propaganda + L"Szerzy propagandę", // facility: spread propaganda (globally) + L"Zbiera plotki", // facility: gather rumours + L"Szerzy propagandę", // spread propaganda + L"Zbiera plotki", // gather information }; @@ -1990,6 +1996,12 @@ STR16 pLongAssignmentStrings[] = L"Jeniec", L"W szpitalu", // patient in a hospital L"Pusty", // Vehicle is empty + L"Więzienny kapuś", // facility: undercover prisoner (snitch) + L"Szerz propagandę", // facility: spread propaganda + L"Szerz propagandę", // facility: spread propaganda (globally) + L"Zbieraj plotki", // facility: gather rumours + L"Szerz propagandę", // spread propaganda + L"Zbieraj plotki", // gather information }; @@ -2105,7 +2117,8 @@ STR16 pAssignMenuStrings[] = L"Pacjent", // the merc is receiving medical attention L"Pojazd", // the merc is in a vehicle L"Naprawa", // the merc is repairing items - L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Nasłuch", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Kapuś", // anv: snitch actions L"Szkolenie", // the merc is training L"Move Item", // move items // TODO.Translate L"Facility", // the merc is using/staffing a facility // TODO.Translate @@ -2177,6 +2190,80 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", }; +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Drużynowy kapuś", + L"Zlecenie w mieście", + L"Anuluj", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Przedyskutuj zachowanie kapusia względem jego kolegów.", + L"Podejmij zlecenie w sektorze miejskim.", + L"Anuluj", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Zgłaszaj skargi", + L"Nie zgłaszaj skarg", + L"Zapobiegaj złemu zachowaniu", + L"Nie zapobiegaj złemu zachowaniu", + L"Anuluj", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Zgłaszaj swojemu dowódcy wszelkie skargi jakie usłyszysz ze strony pozostałych najemników.", + L"Niczego nie zgłaszaj.", + L"Próbuj powstrzymywać pozostałych najemników przed pijaństwem czy kradzieżami.", + L"Nie zwracaj uwagi na zachowanie pozostałych najemników.", + L"Anuluj", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Szerz propagandę", + L"Zbieraj plotki", + L"Anuluj", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Wychwalaj postępowanie najemników aby podnieść lojalność miasta i zaprzeczaj wszelkim negatywnym doniesieniom.", + L"Nasłuchuj wszelkich pogłosek o wrogiej aktywności.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s został zdemaskowany jako kapuś, ale w porę to spostrzegł i zdołał ujść z życiem.", + L"%s został zdemaskowany jako kapuś, ale zdołał załagodzić sytuację i ujść z życiem.", + L"%s został zdemaskowany jako kapuś, ale zdołał uniknąć próby zamachu.", + L"%s został zdemaskowany jako kapuś, ale strażnicy zdołali zapobiec wybuchowi agresji wśród więźniów.", + + L"%s został zdemaskowany jako kapuś i niemal utopiony przez współwięźniów nim strażnicy zdołali go uratować.", + L"%s został zdemaskowany jako kapuś i niemal pobity na śmierć przez współwięźniów nim strażnicy zdołali go uratować.", + L"%s został zdemaskowany jako kapuś i niemal zasztyletowany przez współwięźniów nim strażnicy zdołali go uratować.", + L"%s został zdemaskowany jako kapuś i niemal uduszony przez współwięźniów nim strażnicy zdołali go uratować.", + + L"%s został zdemaskowany jako kapuś i utopiony w kiblu przez współwięźniów.", + L"%s został zdemaskowany jako kapuś i pobity na śmierć przez współwięźniów.", + L"%s został zdemaskowany jako kapuś i zasztyletowany przez współwięźniów.", + L"%s został zdemaskowany jako kapuś i uduszony przez współwięźniów.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s słyszał pogłoski o aktywnośći wroga w %d sektorach.", + +}; + STR16 pRemoveMercStrings[] = { L"Usuń najemnika", // remove dead merc from current team @@ -7025,6 +7112,8 @@ STR16 gzFacilityErrorMessage[]= L"%s doznaje ciężkich obrażeń w sektorze %s", // %s was injured in sector %s. // <--- This is a log message string. // 31 - 35 L"%s doznaje ciężkich obrażeń w sektorze %s", //<--- This is a log message string. + L"Obecni więźniowie zdają sobie sprawę, iż %s jest najemnikiem.", + L"%s jest obecnie powszechnie znany jako kapuś. Odczekaj przynajmniej %d godzin(ę).", }; diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 4443cd4f0..cfc8e9277 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -1934,6 +1934,12 @@ STR16 pPersonnelAssignmentStrings[] = L"В плену", L"Госпиталь", L"Пуст", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gathering Rumours",// TODO.Translate // facility: gather rumours + L"Spreading Propaganda",// TODO.Translate // spread propaganda + L"Gathering Rumours",// TODO.Translate // gather information }; @@ -1982,6 +1988,12 @@ STR16 pLongAssignmentStrings[] = L"В плену", L"В госпитале", // patient in a hospital L"Без пассажиров", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gather Rumours",// TODO.Translate // facility: gather rumours + L"Spread Propaganda",// TODO.Translate // spread propaganda + L"Gather Rumours",// TODO.Translate // gather information }; @@ -2098,6 +2110,7 @@ STR16 pAssignMenuStrings[] = L"Машина", // the merc is in a vehicle L"Ремонт", // the merc is repairing items L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // TODO.Translate // anv: snitch actions L"Обучение", // the merc is training L"Move Item", // move items // TODO.Translate L"Удобства", // the merc is using/staffing a facility //Facility @@ -2169,6 +2182,82 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", }; +// TODO.Translate +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; +// /TODO.Translate + STR16 pRemoveMercStrings[] = { L"Убрать бойца", // remove dead merc from current team @@ -7007,6 +7096,8 @@ STR16 gzFacilityErrorMessage[]= L"%s получил(а) травму в секторе %s.", // 31 - 35 L"%s получил(а) серьёзную травму в секторе %s.", + L"There are currently prisoners here who are aware of %s's identity.", // TODO.Translate + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", // TODO.Translate }; diff --git a/Utils/_TaiwaneseText.cpp b/Utils/_TaiwaneseText.cpp index 6af8a9a45..caf8e3fea 100644 --- a/Utils/_TaiwaneseText.cpp +++ b/Utils/_TaiwaneseText.cpp @@ -1934,6 +1934,12 @@ STR16 pPersonnelAssignmentStrings[] = L"POW", L"Hospital", L"Empty", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda + L"Spreading Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gathering Rumours",// TODO.Translate // facility: gather rumours + L"Spreading Propaganda",// TODO.Translate // spread propaganda + L"Gathering Rumours",// TODO.Translate // gather information }; @@ -1982,6 +1988,12 @@ STR16 pLongAssignmentStrings[] = L"POW", L"Hospital", // patient in a hospital L"Empty", // Vehicle is empty + L"Undercover Snitch", // TODO.Translate // facility: undercover prisoner (snitch) + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda + L"Spread Propaganda",// TODO.Translate // facility: spread propaganda (globally) + L"Gather Rumours",// TODO.Translate // facility: gather rumours + L"Spread Propaganda",// TODO.Translate // spread propaganda + L"Gather Rumours",// TODO.Translate // gather information }; @@ -2098,6 +2110,7 @@ STR16 pAssignMenuStrings[] = L"Vehicle", // the merc is in a vehicle L"Repair", // the merc is repairing items L"Radio Scan", // Flugente: the merc is scanning for patrols in neighbouring sectors + L"Snitch", // TODO.Translate // anv: snitch actions L"Train", // the merc is training L"Move Item", // move items // TODO.Translate L"Facility", // the merc is using/staffing a facility // TODO.Translate @@ -2169,6 +2182,82 @@ STR16 pTraitSkillsDenialStrings[] = L" - possession by a demon", }; +// TODO.Translate +STR16 pSnitchMenuStrings[] = +{ + // snitch + L"Team Informant", + L"Town Assignment", + L"Cancel", +}; + +STR16 pSnitchMenuDescStrings[] = +{ + // snitch + L"Discuss snitch's behaviour towards his teammates.", + L"Take an assignment in this sector.", + L"Cancel", +}; + +STR16 pSnitchToggleMenuStrings[] = +{ + // toggle snitching + L"Report complaints", + L"Don't report", + L"Prevent misbehaviour", + L"Ignore misbehaviour", + L"Cancel", +}; + +STR16 pSnitchToggleMenuDescStrings[] = +{ + L"Report any complaints you hear from other mercs to your commander.", + L"Don't report anything.", + L"Try to stop other mercs from getting wasted and scrounging.", + L"Don't care what other mercs do.", + L"Cancel", +}; + +STR16 pSnitchSectorMenuStrings[] = +{ + // sector assignments + L"Spread propaganda", + L"Gather rumours", + L"Cancel", +}; + +STR16 pSnitchSectorMenuDescStrings[] = +{ + L"Glorify mercs' actions to increase town loyalty and suppress any bad news. ", + L"Keep an ear to the ground on any rumours about enemy forces activity.", + L"", +}; + +STR16 pSnitchPrisonExposedStrings[] = +{ + L"%s was exposed as a snitch but managed to notice it and get out alive.", + L"%s was exposed as a snitch but managed to defuse situation and get out alive.", + L"%s was exposed as a snitch but managed to avoid assassination attempt.", + L"%s was exposed as a snitch but guards managed to prevent any violence outbursts.", + + L"%s was exposed as a snitch and almost drowned by other inmates before guards saved him.", + L"%s was exposed as a snitch and almost beaten to death before guards saved him.", + L"%s was exposed as a snitch and almost stabbed to death before guards saved him.", + L"%s was exposed as a snitch and strangled to death before guards saved him.", + + L"%s was exposed as a snitch and drowned in toilet by other inmates.", + L"%s was exposed as a snitch and beaten to death by other inmates.", + L"%s was exposed as a snitch and shanked to death by other inmates.", + L"%s was exposed as a snitch and strangled to death by other inmates.", +}; + +STR16 pSnitchGatheringRumoursResultStrings[] = +{ + L"%s heard rumours about enemy activity in %d sectors.", + +}; +// /TODO.Translate + STR16 pRemoveMercStrings[] = { L"Remove Merc", // remove dead merc from current team @@ -7013,6 +7102,8 @@ STR16 gzFacilityErrorMessage[]= L"%s was injured in sector %s.", // <--- This is a log message string. // 31 - 35 L"%s was severely injured in sector %s.", //<--- This is a log message string. + L"There are currently prisoners here who are aware of %s's identity.", // TODO.Translate + L"%s is currently well known as a mercenary snitch. Wait at least %d more hours.", // TODO.Translate };