diff --git a/GameSettings.cpp b/GameSettings.cpp index a248746a..dc3a7c9a 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1731,8 +1731,8 @@ void LoadGameExternalOptions() gGameExternalOptions.fZombieOnlyHeadShotsPermanentlyKill = iniReader.ReadBoolean("Tactical Zombie Settings", "ZOMBIE_ONLY_HEADSHOTS_PERMANENTLY_KILL", TRUE); //################# Corpse Settings ################## - gGameExternalOptions.usCorpseDelayUntilRotting = iniReader.ReadInteger( "Corpse Settings", "CORPSE_DELAY_UNTIL_ROTTING", NUM_SEC_IN_DAY / 60, 720, 7 * NUM_SEC_IN_DAY / 60 ); - gGameExternalOptions.usCorpseDelayUntilDoneRotting = iniReader.ReadInteger( "Corpse Settings", "CORPSE_DELAY_UNTIL_DONE_ROTTING", 3 * NUM_SEC_IN_DAY / 60, NUM_SEC_IN_DAY / 60, 14 * NUM_SEC_IN_DAY / 60 ); + gGameExternalOptions.usCorpseDelayUntilRotting = iniReader.ReadInteger( "Corpse Settings", "CORPSE_DELAY_UNTIL_ROTTING", NUM_SEC_IN_DAY / 60, 0, 7 * NUM_SEC_IN_DAY / 60 ); + gGameExternalOptions.usCorpseDelayUntilDoneRotting = iniReader.ReadInteger( "Corpse Settings", "CORPSE_DELAY_UNTIL_DONE_ROTTING", 3 * NUM_SEC_IN_DAY / 60, 0, 14 * NUM_SEC_IN_DAY / 60 ); //################# Tactical Fortification Settings ################## gGameExternalOptions.fFortificationAllowInHostileSector = iniReader.ReadBoolean("Tactical Fortification Settings", "FORTIFICATION_ALLOW_IN_HOSTILE_SECTOR", FALSE); diff --git a/GameVersion.cpp b/GameVersion.cpp index 301a5bc8..4024b8c2 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -55,8 +55,8 @@ #endif -CHAR8 czVersionNumber[16] = { "Build 18.07.25" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 18.08.12" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; -CHAR16 zRevisionNumber[16] = { L"Revision 8588" }; +CHAR16 zRevisionNumber[16] = { L"Revision 8591" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/GameVersion.h b/GameVersion.h index b2257670..00ce212c 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -22,6 +22,7 @@ extern CHAR16 zRevisionNumber[16]; // Keeps track of the saved game version. Increment the saved game version whenever // you will invalidate the saved game file +#define CORPSE_DISPOSAL 179 // Flugente: corpses can be removed by assignment #define RAID_EVENTS 178 // Flugente: added bloodcat/zombie/bandit raids #define INDIVIDUAL_MILITIA_EXP_FLOAT 177 // Flugente: changed the way we store individual militia experience #define CHAT_TO_DISTRACT 176 // Flugente: internal variable allows us to distract enemies by engrossing them in conversation @@ -98,7 +99,7 @@ extern CHAR16 zRevisionNumber[16]; #define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes #define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system -#define SAVE_GAME_VERSION RAID_EVENTS +#define SAVE_GAME_VERSION CORPSE_DISPOSAL //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index d1affbfe..381b640b 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -145,6 +145,7 @@ enum{ enum { DISEASE_MENU_DIAGNOSE, DISEASE_MENU_SECTOR_TREATMENT, + DISEASE_MENU_BURIAL, DISEASE_MENU_CANCEL, }; @@ -491,7 +492,7 @@ void HandleRadioScanInSector( INT16 sMapX, INT16 sMapY, INT8 bZ ); // Flugente: disease void HandleDiseaseDiagnosis(); -void HandleDiseaseSectorTreatment( ); +void HandleStrategicDiseaseAndBurial( ); // Flugente: fortification void HandleFortification(); @@ -1002,7 +1003,7 @@ BOOLEAN CanCharacterTreatSectorDisease( SOLDIERTYPE *pSoldier ) SECTORINFO *pSectorInfo = &(SectorInfo[sector]); // we can only treat disease if we have data on it - either our team diagnosed it, or the WHO did and we have access to their data - if ( pSectorInfo && ((pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER) || (gubFact[FACT_DISEASE_WHODATA_ACCESS] && pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_WHO)) ) + if ( pSectorInfo && ((pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER) || gubFact[FACT_DISEASE_WHODATA_ACCESS] ) ) return TRUE; // all criteria fit, can doctor @@ -1055,6 +1056,27 @@ BOOLEAN CanCharacterSpyAssignment( SOLDIERTYPE *pSoldier ) return TRUE; } +BOOLEAN CanCharacterBurial( SOLDIERTYPE *pSoldier ) +{ + if ( !gGameExternalOptions.fDisease || !gGameExternalOptions.fDiseaseStrategic ) + return FALSE; + + AssertNotNIL( pSoldier ); + + if ( !BasicCanCharacterAssignment( pSoldier, TRUE ) ) + return( FALSE ); + + if ( pSoldier->bSectorZ ) + return FALSE; + + SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( pSoldier->sSectorX, pSoldier->sSectorY )] ); + + if ( !pSectorInfo || (!( pSectorInfo->uiFlags & SF_ROTTING_CORPSE_TEMP_FILE_EXISTS ) && !pSectorInfo->usNumCorpses ) ) + return FALSE; + + return TRUE; +} + BOOLEAN IsAnythingAroundForSoldierToRepair( SOLDIERTYPE * pSoldier ) { AssertNotNIL(pSoldier); @@ -2895,7 +2917,7 @@ void UpdateAssignments() // Flugente: disease HandleDisease(); HandleDiseaseDiagnosis(); // this must come after HandleDisease() so we discover fresh infections - HandleDiseaseSectorTreatment(); + HandleStrategicDiseaseAndBurial(); // Flugente: PMC recruits new personnel HourlyUpdatePMC(); @@ -6228,8 +6250,8 @@ void HandleDiseaseDiagnosis() SECTORINFO *pSectorInfo = &(SectorInfo[sector]); - if ( pSectorInfo && pSectorInfo->usInfected && - !((pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER) || (gubFact[FACT_DISEASE_WHODATA_ACCESS] && pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_WHO)) && + if ( pSectorInfo && pSectorInfo->fDiseasePoints && + !(pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER) && Chance( skill ) ) { pSectorInfo->usInfectionFlag |= SECTORDISEASE_DIAGNOSED_PLAYER; @@ -6242,57 +6264,236 @@ void HandleDiseaseDiagnosis() } } +extern BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, std::vector aCorpseDefVector ); + // handle treating the population (NOT our mercs) against diseases // our mercs are healed via the regular doctoring procedure -void HandleDiseaseSectorTreatment() +void HandleStrategicDiseaseAndBurial() { // requires dieases, duh if ( !gGameExternalOptions.fDisease || !gGameExternalOptions.fDiseaseStrategic ) return; - // every merc on diagnosis examines every other merc in this sector for diseases that are currently now known - // depending on his skills how far an infection has gotten, the infection will be made public, giving us more time to cure it + UINT32 currenttime = GetWorldTotalMin(); + + // turn corpses into disease once they are old enough + for ( INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) + { + for ( INT16 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( sX, sY )] ); + + if ( pSectorInfo ) + { + if ( ( pSectorInfo->uiFlags & SF_ROTTING_CORPSE_TEMP_FILE_EXISTS ) || pSectorInfo->usNumCorpses ) + { + // determine corpse removal points of all mercs on assignment here + FLOAT corpseremovalpoints = pSectorInfo->dBurial_UnappliedProgress; + + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt = 0; + for ( uiCnt = 0, pSoldier = MercPtrs[uiCnt]; uiCnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++uiCnt, ++pSoldier ) + { + if ( pSoldier->bActive && pSoldier->bAssignment == BURIAL && !pSoldier->flags.fMercAsleep && + pSoldier->sSectorX == sX && pSoldier->sSectorY == sY && !pSoldier->bSectorZ && EnoughTimeOnAssignment( pSoldier ) ) + { + corpseremovalpoints += pSoldier->GetBurialPoints( NULL ); + } + } + + INT32 corpsesremoved_burial = 0; + INT32 corpsesremoved_rot = 0; + + // open corpse table, check them for age, remove those ones old enough and add disease and a loyalty penalty + if ( sX == gWorldSectorX && sY == gWorldSectorY ) + { + INT32 corpsesleft = 0; + + for ( INT32 iCount = 0; iCount < giNumRottingCorpse; ++iCount ) + { + if ( ( gRottingCorpse[iCount].fActivated ) ) + { + if ( corpseremovalpoints >= CORPSEREMOVALPOINTSPERCORPSE ) + { + corpseremovalpoints -= CORPSEREMOVALPOINTSPERCORPSE; + + RemoveCorpse( iCount ); + + ++corpsesremoved_burial; + } + else if ( ( ( currenttime - gRottingCorpse[iCount].def.uiTimeOfDeath ) > gGameExternalOptions.usCorpseDelayUntilDoneRotting ) ) + { + // add disease + pSectorInfo->fDiseasePoints = min( DISEASE_MAX_SECTOR, pSectorInfo->fDiseasePoints + DISEASE_PER_ROTTINGCORPSE ); + + RemoveCorpse( iCount ); + + ++corpsesremoved_rot; + } + else + { + ++corpsesleft; + } + } + } + + pSectorInfo->usNumCorpses = corpsesleft; + } + else + { + HWFILE hFile; + UINT32 uiNumBytesRead = 0; + CHAR8 zMapName[128]; + UINT32 uiNumberOfCorpses = 0; + ROTTING_CORPSE_DEFINITION def; + std::vector corpsedefvector; + + GetMapTempFileName( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, zMapName, sX, sY, 0 ); + + //Check to see if the file exists + if ( FileExists( zMapName ) ) + { + //Open the file for reading + hFile = FileOpen( zMapName, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE ); + if ( hFile != 0 ) + { + // Load the number of Rotting corpses + FileRead( hFile, &uiNumberOfCorpses, sizeof( UINT32 ), &uiNumBytesRead ); + if ( uiNumBytesRead != sizeof( UINT32 ) ) + { + // Error Writing size of array to disk + FileClose( hFile ); + } + else + { + // we loop over all corpses and remove some of them, either by rotting or assignment + // if we chang anything, we save the now reduced array + for ( UINT32 cnt = 0; cnt < uiNumberOfCorpses; ++cnt ) + { + // Load the Rotting corpses info + FileRead( hFile, &def, sizeof( ROTTING_CORPSE_DEFINITION ), &uiNumBytesRead ); + if ( uiNumBytesRead != sizeof( ROTTING_CORPSE_DEFINITION ) ) + { + //Error Writing size of array to disk + continue; + } + + if ( corpseremovalpoints >= CORPSEREMOVALPOINTSPERCORPSE ) + { + corpseremovalpoints -= CORPSEREMOVALPOINTSPERCORPSE; + + ++corpsesremoved_burial; + } + else if ( ( ( currenttime - def.uiTimeOfDeath ) > gGameExternalOptions.usCorpseDelayUntilDoneRotting ) ) + { + // add disease + pSectorInfo->fDiseasePoints = min( DISEASE_MAX_SECTOR, pSectorInfo->fDiseasePoints + DISEASE_PER_ROTTINGCORPSE); + + ++corpsesremoved_rot; + } + else + { + corpsedefvector.push_back( def ); + } + } + + FileClose( hFile ); + + pSectorInfo->usNumCorpses = corpsedefvector.size(); + + // now save the corpses under the same filename + if ( corpsesremoved_burial + corpsesremoved_rot ) + SaveRottingCorpsesToTempCorpseFile( sX, sY, 0, corpsedefvector ); + } + } + } + } + + // the population doesn't like it when their neighbourhood suffers from disease + if ( corpsesremoved_rot ) + { + INT8 bTownId = GetTownIdForSector( sX, sY ); + + // if NOT in a town + if ( bTownId != BLANK_SECTOR ) + { + UINT32 uiLoyaltyChange = corpsesremoved_rot * LOYALTY_PENALTY_ROTTED_CORPSE; + DecrementTownLoyalty( bTownId, uiLoyaltyChange ); + } + } + + // if we removed corpses, award experience to the undertakers + if ( corpsesremoved_burial ) + { + for ( uiCnt = 0, pSoldier = MercPtrs[uiCnt]; uiCnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++uiCnt, ++pSoldier ) + { + if ( pSoldier->bActive && pSoldier->bAssignment == BURIAL && !pSoldier->flags.fMercAsleep && + pSoldier->sSectorX == sX && pSoldier->sSectorY == sY && !pSoldier->bSectorZ && EnoughTimeOnAssignment( pSoldier ) ) + { + StatChange( pSoldier, STRAMT, 8, FALSE ); + } + } + } + + // store unapplied assignment progress + pSectorInfo->dBurial_UnappliedProgress = max( 0.0f, corpseremovalpoints ); + } + + // disease from corpses decays over time + // if this the hospital sector, the amount of doctoring is increased to marvellous levels + if ( sX == gModSettings.ubHospitalSectorX && sY == gModSettings.ubHospitalSectorY ) + pSectorInfo->fDiseasePoints = max( 0.0f, min( pSectorInfo->fDiseasePoints * 0.9f, pSectorInfo->fDiseasePoints - 10.0f ) ); + else + pSectorInfo->fDiseasePoints = max( 0.0f, min( pSectorInfo->fDiseasePoints * 0.98f, pSectorInfo->fDiseasePoints - 2.0f ) ); + } + } + } + + // mercs remove strategic disease SOLDIERTYPE *pSoldier = NULL; UINT32 uiCnt = 0; - for ( uiCnt = 0, pSoldier = MercPtrs[uiCnt]; uiCnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++uiCnt, pSoldier++ ) + for ( uiCnt = 0, pSoldier = MercPtrs[uiCnt]; uiCnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++uiCnt, ++pSoldier ) { - if ( pSoldier->bActive && pSoldier->bAssignment == DISEASE_DOCTOR_SECTOR && CanCharacterTreatSectorDisease( pSoldier ) && !pSoldier->flags.fMercAsleep && EnoughTimeOnAssignment( pSoldier ) ) + if ( pSoldier->bActive && pSoldier->bAssignment == DISEASE_DOCTOR_SECTOR && !pSoldier->bSectorZ && + !pSoldier->flags.fMercAsleep && EnoughTimeOnAssignment( pSoldier ) && CanCharacterTreatSectorDisease( pSoldier ) ) { - MakeSureMedKitIsInHand( pSoldier ); - - // get available healing pts - UINT16 max = 0; - UINT16 ptsavailable = CalculateHealingPointsForDoctor( pSoldier, &max, TRUE ); - - ptsavailable = (ptsavailable * (100 + pSoldier->GetBackgroundValue( BG_PERC_DISEASE_TREAT ))) / 100; - - // calculate how much total points we have in all medical bags - UINT16 usTotalMedPoints = TotalMedicalKitPoints( pSoldier ); - - // doctoring points are limited by medical supplies - ptsavailable = min( ptsavailable, usTotalMedPoints * 100 ); - // if we are doctoring in a sector, then we know for sure that there is disease here - SECTORINFO *pSectorInfo = &(SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ]); + SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( pSoldier->sSectorX, pSoldier->sSectorY )] ); - if ( pSectorInfo && pSectorInfo->usInfected ) + if ( pSectorInfo && pSectorInfo->fDiseasePoints ) + { pSectorInfo->usInfectionFlag |= SECTORDISEASE_DIAGNOSED_PLAYER; - UINT32 ptsused = HealSectorPopulation( pSoldier->sSectorX, pSoldier->sSectorY, ptsavailable ); - - // Finaly use all kit points (we are sure, we have that much) - if ( !UseTotalMedicalKitPoints( pSoldier, ptsused / 100 ) ) - { - // throw message if this went wrong for feedback on debugging -#ifdef JA2TESTVERSION - ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"Warning! UseTotalKitPOints returned false, not all points were probably used." ); -#endif - } + MakeSureMedKitIsInHand( pSoldier ); - // increment skills based on healing pts used - StatChange( pSoldier, MEDICALAMT, (UINT16)(ptsused / 100), FALSE ); - StatChange( pSoldier, DEXTAMT, (UINT16)(ptsused / 100), FALSE ); - StatChange( pSoldier, WISDOMAMT, (UINT16)(ptsused / 100), FALSE ); + // get available healing pts + UINT16 max = 0; + UINT16 ptsavailable = CalculateHealingPointsForDoctor( pSoldier, &max, TRUE ); + + ptsavailable = ( ptsavailable * ( 100 + pSoldier->GetBackgroundValue( BG_PERC_DISEASE_TREAT ) ) ) / 100; + + // calculate how much total points we have in all medical bags + UINT16 usTotalMedPoints = TotalMedicalKitPoints( pSoldier ); + + // doctoring points are limited by medical supplies + ptsavailable = min( ptsavailable, usTotalMedPoints * 100 ); + + UINT32 ptsused = HealSectorPopulation( pSoldier->sSectorX, pSoldier->sSectorY, ptsavailable ); + + // Finaly use all kit points (we are sure, we have that much) + if ( !UseTotalMedicalKitPoints( pSoldier, ptsused / 100 ) ) + { + // throw message if this went wrong for feedback on debugging +#ifdef JA2TESTVERSION + ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"Warning! UseTotalMedicalKitPoints returned false, not all points were probably used." ); +#endif + } + + // increment skills based on healing pts used + StatChange( pSoldier, MEDICALAMT, 3, FALSE ); + StatChange( pSoldier, DEXTAMT, 1, FALSE ); + StatChange( pSoldier, WISDOMAMT, 1, FALSE ); + } } } } @@ -17572,6 +17773,10 @@ void ReEvaluateEveryonesNothingToDo( BOOLEAN aDoExtensiveCheck ) fNothingToDo = !CanCharacterDrillMilitia( pSoldier ); break; + case BURIAL: + fNothingToDo = !CanCharacterBurial( pSoldier ); + break; + case VEHICLE: default: // squads fNothingToDo = FALSE; @@ -17909,6 +18114,15 @@ void SetAssignmentForList( INT8 bAssignment, INT8 bParam ) } break; + case BURIAL: + if ( CanCharacterBurial( pSoldier ) ) + { + pSoldier->bOldAssignment = pSoldier->bAssignment; + SetSoldierAssignment( pSoldier, bAssignment, bParam, 0, 0 ); + fItWorked = TRUE; + } + break; + case( SQUAD_1 ): case( SQUAD_2 ): case( SQUAD_3 ): @@ -21645,6 +21859,7 @@ BOOLEAN DisplayDiseaseMenu( SOLDIERTYPE *pSoldier ) AddMonoString( (UINT32 *)&hStringHandle, szDiseaseText[TEXT_DISEASE_DIAGNOSIS] ); AddMonoString( (UINT32 *)&hStringHandle, szDiseaseText[TEXT_DISEASE_TREATMENT] ); + AddMonoString( (UINT32 *)&hStringHandle, szDiseaseText[TEXT_DISEASE_BURIAL] ); // cancel AddMonoString( (UINT32 *)&hStringHandle, szDiseaseText[TEXT_DISEASE_CANCEL] ); @@ -21672,6 +21887,7 @@ void HandleShadingOfLinesForDiseaseMenu( void ) return; } + UnShadeStringInBox( ghDiseaseBox, iCount++ ); UnShadeStringInBox( ghDiseaseBox, iCount++ ); UnShadeStringInBox( ghDiseaseBox, iCount++ ); @@ -21740,7 +21956,15 @@ void CreateDestroyMouseRegionForDiseaseMenu( void ) MSYS_SetRegionUserData( &gDisease[iCount], 0, iCount ); MSYS_SetRegionUserData( &gDisease[iCount], 1, iCount ); ++iCount; - + + // burial assignment + MSYS_DefineRegion( &gDisease[iCount], (INT16)( iBoxXPosition ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + (iFontHeight)* iCount ), (INT16)( iBoxXPosition + iBoxWidth ), (INT16)( iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + ( iFontHeight )* ( iCount + 1 ) ), MSYS_PRIORITY_HIGHEST - 4, + MSYS_NO_CURSOR, DiseaseMenuMvtCallback, DiseaseMenuBtnCallback ); + + MSYS_SetRegionUserData( &gDisease[iCount], 0, iCount ); + MSYS_SetRegionUserData( &gDisease[iCount], 1, iCount ); + ++iCount; + // cancel MSYS_DefineRegion( &gDisease[iCount], (INT16)(iBoxXPosition), (INT16)(iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + (iFontHeight)* iCount), (INT16)(iBoxXPosition + iBoxWidth), (INT16)(iBoxYPosition + GetTopMarginSize( ghAssignmentBox ) + (iFontHeight)* (iCount + 1)), MSYS_PRIORITY_HIGHEST - 4, MSYS_NO_CURSOR, DiseaseMenuMvtCallback, DiseaseMenuBtnCallback ); @@ -21801,6 +22025,8 @@ void DiseaseMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason ) INT8 newassignment = DISEASE_DIAGNOSE; if ( iWhat == DISEASE_MENU_SECTOR_TREATMENT ) newassignment = DISEASE_DOCTOR_SECTOR; + else if ( iWhat == DISEASE_MENU_BURIAL ) + newassignment = BURIAL; if ( pSoldier->bAssignment != newassignment ) { diff --git a/Strategic/Assignments.h b/Strategic/Assignments.h index e5611e4d..a15e5dc8 100644 --- a/Strategic/Assignments.h +++ b/Strategic/Assignments.h @@ -96,6 +96,7 @@ enum GATHERINTEL, // gathers information while disguised in enemy territory DOCTOR_MILITIA, // heal militia DRILL_MILITIA, // train existing militia (does not create new ones) + BURIAL, // merc removes corpses in this sector NUM_ASSIGNMENTS, }; @@ -187,6 +188,8 @@ BOOLEAN CanCharacterFortify( SOLDIERTYPE *pSoldier ); BOOLEAN CanCharacterSpyAssignment( SOLDIERTYPE *pSoldier ); +BOOLEAN CanCharacterBurial( SOLDIERTYPE *pSoldier ); + // can this character be assigned as a repairman? BOOLEAN CanCharacterRepair( SOLDIERTYPE *pCharacter ); diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index 3fcc6d7c..a41db8df 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -4799,10 +4799,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget ) { AddRaidPersonnel( -( pTarget->pSoldier->ubBodyType == BLOODCAT ), -( pTarget->pSoldier->ubSoldierClass == SOLDIER_CLASS_ZOMBIE ), -( pTarget->pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT ) ); } - - // Flugente: disease - HandleDeathDiseaseImplications( pTarget->pSoldier ); - + if( pAttacker->uiFlags & CELL_MERC ) { //Player killed the enemy soldier -- update his stats as well as any assisters. ///////////////////////////////////////////////////////////////////////////////////// @@ -5028,10 +5025,7 @@ void TargetHitCallback( SOLDIERCELL *pTarget, INT32 index ) { AddRaidPersonnel( -( pTarget->pSoldier->ubBodyType == BLOODCAT ), -( pTarget->pSoldier->ubSoldierClass == SOLDIER_CLASS_ZOMBIE ), -( pTarget->pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT ) ); } - - // Flugente: disease - HandleDeathDiseaseImplications( pTarget->pSoldier ); - + //soldier has been killed if( pTarget->pAttacker[ index ]->uiFlags & CELL_PLAYER ) { //Player killed the enemy soldier -- update his stats as well as any assisters. diff --git a/Strategic/Campaign Types.h b/Strategic/Campaign Types.h index e8ca7aee..80f53977 100644 --- a/Strategic/Campaign Types.h +++ b/Strategic/Campaign Types.h @@ -518,9 +518,9 @@ typedef struct SECTORINFO UINT8 ubTanksInBattle; // Flugente: disease - UINT16 usInfected; // how many people (civilians + enemy + militia) are infected in this sector? Does NOT count our mercs - FLOAT fInfectionSeverity; // mean infection rate of those infected (percentage) - UINT8 usDiseaseDoctoringDelay; // AI doctoring in this sector is delayed due to player interference + UINT16 usNumCorpses; // number of corpses in this sector + FLOAT fDiseasePoints; // disease points + UINT8 bFiller4; UINT8 usInfectionFlag; // Flugente: fortification @@ -537,7 +537,10 @@ typedef struct SECTORINFO // Flugente: localized weather UINT32 usWeather; - INT8 bPadding[ 16 ]; + // Flugente: burial assignment + FLOAT dBurial_UnappliedProgress; // progress done via assignment work. This way no work gets lost + + INT8 bPadding[ 12 ]; }SECTORINFO; diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 128fbfbe..8d7aa696 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -705,46 +705,43 @@ void HandleShowingOfEnemiesWithMilitiaOn( void ) // aType = 2: intel INT32 GetMapColour( INT16 sX, INT16 sY, UINT8 aType ) { + UINT8 sector = SECTOR( sX, sY ); + if ( aType == 0 ) - { - UINT16 population = GetSectorPopulation( sX, sY ); + { + SECTORINFO *pSectorInfo = &( SectorInfo[sector] ); - if ( population ) + // display sector information only if we know about infection there + if ( pSectorInfo && ( ( pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER ) || gubFact[FACT_DISEASE_WHODATA_ACCESS] ) ) { - UINT8 sector = SECTOR( sX, sY ); + FLOAT diseaseratio = pSectorInfo->fDiseasePoints / DISEASE_MAX_SECTOR; - SECTORINFO *pSectorInfo = &( SectorInfo[sector] ); - - // display sector information only if we know about infection there - if ( pSectorInfo && ( ( pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER ) || ( gubFact[FACT_DISEASE_WHODATA_ACCESS] && pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_WHO ) ) ) - { - FLOAT infectedpercentage = (FLOAT)pSectorInfo->usInfected / (FLOAT)( population ); - - if ( infectedpercentage < 0.2f ) - return MAP_SHADE_DK_GREEN; - else if ( infectedpercentage < 0.3f ) - return MAP_SHADE_MD_GREEN; - else if ( infectedpercentage < 0.4f ) - return MAP_SHADE_LT_GREEN; - else if ( infectedpercentage < 0.5f ) - return MAP_SHADE_DK_YELLOW; - else if ( infectedpercentage < 0.6f ) - return MAP_SHADE_MD_YELLOW; - else if ( infectedpercentage < 0.7f ) - return MAP_SHADE_LT_YELLOW; - else if ( infectedpercentage < 0.8f ) - return MAP_SHADE_DK_RED; - else if ( infectedpercentage < 0.9f ) - return MAP_SHADE_MD_RED; - else - return MAP_SHADE_LT_RED; - } + if ( pSectorInfo->fDiseasePoints < 0.1f ) + return MAP_SHADE_BLACK; + else if ( diseaseratio < 0.05f ) + return MAP_SHADE_DK_GREEN; + else if ( diseaseratio < 0.1f ) + return MAP_SHADE_MD_GREEN; + else if ( diseaseratio < 0.2f ) + return MAP_SHADE_LT_GREEN; + else if ( diseaseratio < 0.3f ) + return MAP_SHADE_DK_YELLOW; + else if ( diseaseratio < 0.4f ) + return MAP_SHADE_MD_YELLOW; + else if ( diseaseratio < 0.5f ) + return MAP_SHADE_LT_YELLOW; + else if ( diseaseratio < 0.65f ) + return MAP_SHADE_ORANGE; + else if ( diseaseratio < 0.8f ) + return MAP_SHADE_DK_RED; + else if ( diseaseratio < 0.9f ) + return MAP_SHADE_MD_RED; + else + return MAP_SHADE_LT_RED; } } else if ( aType == 1 ) { - UINT8 sector = SECTOR( sX, sY ); - SECTORINFO *pSectorInfo = &( SectorInfo[sector] ); // display sector information only if we know about infection there @@ -773,8 +770,6 @@ INT32 GetMapColour( INT16 sX, INT16 sY, UINT8 aType ) } else if ( aType == 2 ) { - UINT8 sector = SECTOR( sX, sY ); - return gMapIntelData[sector].mapcolour; } @@ -7248,7 +7243,6 @@ void ShowDiseaseOnMap() } SetFont(MapItemsFont); - SetFontForeground(FONT_MCOLOR_LTGREEN); SetFontBackground(FONT_MCOLOR_BLACK); // run through sectors @@ -7260,42 +7254,34 @@ void ShowDiseaseOnMap() SECTORINFO *pSectorInfo = &(SectorInfo[sector]); - if ( pSectorInfo && ((pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER) || (gubFact[FACT_DISEASE_WHODATA_ACCESS] && pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_WHO)) ) + if ( pSectorInfo && ((pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER) || gubFact[FACT_DISEASE_WHODATA_ACCESS] ) ) { - // hide this information, as it might allow the player to deduct enemy positions and numbers - /*{ - UINT16 population = GetSectorPopulation( sMapX, sMapY ); - - if ( population ) - { - sXCorner = (INT16)(MAP_VIEW_START_X + (sMapX * MAP_GRID_X)); - sYCorner = (INT16)(MAP_VIEW_START_Y + (sMapY * MAP_GRID_Y)); - - SetFontForeground( FONT_MCOLOR_WHITE ); - if ( pSectorInfo->usInfectionFlag & SECTORDISEASE_OUTBREAK ) - swprintf( sString, L"%d/%d", pSectorInfo->usInfected, population ); - else - swprintf( sString, L"%d", population ); - - FindFontCenterCoordinates( sXCorner, sYCorner, MAP_GRID_X, MAP_GRID_Y, sString, MapItemsFont, &usXPos, &usYPos ); - - mprintf( usXPos, usYPos, sString ); - } - }*/ + sXCorner = (INT16)( MAP_VIEW_START_X + ( sMapX * MAP_GRID_X ) ); + sYCorner = (INT16)( MAP_VIEW_START_Y + ( sMapY * MAP_GRID_Y ) ); + if ( pSectorInfo->usNumCorpses > 0 ) { - if ( pSectorInfo->fInfectionSeverity > 0 ) - { - sXCorner = (INT16)(MAP_VIEW_START_X + (sMapX * MAP_GRID_X)); - sYCorner = (INT16)(MAP_VIEW_START_Y + (sMapY * MAP_GRID_Y)); + SetFontForeground( FONT_MCOLOR_WHITE ); - SetFontForeground( FONT_MCOLOR_WHITE ); - swprintf( sString, L"%4.1f%%", 100 * pSectorInfo->fInfectionSeverity ); + swprintf( sString, L"%d", pSectorInfo->usNumCorpses ); - FindFontCenterCoordinates( sXCorner, sYCorner, MAP_GRID_X, MAP_GRID_Y, sString, MapItemsFont, &usXPos, &usYPos ); + FindFontCenterCoordinates( sXCorner, sYCorner, MAP_GRID_X, MAP_GRID_Y, sString, MapItemsFont, &usXPos, &usYPos ); - mprintf( usXPos, usYPos, sString ); - } + mprintf( usXPos, usYPos, sString ); + } + + if ( pSectorInfo->fDiseasePoints > 0 ) + { + SetFontForeground( FONT_MCOLOR_LTGREEN ); + + // as the healing displayed is always divided by 10 (see in face display), we do the same thinh here to not confuse the player + swprintf( sString, L"%6.1f", pSectorInfo->fDiseasePoints / 10.0f ); + + sYCorner += GetFontHeight( MapItemsFont ); + + FindFontCenterCoordinates( sXCorner, sYCorner, MAP_GRID_X, MAP_GRID_Y, sString, MapItemsFont, &usXPos, &usYPos ); + + mprintf( usXPos, usYPos, sString ); } } } diff --git a/Strategic/MilitiaIndividual.cpp b/Strategic/MilitiaIndividual.cpp index 05efd64f..5e065e81 100644 --- a/Strategic/MilitiaIndividual.cpp +++ b/Strategic/MilitiaIndividual.cpp @@ -365,7 +365,17 @@ void HandleHourlyMilitiaHealing( ) { if ( !((*it).flagmask & MILITIAFLAG_DEAD) ) { - (*it).healthratio = min( 100.0f, (*it).healthratio + gGameExternalOptions.dIndividualMilitiaHourlyHealthPercentageGain ); + FLOAT healingmodifier = 1.0f; + + if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[(*it).sector] ); + + if ( pSectorInfo && pSectorInfo->fDiseasePoints ) + healingmodifier -= 2.5f * pSectorInfo->fDiseasePoints / DISEASE_MAX_SECTOR; + } + + (*it).healthratio = min( 100.0f, (*it).healthratio + healingmodifier * gGameExternalOptions.dIndividualMilitiaHourlyHealthPercentageGain ); } } diff --git a/Strategic/MilitiaSquads.cpp b/Strategic/MilitiaSquads.cpp index 9d865be7..973549a4 100644 --- a/Strategic/MilitiaSquads.cpp +++ b/Strategic/MilitiaSquads.cpp @@ -277,9 +277,6 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL // Flugente: update individual militia data ApplyTacticalLifeRatioToMilitia( ); - // Flugente: disease - PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens ); - // Erase ALL militia from both locations. StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] ); StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] ); @@ -321,10 +318,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL // Flugente: update individual militia data ApplyTacticalLifeRatioToMilitia( ); - - // Flugente: disease - PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens ); - + // Remove half team from source sector StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, bGreensDestTeam ); StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, bRegularsDestTeam ); @@ -414,10 +408,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL // Flugente: update individual militia data ApplyTacticalLifeRatioToMilitia( ); - - // Flugente: disease - PopulationMove( sMapX, sMapY, sTMapX, sTMapY, elites + regulars + greens ); - + // Erase ALL militia from both locations. StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] ); StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] ); diff --git a/Strategic/Queen Command.cpp b/Strategic/Queen Command.cpp index 2f1b0849..fd7fd427 100644 --- a/Strategic/Queen Command.cpp +++ b/Strategic/Queen Command.cpp @@ -2131,6 +2131,24 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, ubTotalSoldiers ); #endif + extern INT16 gsStrategicDiseaseOriginSector; + + // Flugente: we need to set the sector of origin to determine from which sector to take the disease ratio that affects health + gsStrategicDiseaseOriginSector = -1; + + if ( !gbWorldSectorZ ) + { + switch ( ubStrategicInsertionCode ) + { + case INSERTION_CODE_NORTH: gsStrategicDiseaseOriginSector = SECTOR( gWorldSectorX, gWorldSectorY - 1 ); break; + case INSERTION_CODE_EAST: gsStrategicDiseaseOriginSector = SECTOR( gWorldSectorX + 1, gWorldSectorY ); break; + case INSERTION_CODE_SOUTH: gsStrategicDiseaseOriginSector = SECTOR( gWorldSectorX, gWorldSectorY + 1 ); break; + case INSERTION_CODE_WEST: gsStrategicDiseaseOriginSector = SECTOR( gWorldSectorX - 1, gWorldSectorY ); break; + default: + break; + } + } + ubCurrSlot = 0; while( ubTotalSoldiers ) { @@ -2265,6 +2283,9 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub gCurrentIncident.usIncidentFlags |= INCIDENT_REINFORCEMENTS_ENEMY; } } + + // set this back so it doesn't affect others + gsStrategicDiseaseOriginSector = -1; #ifdef JA2UB gsGridNoForMapEdgePointInfo = -1; diff --git a/Strategic/Reinforcement.cpp b/Strategic/Reinforcement.cpp index c40b056d..738e1ec0 100644 --- a/Strategic/Reinforcement.cpp +++ b/Strategic/Reinforcement.cpp @@ -226,9 +226,6 @@ UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam { while ( (pGroup = GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam )) != NULL ) { - // Flugente: disease - PopulationMove( pGroup->ubSectorX, pGroup->ubSectorY, sMapX, sMapY, pGroup->ubGroupSize ); - pGroup->ubPrevX = pGroup->ubSectorX; pGroup->ubPrevY = pGroup->ubSectorY; diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index 0bed70c1..ad97423c 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -1932,13 +1932,7 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe return; } - - // Flugente: disease - if ( pGroup->usGroupTeam != OUR_TEAM ) - { - PopulationMove( pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubNextX, pGroup->ubNextY, pGroup->ubGroupSize ); - } - + //Update the position of the group pGroup->ubPrevX = pGroup->ubSectorX; pGroup->ubPrevY = pGroup->ubSectorY; diff --git a/Strategic/Strategic Town Loyalty.h b/Strategic/Strategic Town Loyalty.h index 1f339c97..b87cec02 100644 --- a/Strategic/Strategic Town Loyalty.h +++ b/Strategic/Strategic Town Loyalty.h @@ -47,6 +47,9 @@ //Madd: #define LOYALTY_PENALTY_INACTIVE 0 // (10 * GAIN_PTS_PER_LOYALTY_PT) +// Flugente: a rotting corpse is so decayed that it disappeared (we're the ones making all those corpses, the last we could do is clean up afterwards) +#define LOYALTY_PENALTY_ROTTED_CORPSE (1 * GAIN_PTS_PER_LOYALTY_PT) + typedef enum { // There are only for distance-adjusted global loyalty effects. Others go into list above instead! diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index 2dca871f..d5141eac 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -5593,6 +5593,14 @@ BOOLEAN LoadStrategicInfoFromSavedFile( HWFILE hFile ) SectorInfo[sectorID].usWorkers = SectorExternalData[sectorID][0].maxworkers * gGameExternalOptions.dInitialWorkerRate; SectorInfo[sectorID].ubWorkerTrainingHundredths = 0; } + + if ( guiCurrentSaveGameVersion < CORPSE_DISPOSAL ) + { + SectorInfo[sectorID].usNumCorpses = 0; // this will get updated on the next full hour anyway + SectorInfo[sectorID].fDiseasePoints = 0.0f; + SectorInfo[sectorID].usInfectionFlag &= ~3; + SectorInfo[sectorID].dBurial_UnappliedProgress = 0.0f; + } } // uiSize = sizeof( SECTORINFO ) * 256; diff --git a/Tactical/Disease.cpp b/Tactical/Disease.cpp index d4a8a066..e3fddf57 100644 --- a/Tactical/Disease.cpp +++ b/Tactical/Disease.cpp @@ -124,54 +124,14 @@ void HandleDisease() } } - // we can also be infected by the population + // we can also be infected by the disease left from corpses if ( gGameExternalOptions.fDiseaseStrategic ) { - UINT16 population = GetSectorPopulation( pSoldier->sSectorX, pSoldier->sSectorY ); + SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( pSoldier->sSectorX, pSoldier->sSectorY )] ); - if ( population ) + if ( pSectorInfo && pSectorInfo->fDiseasePoints ) { - UINT8 sector = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ); - - SECTORINFO *pSectorInfo = &(SectorInfo[sector]); - - if ( pSectorInfo ) - { - // if there are infected people, we might get an infection (disease 0 only) - if ( pSectorInfo->usInfected ) - { - // infection is also possible by human contact - FLOAT dChance = Disease[0].dInfectionChance[INFECTION_TYPE_CONTACT_HUMAN]; - - // if disease is known, mercs will avoid the infected, lowering the chance of them being infected - UINT16 max = min(20, pSectorInfo->usInfected); - if ( (pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_PLAYER) || (gubFact[FACT_DISEASE_WHODATA_ACCESS] && pSectorInfo->usInfectionFlag & SECTORDISEASE_DIAGNOSED_WHO) ) - max /= 4; - - for ( UINT16 i = 0; i < max; ++i ) - { - // chances can be smaller than 1%, so we use a trick here by altering our 'chance function'. This allows to have much smaller chances, as for diseases, 1% can be way too high. - if ( Random( 10000 ) < dChance * 100 ) - HandlePossibleInfection( pSoldier, NULL, INFECTION_TYPE_CONTACT_HUMAN, 1.0f, TRUE ); - } - } - - // if we are infected, WE might infect other people - if ( pSoldier->sDiseasePoints[0] > 0 ) - { - if ( pSectorInfo->usInfected < population ) - { - // chances can be smaller than 1%, so we use a trick here by altering our 'chance function'. This allows to have much smaller chances, as for diseases, 1% can be way too high. - if ( Random( 10000 ) < Disease[0].dInfectionChance[INFECTION_TYPE_CONTACT_HUMAN] * 100 ) - { - FLOAT infectedseverity = (FLOAT)Disease[0].sInfectionPtsInitial / (FLOAT)Disease[0].sInfectionPtsFull; - - pSectorInfo->fInfectionSeverity = (pSectorInfo->fInfectionSeverity * pSectorInfo->usInfected + infectedseverity * 1) / (pSectorInfo->usInfected + 1); - ++pSectorInfo->usInfected; - } - } - } - } + HandlePossibleInfection( pSoldier, NULL, INFECTION_TYPE_CONTACT_CORPSE, ( pSectorInfo->fDiseasePoints / DISEASE_MAX_SECTOR ) ); } } @@ -217,191 +177,6 @@ void HandleDisease() } } } - - // now to handle strategic disease - if ( !gGameExternalOptions.fDiseaseStrategic ) - return; - - for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) - { - for ( UINT8 sY = 1; sY < MAP_WORLD_X - 1; ++sY ) - { - UINT8 sector = SECTOR( sX, sY ); - - SECTORINFO *pSectorInfo = &(SectorInfo[sector]); - - if ( !pSectorInfo ) - continue; - - // first, existing infections get worse - if ( pSectorInfo->fInfectionSeverity > 0 ) - { - pSectorInfo->fInfectionSeverity = min( 1.0f, pSectorInfo->fInfectionSeverity + ( FLOAT )(Disease[0].sInfectionPtsGainPerHour) / (FLOAT)(Disease[0].sInfectionPtsFull) ); - } - - UINT16 population = GetSectorPopulation( sX, sY ); - - if ( population ) - { - // how many people are already infected? - if ( pSectorInfo->usInfected < population ) - { - UINT16 lefttoinfect = population - pSectorInfo->usInfected; - UINT16 newinfected = 0; - - // population might get infected if this a swamp or tropical sector - switch ( SectorInfo[sector].ubTraversability[THROUGH_STRATEGIC_MOVE] ) - { - case TROPICS_SAM_SITE: - case TROPICS: - case TROPICS_ROAD: - { - FLOAT dChance = Disease[0].dInfectionChance[INFECTION_TYPE_TROPICS]; - for ( UINT16 i = 0; i < lefttoinfect; ++i ) - { - // chances can be smaller than 1%, so we use a trick here by altering our 'chance function'. This allows to have much smaller chances, as for diseases, 1% can be way too high. - if ( Random( 10000 ) < dChance * 100 ) - ++newinfected; - } - } - break; - case SWAMP: - case SWAMP_ROAD: - { - FLOAT dChance = Disease[0].dInfectionChance[INFECTION_TYPE_SWAMP]; - for ( UINT16 i = 0; i < lefttoinfect; ++i ) - { - // chances can be smaller than 1%, so we use a trick here by altering our 'chance function'. This allows to have much smaller chances, as for diseases, 1% can be way too high. - if ( Random( 10000 ) < dChance * 100 ) - ++newinfected; - } - } - break; - default: - break; - } - - if ( lefttoinfect - newinfected > 1 && pSectorInfo->usInfected ) - { - // infection is also possible by human contact - FLOAT dChance = Disease[0].dInfectionChance[INFECTION_TYPE_CONTACT_HUMAN]; - UINT16 max = sqrt( (FLOAT) min( lefttoinfect - newinfected, pSectorInfo->usInfected ) ); - for ( UINT16 i = 0; i < max; ++i ) - { - // chances can be smaller than 1%, so we use a trick here by altering our 'chance function'. This allows to have much smaller chances, as for diseases, 1% can be way too high. - if ( Random( 10000 ) < dChance * 100 ) - ++newinfected; - } - } - - if ( lefttoinfect - newinfected > 0 ) - { - // there is also the chance to be infected by bad food, sex, contact with animals etc. - // For now, we assume this to be very rare events, so just add a small chance to be infected this way - FLOAT populationpercentage = (FLOAT)(lefttoinfect - newinfected) / (FLOAT)(population); - FLOAT basechance = sqrt( (FLOAT) min( lefttoinfect, pSectorInfo->usInfected + newinfected ) ) * 0.5f; - - FLOAT chance_sex = Disease[0].dInfectionChance[INFECTION_TYPE_SEX] * basechance * populationpercentage; - FLOAT chance_corpse = 0; - - // if there was a fight here in the last 48 hours, then corpses will still be here - increase chance of infection - if ( pSectorInfo->uiTimeLastPlayerLiberated && pSectorInfo->uiTimeLastPlayerLiberated + (48 * 3600) > GetWorldTotalSeconds( ) ) - chance_corpse = Disease[0].dInfectionChance[INFECTION_TYPE_CONTACT_CORPSE] * populationpercentage; - - // chances can be smaller than 1%, so we use a trick here by altering our 'chance function'. This allows to have much smaller chances, as for diseases, 1% can be way too high. - if ( Random( 10000 ) < chance_sex * 100 ) - ++newinfected; - - if ( Random( 10000 ) < chance_corpse * 100 ) - ++newinfected; - } - - if ( lefttoinfect - newinfected > 0 ) - { - // adjacent sectors can infect us too - for ( UINT8 dir = 0; dir < SP_DIR_MAX; ++dir ) - { - INT16 othersector = GetAdjacentSector( sector, dir ); - - if ( othersector > -1 ) - { - UINT16 population_other = GetSectorPopulation( SECTORX( othersector ), SECTORY( othersector ) ); - SECTORINFO *pSectorInfo_Other = &(SectorInfo[othersector]); - - if ( pSectorInfo_Other && pSectorInfo_Other->usInfected && population_other ) - { - FLOAT infectedothersector = (FLOAT)pSectorInfo_Other->usInfected / (FLOAT)(population_other); - - if ( infectedothersector > DISEASE_STRATEGIC_ADJACENTINFECTION ) - { - FLOAT percentage = (FLOAT)((lefttoinfect - newinfected) * Disease[0].dInfectionChance[INFECTION_TYPE_CONTACT_HUMAN]) / (FLOAT)(100 * population); - - // chances can be smaller than 1%, so we use a trick here by altering ou 'chance function'. This allows to have much smaller chances, as for diseases, 1% can be way too high. - if ( Random( 10000 ) < percentage * 100 * 100 ) - ++newinfected; - } - } - } - } - } - - if ( pSectorInfo->usInfected + newinfected > 0 && Disease[0].sInfectionPtsFull ) - { - FLOAT infectedseverity = (FLOAT)Disease[0].sInfectionPtsInitial / (FLOAT)Disease[0].sInfectionPtsFull; - - pSectorInfo->fInfectionSeverity = (pSectorInfo->fInfectionSeverity * pSectorInfo->usInfected + infectedseverity * newinfected) / (pSectorInfo->usInfected + newinfected); - pSectorInfo->usInfected += newinfected; - - pSectorInfo->usInfected = min( pSectorInfo->usInfected , population); - } - } - - // if infection is high enough, disease officially breaks out - FLOAT infectedpercentage = (FLOAT)pSectorInfo->usInfected / (FLOAT)(population); - - if ( infectedpercentage >= GetSectorDiseaseOverFlowThreshold() || pSectorInfo->fInfectionSeverity > ((FLOAT)Disease[0].sInfectionPtsOutbreak / (FLOAT)Disease[0].sInfectionPtsFull) ) - { - pSectorInfo->usInfectionFlag |= (SECTORDISEASE_OUTBREAK | SECTORDISEASE_DIAGNOSED_WHO); - } - - // if disease is known and doctoring isn't inhibited, use doctoring to remove disease - // doctors (civilian and military) can fight the disease - if ( (pSectorInfo->usInfectionFlag & (SECTORDISEASE_DIAGNOSED_WHO | SECTORDISEASE_DIAGNOSED_PLAYER)) && !pSectorInfo->usDiseaseDoctoringDelay) - { - // the country doesn't have many doctors... - UINT32 doctors = GetSectorPopulation( sX, sY, FALSE ) * GetCivPopulationDoctorRate(); - - // if this the hospital sector, the amount of doctoring is increased to marvellous levels - if ( sX == gModSettings.ubHospitalSectorX && sY == gModSettings.ubHospitalSectorY ) - { - doctors += 200; - } - - // the bulk of doctoring will come from the military - doctors += NumNonPlayerTeamMembersInSector( sX, sY, ENEMY_TEAM ) * GetMilitaryPopulationDoctorRate( ); - - UINT32 doctorpower = doctors * GetPopulationDoctorPoints( ); - - // if the disease escalates, increase doctor power! - if ( infectedpercentage > GetSectorDiseaseOverFlowThreshold( ) + 0.1f ) - doctorpower += doctors * 0.3f * GetPopulationDoctorPoints(); - - HealSectorPopulation( sX, sY, doctorpower ); - } - } - else - { - // if nobody is there, be sure to set infection data to 0 - pSectorInfo->usInfected = 0; - pSectorInfo->usInfectionFlag = 0; - pSectorInfo->fInfectionSeverity = 0; - pSectorInfo->usDiseaseDoctoringDelay = 0; - } - - // in any case, one hour has passed, update possible doctor replacements - pSectorInfo->usDiseaseDoctoringDelay = max( 0, pSectorInfo->usDiseaseDoctoringDelay - 1); - } - } } // chance gets modified by aModifier (contextual modifier) @@ -503,95 +278,6 @@ UINT16 GetSectorPopulation( INT16 sX, INT16 sY, BOOLEAN fWithMilitary ) return population; } -// handle infection redistribution if people move from A to B (set sXB and sYB to negative values to simply remove infected people in A) -void PopulationMove( INT16 sXA, INT16 sYA, INT16 sXB, INT16 sYB, UINT16 usAmount ) -{ - // we have to handle the impact on a sector's disease if people other than mercs move from A to B - if ( !gGameExternalOptions.fDiseaseStrategic ) - return; - - UINT8 sectorA = SECTOR( sXA, sYA ); - - SECTORINFO *pSectorInfoA = &(SectorInfo[sectorA]); - - UINT16 populationA = GetSectorPopulation( sXA, sYA ); - - if ( populationA ) - { - // how many people are already infected? - if ( pSectorInfoA ) - { - FLOAT infectionrateA = (FLOAT)(pSectorInfoA->usInfected) / (FLOAT)(populationA); - - UINT16 movinginfected = usAmount * infectionrateA; - - // we have to add the infection of movinginfected new infected with an infection level of pSectorInfoA->usInfectionSeverity - if ( movinginfected ) - { - // it is possible that there is no other sector - if ( sXB > -1 && sYB > -1 ) - { - UINT8 sectorB = SECTOR( sXB, sYB ); - - SECTORINFO *pSectorInfoB = &(SectorInfo[sectorB]); - - if ( pSectorInfoB ) - { - // new infection severity is the mean of old and new infected times their infection ratios - pSectorInfoB->fInfectionSeverity = (pSectorInfoB->fInfectionSeverity * pSectorInfoB->usInfected + pSectorInfoA->fInfectionSeverity * movinginfected) / (pSectorInfoB->usInfected + movinginfected); - pSectorInfoB->usInfected += movinginfected; - - // disease moves before population moves, so we have to add those too - UINT16 populationB = GetSectorPopulation( sXB, sYB ) + movinginfected; - - FLOAT infectedpercentage = 0; - if ( populationB ) - infectedpercentage = (FLOAT)pSectorInfoB->usInfected / (FLOAT)(populationB); - - if ( infectedpercentage >= GetSectorDiseaseOverFlowThreshold() || pSectorInfoB->fInfectionSeverity > ((FLOAT)Disease[0].sInfectionPtsOutbreak / (FLOAT)Disease[0].sInfectionPtsFull) ) - pSectorInfoB->usInfectionFlag |= (SECTORDISEASE_OUTBREAK | SECTORDISEASE_DIAGNOSED_WHO); - } - } - - // reduce the amount of infected in sector A - pSectorInfoA->usInfected -= movinginfected; - - // if no infected remain, clean up data - if ( !pSectorInfoA->usInfected ) - { - pSectorInfoA->fInfectionSeverity = 0; - pSectorInfoA->usInfectionFlag &= ~(SECTORDISEASE_OUTBREAK | SECTORDISEASE_DIAGNOSED_WHO | SECTORDISEASE_DIAGNOSED_PLAYER); - } - } - } - } -} - -void HandleDeathDiseaseImplications( SOLDIERTYPE *pSoldier ) -{ - if ( !gGameExternalOptions.fDisease || !gGameExternalOptions.fDiseaseStrategic || !pSoldier ) - return; - - UINT8 sector = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ); - - SECTORINFO *pSectorInfo = &(SectorInfo[sector]); - - if ( pSectorInfo ) - { - // if the deceased was infected and not a merc, reduce sector number of infected - if ( pSoldier->sDiseasePoints[0] && pSoldier->bTeam != OUR_TEAM ) - { - pSectorInfo->usInfected = max( 0, pSectorInfo->usInfected - 1 ); - } - - // if this guy was a medic, then medical personnel was killed - it will take a while before he will be replaced - if ( HAS_SKILL_TRAIT( pSoldier, DOCTOR_NT ) ) - { - pSectorInfo->usDiseaseDoctoringDelay = min( 255, pSectorInfo->usDiseaseDoctoringDelay + 12 ); - } - } -} - void HandleDiseaseDailyRefresh() { if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic && gubFact[FACT_DISEASE_WHODATA_SUBSCRIBED] && LaptopSaveInfo.iCurrentBalance > gGameExternalOptions.sDiseaseWHOSubscriptionCost ) @@ -619,31 +305,21 @@ UINT32 HealSectorPopulation( INT16 sX, INT16 sY, UINT32 uHealpts ) UINT32 ptsused = uHealpts; - // the amount of points needed to cure a single patient - UINT32 ptsneededforcure = pSectorInfo->fInfectionSeverity * Disease[0].sInfectionPtsFull; - - // if possible, cure people (we prioritise on this, as we want to lower the number os possible infection sources) - while ( pSectorInfo->usInfected && uHealpts >= ptsneededforcure ) + if ( uHealpts >= pSectorInfo->fDiseasePoints ) { - uHealpts -= ptsneededforcure; - --pSectorInfo->usInfected; + uHealpts -= pSectorInfo->fDiseasePoints; + pSectorInfo->fDiseasePoints = 0; } - - // if there are still points let, but we cannot cure someone, at least lower their disease - if ( pSectorInfo->usInfected && uHealpts > 0 && Disease[0].sInfectionPtsFull ) + else { - UINT32 totaldiseasepoints = pSectorInfo->usInfected * ptsneededforcure; - totaldiseasepoints = max( 0, totaldiseasepoints - uHealpts ); - - pSectorInfo->fInfectionSeverity = (FLOAT)totaldiseasepoints / (FLOAT)(pSectorInfo->usInfected * Disease[0].sInfectionPtsFull); + pSectorInfo->fDiseasePoints -= uHealpts; + uHealpts = 0; } - + // if there are no more infected, or infection is at 0, remove all traces of disease - if ( !pSectorInfo->usInfected || !pSectorInfo->fInfectionSeverity ) + if ( pSectorInfo->fDiseasePoints <= 0 ) { - pSectorInfo->usInfected = 0; - pSectorInfo->fInfectionSeverity = 0; - pSectorInfo->usInfectionFlag &= ~(SECTORDISEASE_OUTBREAK | SECTORDISEASE_DIAGNOSED_WHO | SECTORDISEASE_DIAGNOSED_PLAYER); + pSectorInfo->usInfectionFlag &= ~(SECTORDISEASE_DIAGNOSED_PLAYER); } ptsused -= uHealpts; @@ -658,7 +334,8 @@ FLOAT GetWorkforceEffectivenessWithDisease( INT8 bTownId, UINT8 usTeam ) return 1.0f; FLOAT val = 0.0f; - UINT8 sectors = 0; + UINT16 population_healthy = 0; + UINT16 population_total = 0; for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) { @@ -675,33 +352,29 @@ FLOAT GetWorkforceEffectivenessWithDisease( INT8 bTownId, UINT8 usTeam ) continue; UINT8 sector = SECTOR( sX, sY ); - SECTORINFO *pSectorInfo = &(SectorInfo[sector]); + SECTORINFO *pSector = &(SectorInfo[sector]); - if ( !pSectorInfo ) + if ( !pSector ) continue; - UINT16 population = GetSectorPopulation( sX, sY, FALSE ); + // at least 1 to be safe + UINT16 population = max(1, GetSectorPopulation( sX, sY, FALSE ) ); + + population_total += population; // only civilian population is relevant here if ( population ) { - // workforce effectivity in a sector is population minus cumulated effectivity loss of all infected, divided by entire population - val += (population - min( pSectorInfo->usInfected, population ) * pSectorInfo->fInfectionSeverity ) / population; - } - // if no population is here, then there is no part of te population that is not working, so retrun 1.0 here :-) - // this is basically a fix for players using this feature who have faulty xmls with population 0 - else - { - val += 1.0f; + // workforce effectivity is linearly dependent on disease + population = max( 0, ( ( DISEASE_MAX_SECTOR - pSector->fDiseasePoints) / DISEASE_MAX_SECTOR ) * population ); } - ++sectors; + population_healthy += population; } } } - if ( sectors ) - val /= sectors; + val = (FLOAT)(population_healthy) / (FLOAT)(population_total); return val; } diff --git a/Tactical/Disease.h b/Tactical/Disease.h index b4a12747..1ca8cedc 100644 --- a/Tactical/Disease.h +++ b/Tactical/Disease.h @@ -60,8 +60,6 @@ enum }; // disase flags for a sector -#define SECTORDISEASE_OUTBREAK 0x01 //1 // disease has officially broken out here - it can now be seen on the map, and the AI will try to remove it -#define SECTORDISEASE_DIAGNOSED_WHO 0x02 //2 // disease has been diagnosed by the WHO. This information can only be seen if the player has a contract with the WHO #define SECTORDISEASE_DIAGNOSED_PLAYER 0x04 //4 // disease has been diagnosed by the player // properties of diseases @@ -73,6 +71,10 @@ enum #define DISEASE_PROPERTY_DISGUSTING 0x00000010 // other merc's will be disgusted by anyone with this disease if broken out #define DISEASE_PROPERTY_PTSD_BUNS 0x00000020 // if Buns has this disease, she can change personality +#define CORPSEREMOVALPOINTSPERCORPSE 1.0f // number of corpse removal points required to, you guessed it, remove a corpse +#define DISEASE_PER_ROTTINGCORPSE 100.0f // if a corpse is removed by rotting, add this many disease points to the sector +#define DISEASE_MAX_SECTOR 10000.0f // max disease points in a sector + typedef struct { UINT8 uiIndex; @@ -138,11 +140,6 @@ INT16 GetAdjacentSector( UINT8 sector, UINT8 spdir ); // get a sector population (not the tactical one - we use an xml estimation + troops present) UINT16 GetSectorPopulation( INT16 sX, INT16 sY, BOOLEAN fWithMilitary = TRUE ); -// handle infection redistribution if people move from A to B (set sXB and sYB to negative values to simply remove infected people in A) -void PopulationMove( INT16 sXA, INT16 sYA, INT16 sXB, INT16 sYB, UINT16 usAmount ); - -void HandleDeathDiseaseImplications( SOLDIERTYPE *pSoldier ); - void HandleDiseaseDailyRefresh(); // heal sector population, return number of points used diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index 462fce35..9269ffbc 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -2491,7 +2491,15 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE usTextWidth = StringPixLength( sString, FONT10ARIAL ) - 10; } + break; + case BURIAL: + sIconIndex_Assignment = 35; + fDoIcon_Assignment = TRUE; + fShowCustomText = TRUE; + bPtsAvailable = MercPtrs[pFace->ubSoldierID]->GetBurialPoints( &usMaximumPts ); + + swprintf( sString, L"%3.1f/%d", bPtsAvailable, usMaximumPts ); break; } diff --git a/Tactical/Interface Enhanced.cpp b/Tactical/Interface Enhanced.cpp index d401e934..ed7626e1 100644 --- a/Tactical/Interface Enhanced.cpp +++ b/Tactical/Interface Enhanced.cpp @@ -2729,6 +2729,15 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr MSYS_EnableRegion( &gUDBFasthelpRegions[iFirstDataRegion + cnt] ); ++cnt; } + + //////////////////// BURIAL MODIFIER + if ( Item[gpItemDescObject->usItem].usBurialModifier ) + { + swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[42], szUDBGenSecondaryStatsExplanationsTooltipText[42] ); + SetRegionFastHelpText( &( gUDBFasthelpRegions[iFirstDataRegion + cnt] ), pStr ); + MSYS_EnableRegion( &gUDBFasthelpRegions[iFirstDataRegion + cnt] ); + ++cnt; + } } ////////////////////////////////////////////////////// @@ -6273,6 +6282,14 @@ void DrawSecondaryStats( OBJECTTYPE * gpItemDescObject ) BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 39, gItemDescGenSecondaryRegions[cnt].sLeft + sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL ); cnt++; } + + //////////////////// BURIAL MODIFIER + if ( ( Item[gpItemDescObject->usItem].usBurialModifier && !fComparisonMode ) || + ( fComparisonMode && Item[gpComparedItemDescObject->usItem].usBurialModifier ) ) + { + BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 40, gItemDescGenSecondaryRegions[cnt].sLeft + sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL ); + cnt++; + } } void DrawPropertyValueInColour( INT16 iValue, UINT8 ubNumLine, UINT8 ubNumRegion, BOOLEAN fComparisonMode, BOOLEAN fModifier, BOOLEAN fHigherBetter, UINT16 uiOverwriteColour = 0, BOOLEAN fPercentSign = FALSE ) diff --git a/Tactical/Interface.h b/Tactical/Interface.h index fe888d27..5528d5a1 100644 --- a/Tactical/Interface.h +++ b/Tactical/Interface.h @@ -201,6 +201,7 @@ enum { BG_CROUCHEDDEFENSE, // lowers enemy cth if they fire at us while we are crouched against cover in the direction the shots come from BG_FORTIFY_ASSIGNMENT, // modifies effectivity of 'FORTIFICATION' assignment BG_HACKERSKILL, // hacking skill from 0 to 100, > 0 means hacking is possible + BG_BURIAL_ASSIGNMENT, // modifies effectivity of 'BURIAL' assignment BG_MAX, }; diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 8e575c69..f33a8143 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -1146,6 +1146,9 @@ typedef struct // Flugente: a modifier to hacking UINT8 usHackingModifier; + // Flugente: a modifier for burial effectiveness + UINT8 usBurialModifier; + // Flugente: advanced repair/dirt system UINT8 usDamageChance; // chance that damage to the status will also damage the repair threshold FLOAT dirtIncreaseFactor; // one shot causes this much dirt on a gun @@ -1172,7 +1175,7 @@ typedef struct // silversurfer: item provides breath regeneration bonus while resting UINT8 ubSleepModifier; - // Flugente: spoting effectiveness + // Flugente: spotting effectiveness INT16 usSpotting; //JMich.BackpackClimb diff --git a/Tactical/Rotting Corpses.cpp b/Tactical/Rotting Corpses.cpp index 8cdfbf50..b4a32467 100644 --- a/Tactical/Rotting Corpses.cpp +++ b/Tactical/Rotting Corpses.cpp @@ -49,6 +49,7 @@ #include "Vehicles.h" // added by silversurfer #include "ai.h" // added by Flugente #include "PreBattle Interface.h" // added by Flugente + #include "Strategic Town Loyalty.h" // added by Flugente #endif #include "Animation Control.h" @@ -677,6 +678,15 @@ INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef ) } } + // Flugente: update number of corpses in this sector + if ( !gbWorldSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( gWorldSectorX, gWorldSectorY )] ); + + if ( pSectorInfo ) + pSectorInfo->usNumCorpses = giNumRottingCorpse; + } + // OK, we're done! return( iIndex ); } @@ -1614,7 +1624,7 @@ void VaporizeCorpse( INT32 sGridNo, INT8 asLevel, UINT16 usStructureID ) { // Add explosion memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) ); - AniParams.sGridNo = sBaseGridNo; + AniParams.sGridNo = sBaseGridNo; // Check if on roof or not... if ( pCorpse->def.bLevel == 0 ) @@ -1622,12 +1632,12 @@ void VaporizeCorpse( INT32 sGridNo, INT8 asLevel, UINT16 usStructureID ) else AniParams.ubLevelID = ANI_ONROOF_LEVEL; - AniParams.sDelay = (INT16)( 80 ); - AniParams.sStartFrame = 0; - AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD; - AniParams.sX = CenterX( sBaseGridNo ); - AniParams.sY = CenterY( sBaseGridNo ); - AniParams.sZ = (INT16)pCorpse->def.sHeightAdjustment; + AniParams.sDelay = (INT16)( 80 ); + AniParams.sStartFrame = 0; + AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD; + AniParams.sX = CenterX( sBaseGridNo ); + AniParams.sY = CenterY( sBaseGridNo ); + AniParams.sZ = (INT16)pCorpse->def.sHeightAdjustment; strcpy( AniParams.zCachedFile, "TILECACHE\\GEN_BLOW.STI" ); CreateAnimationTile( &AniParams ); @@ -1636,6 +1646,25 @@ void VaporizeCorpse( INT32 sGridNo, INT8 asLevel, UINT16 usStructureID ) RemoveCorpse( pCorpse->iID ); SetRenderFlags( RENDER_FLAG_FULL ); + // add disease + if ( !gbWorldSectorZ ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( gWorldSectorX, gWorldSectorY )] ); + + if ( pSectorInfo ) + pSectorInfo->fDiseasePoints = min( DISEASE_MAX_SECTOR, pSectorInfo->fDiseasePoints + DISEASE_PER_ROTTINGCORPSE ); + + // the population doesn't like it when we blow chunks of people all over the place + INT8 bTownId = GetTownIdForSector( gWorldSectorX, gWorldSectorY ); + + // if NOT in a town + if ( bTownId != BLANK_SECTOR ) + { + UINT32 uiLoyaltyChange = LOYALTY_PENALTY_ROTTED_CORPSE; + DecrementTownLoyalty( bTownId, uiLoyaltyChange ); + } + } + if ( pCorpse->def.bLevel == 0 ) { // Set some blood...... diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index 1066fded..cec24adc 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -4081,10 +4081,7 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse ) UpdateMilitia(militia); } - - // Flugente: disease - HandleDeathDiseaseImplications( pSoldier ); - + if ( TurnSoldierIntoCorpse( pSoldier, TRUE, TRUE ) ) { *pfMadeCorpse = TRUE; diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 9af6b3c0..4f522f5f 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -18834,17 +18834,6 @@ void SOLDIERTYPE::Infect( UINT8 aDisease ) // we are getting infected. Raise our disease points, but not over the level of an infection if ( aDisease < NUM_DISEASES && this->sDiseasePoints[aDisease] < Disease[aDisease].sInfectionPtsInitial ) { - // if this guy is not of our team, note that a new infected person is in the sector - if ( this->bTeam != gbPlayerNum && aDisease == 0 && this->sDiseasePoints[0] <= 0 ) - { - UINT8 sector = SECTOR( this->sSectorX, this->sSectorY ); - - SECTORINFO *pSectorInfo = &(SectorInfo[sector]); - - if ( pSectorInfo ) - ++pSectorInfo->usInfected; - } - this->sDiseasePoints[aDisease] = min( this->sDiseasePoints[aDisease] + Disease[aDisease].sInfectionPtsInitial, Disease[aDisease].sInfectionPtsInitial ); if ( this->sDiseasePoints[aDisease] > Disease[aDisease].sInfectionPtsOutbreak ) @@ -19274,6 +19263,70 @@ INT16 SOLDIERTYPE::GetDiseaseResistance( ) return(val); } +FLOAT SOLDIERTYPE::GetBurialPoints( UINT16* apCorpses ) +{ + if ( this->stats.bLife < OKLIFE || this->bSectorZ || ( this->usSoldierFlagMask & SOLDIER_POW ) ) + return 0.0f; + + if ( apCorpses ) + { + SECTORINFO *pSectorInfo = &( SectorInfo[SECTOR( this->sSectorX, this->sSectorY )] ); + + if ( pSectorInfo ) + *apCorpses = pSectorInfo->usNumCorpses; + } + + // if not on correct assignment, no gain + if ( this->bAssignment != BURIAL ) + return 0.0f; + + UINT32 val = 4 * EffectiveStrength( this, FALSE ); + + ReducePointsForFatigue( this, &val ); + + // personality/disability modifiers + FLOAT persmodifier = 1.0f; + if ( DoesMercHaveDisability( this, HEAT_INTOLERANT ) ) persmodifier -= 0.01f; + if ( DoesMercHaveDisability( this, FEAR_OF_INSECTS ) ) persmodifier -= 0.03f; + + // background modifier + persmodifier += ( this->GetBackgroundValue( BG_BURIAL_ASSIGNMENT ) ) / 100.0f; + + // equipment modifier + FLOAT bestequipmentmodifier = 1.0f; + + OBJECTTYPE* pObj = NULL; + + INT8 invsize = (INT8)inv.size(); // remember inventorysize, so we don't call size() repeatedly + + for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) // ... for all items in our inventory ... + { + // ... if Item exists and is canteen (that can have drink points) ... + if ( inv[bLoop].exists() == true && Item[inv[bLoop].usItem].usBurialModifier ) + { + OBJECTTYPE * pObj = &( this->inv[bLoop] ); // ... get pointer for this item ... + + if ( pObj != NULL ) // ... if pointer is not obviously useless ... + { + for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i ) + { + FLOAT modifier = 1.0f + ( Item[inv[bLoop].usItem].usBurialModifier * ( *pObj )[i]->data.objectStatus ) / 10000.0f; + + if ( modifier > bestequipmentmodifier ) + bestequipmentmodifier = modifier; + } + } + } + } + + FLOAT totalvalue = val * persmodifier * bestequipmentmodifier * 0.01f; + + // A most awesome merc in Meduna palace, disguised as a soldier, would have a value of 1.15 * 4.63 * 2 = 10.649 at this point. + // This would be the place where we modify our intel gain rate. + + return totalvalue; +} + // Flugente: hourly breath regen calculation INT8 SOLDIERTYPE::GetSleepBreathRegeneration( ) { @@ -19558,16 +19611,13 @@ UINT16 SOLDIERTYPE::GetInteractiveActionSkill( INT32 sGridNo, UINT8 usLevel, UIN return 0; FLOAT bestmodifier = 1.0f; - - UINT8 bestequipmentbonus = 0; - + OBJECTTYPE* pObj = NULL; INT8 invsize = (INT8)inv.size( ); // remember inventorysize, so we don't call size() repeatedly for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) // ... for all items in our inventory ... { - // ... if Item exists and is canteen (that can have drink points) ... if ( inv[bLoop].exists( ) == true && Item[inv[bLoop].usItem].usHackingModifier ) { OBJECTTYPE * pObj = &(this->inv[bLoop]); // ... get pointer for this item ... @@ -19584,7 +19634,6 @@ UINT16 SOLDIERTYPE::GetInteractiveActionSkill( INT32 sGridNo, UINT8 usLevel, UIN } } } - return (UINT16)(skill * bestmodifier); } diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 7dbd5800..c1c8ffd6 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -1941,6 +1941,7 @@ public: void PrintSleepDesc( CHAR16* apStr ); FLOAT GetDiseaseContactProtection(); // get percentage protection from infections via contact INT16 GetDiseaseResistance(); + FLOAT GetBurialPoints( UINT16* apCorpses ); // Flugente: hourly breath regen calculation INT8 GetSleepBreathRegeneration(); diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index 753d6007..f194ec25 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -568,6 +568,12 @@ void DecideToAssignSniperOrders( SOLDIERCREATE_STRUCT * pp ) } } + +// Flugente: disease in a sector affects the health of any NPC spawning there. +// This causes an issue if someone enters a sector from an adjacent sector - they should be affected by their point of origin, not the current sector +// For this reason, we add a little helper variable that stores such a sector. +INT16 gsStrategicDiseaseOriginSector = -1; + SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *pubID ) { SOLDIERTYPE Soldier; @@ -810,50 +816,40 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * Soldier.bOldLife = Soldier.stats.bLifeMax; // Flugente: disease can affect a soldier's health - if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic && Soldier.bTeam != OUR_TEAM && Soldier.bTeam != CREATURE_TEAM && !ARMED_VEHICLE((&Soldier)) ) + // not for us, and not for individual militia (their health is affected by their hourly healing instead) + if ( gGameExternalOptions.fDisease && gGameExternalOptions.fDiseaseStrategic && Soldier.bTeam != OUR_TEAM && Soldier.bTeam != CREATURE_TEAM && !ARMED_VEHICLE((&Soldier)) && + !( Soldier.bTeam == MILITIA_TEAM && gGameExternalOptions.fIndividualMilitia && gGameExternalOptions.fIndividualMilitia_ManageHealth ) ) { UINT8 sector = SECTOR( Soldier.sSectorX, Soldier.sSectorY ); - UINT16 population = GetSectorPopulation( Soldier.sSectorX, Soldier.sSectorY ); // if this is autoresolve, we have to get the sector in a different way.. if ( guiCurrentScreen == AUTORESOLVE_SCREEN ) - { sector = GetAutoResolveSectorID( ); - population = GetSectorPopulation( SECTORX( sector ), SECTORY( sector ) ); - } + if ( gsStrategicDiseaseOriginSector > 0 ) + sector = (UINT8)gsStrategicDiseaseOriginSector; - if ( population ) + SECTORINFO *pSectorInfo = &(SectorInfo[sector]); + + if ( pSectorInfo ) { - SECTORINFO *pSectorInfo = &(SectorInfo[sector]); + INT32 diseaseamount = (Disease[0].sInfectionPtsFull * pSectorInfo->fDiseasePoints) / DISEASE_MAX_SECTOR; + Soldier.AddDiseasePoints( 0, diseaseamount ); - if ( pSectorInfo && pSectorInfo->usInfected ) + // if disease has broken out, lower life points + if ( Soldier.sDiseaseFlag[0] & SOLDIERDISEASE_OUTBREAK ) { - UINT16 chanceofinfection = 100 * (FLOAT)(pSectorInfo->usInfected) / (FLOAT)(population); + // we only alter breath and life points here, stats effectivity will be handled automatically + FLOAT magnitude = Soldier.GetDiseaseMagnitude( 0 ); - if ( Chance( chanceofinfection ) ) - { - INT32 diseaseamount = Disease[0].sInfectionPtsFull * pSectorInfo->fInfectionSeverity; - Soldier.AddDiseasePoints( 0, diseaseamount ); + UINT16 diseasemaxbreathreduction = Disease[0].usMaxBreath * magnitude; - // if disease has broken out, lower life points - if ( Soldier.sDiseaseFlag[0] & SOLDIERDISEASE_OUTBREAK ) - { - // we only alter breath and life points here, stats effectivity will be handled automatically - FLOAT magnitude = Soldier.GetDiseaseMagnitude( 0 ); + Soldier.bBreathMax = min( Soldier.bBreathMax, 100 - diseasemaxbreathreduction ); + Soldier.bBreath = min( Soldier.bBreath, Soldier.bBreathMax ); - UINT16 diseasemaxbreathreduction = Disease[0].usMaxBreath * magnitude; + INT8 lifereduction = (6 * Disease[0].sLifeRegenHundreds) * (magnitude / 100.0f); - Soldier.bBreathMax = min( Soldier.bBreathMax, 100 - diseasemaxbreathreduction ); - Soldier.bBreath = min( Soldier.bBreath, Soldier.bBreathMax ); - - INT8 lifereduction = (6 * Disease[0].sLifeRegenHundreds) * (magnitude / 100); - - Soldier.stats.bLifeMax = max( OKLIFE, Soldier.stats.bLifeMax + lifereduction ); - Soldier.stats.bLifeMax = min( 100, Soldier.stats.bLifeMax ); - Soldier.stats.bLife = min( Soldier.stats.bLife, Soldier.stats.bLifeMax ); - } - } + Soldier.stats.bLife = max( OKLIFE, min(100, Soldier.stats.bLife + lifereduction) ); } } } diff --git a/Tactical/Tactical Save.cpp b/Tactical/Tactical Save.cpp index ec1d8551..0df26566 100644 --- a/Tactical/Tactical Save.cpp +++ b/Tactical/Tactical Save.cpp @@ -108,7 +108,7 @@ BOOLEAN RetrieveTempFileFromSavedGame( HWFILE hFile, UINT32 uiType, INT16 sMapX, BOOLEAN AddTempFileToSavedGame( HWFILE hFile, UINT32 uiType, INT16 sMapX, INT16 sMapY, INT8 bMapZ ); -BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ); +BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, std::vector aCorpseDefVector ); BOOLEAN LoadRottingCorpsesFromTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ); void LoadNPCInformationFromProfileStruct(); @@ -1021,8 +1021,17 @@ BOOLEAN SaveCurrentSectorsInformationToTempItemFile( ) return( FALSE ); } + std::vector corpsedefvector; + + //Determine how many rotting corpses there are + for ( INT32 iCount = 0; iCount < giNumRottingCorpse; ++iCount ) + { + if ( gRottingCorpse[iCount].fActivated ) + corpsedefvector.push_back( gRottingCorpse[iCount].def ); + } + //Save the rotting corpse array to the temp rotting corpse file - if( !SaveRottingCorpsesToTempCorpseFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) ) + if( !SaveRottingCorpsesToTempCorpseFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, corpsedefvector ) ) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("SaveCurrentSectorsInformationToTempItemFile: failed in SaveRottingCorpsesToTempCorpseFile()" ) ); EnableModifiedFileSetCache(cacheResetValue); @@ -1706,27 +1715,22 @@ BOOLEAN InitTacticalSave( BOOLEAN fCreateTempDir ) } - -BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) +BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ, std::vector aCorpseDefVector ) { HWFILE hFile; UINT32 uiNumBytesWritten=0; -// CHAR8 zTempName[ 128 ]; - CHAR8 zMapName[ 128 ]; - UINT32 uiNumberOfCorpses=0; - INT32 iCount; + CHAR8 zMapName[ 128 ]; + + // if we have no corpses at all, we have nothing to write - erase the 'corpse file exists flag', the next time we add a corpse, a new file will be created + if ( aCorpseDefVector.empty() ) + { + ReSetSectorFlag( sMapX, sMapY, bMapZ, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS ); -/* - //Convert the current sector location into a file name - GetMapFileName( sMapX,sMapY, bMapZ, zTempName, FALSE ); - - //add the 'r' for 'Rotting Corpses' to the front of the map name - sprintf( zMapName, "%s\\r_%s", MAPS_DIR, zTempName); -*/ + return TRUE; + } GetMapTempFileName( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ ); - - + //Open the file for writing, Create it if it doesnt exist hFile = FileOpen( zMapName, FILE_ACCESS_WRITE | FILE_OPEN_ALWAYS, FALSE ); if( hFile == 0 ) @@ -1734,16 +1738,9 @@ BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ //Error opening map modification file return( FALSE ); } - - - //Determine how many rotting corpses there are - for(iCount=0; iCount < giNumRottingCorpse; iCount++) - { - if( gRottingCorpse[iCount].fActivated == TRUE ) - uiNumberOfCorpses++; - } - - + + UINT32 uiNumberOfCorpses = aCorpseDefVector.size(); + //Save the number of the Rotting Corpses array table FileWrite( hFile, &uiNumberOfCorpses, sizeof( UINT32 ), &uiNumBytesWritten ); if( uiNumBytesWritten != sizeof( UINT32 ) ) @@ -1754,31 +1751,26 @@ BOOLEAN SaveRottingCorpsesToTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ } //Loop through all the carcases in the array and save the active ones - for(iCount=0; iCount < giNumRottingCorpse; iCount++) + for( std::vector::iterator it = aCorpseDefVector.begin(); it != aCorpseDefVector.end(); ++it ) { - if( gRottingCorpse[iCount].fActivated == TRUE ) + //Save the RottingCorpse info array + FileWrite( hFile, &(*it), sizeof( ROTTING_CORPSE_DEFINITION ), &uiNumBytesWritten ); + if ( uiNumBytesWritten != sizeof( ROTTING_CORPSE_DEFINITION ) ) { - //Save the RottingCorpse info array - FileWrite( hFile, &gRottingCorpse[iCount].def, sizeof( ROTTING_CORPSE_DEFINITION ), &uiNumBytesWritten ); - if( uiNumBytesWritten != sizeof( ROTTING_CORPSE_DEFINITION ) ) - { - //Error Writing size of array to disk - FileClose( hFile ); - return( FALSE ); - } + //Error Writing size of array to disk + FileClose( hFile ); + return( FALSE ); } } FileClose( hFile ); // Set the flag indicating that there is a rotting corpse Temp File -// SectorInfo[ SECTOR( sMapX,sMapY) ].uiFlags |= SF_ROTTING_CORPSE_TEMP_FILE_EXISTS; SetSectorFlag( sMapX, sMapY, bMapZ, SF_ROTTING_CORPSE_TEMP_FILE_EXISTS ); return( TRUE ); } - BOOLEAN DeleteTempItemMapFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) { UINT8 bSectorId = 0; @@ -1813,26 +1805,18 @@ BOOLEAN LoadRottingCorpsesFromTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMa { HWFILE hFile; UINT32 uiNumBytesRead=0; -// CHAR8 zTempName[ 128 ]; CHAR8 zMapName[ 128 ]; UINT32 uiNumberOfCorpses=0; UINT32 cnt; ROTTING_CORPSE_DEFINITION def; - BOOLEAN fDontAddCorpse = FALSE; - INT8 bTownId; - - + BOOLEAN fDontAddCorpse = FALSE; + INT8 bTownId; + //Delete the existing rotting corpse array RemoveCorpses( ); -/* - //Convert the current sector location into a file name - GetMapFileName( sMapX,sMapY, bMapZ, zTempName, FALSE ); - sprintf( zMapName, "%s\\r_%s", MAPS_DIR, zTempName); -*/ GetMapTempFileName( SF_ROTTING_CORPSE_TEMP_FILE_EXISTS, zMapName, sMapX, sMapY, bMapZ ); - - + //Check to see if the file exists if( !FileExists( zMapName ) ) { @@ -1864,7 +1848,7 @@ BOOLEAN LoadRottingCorpsesFromTempCorpseFile( INT16 sMapX, INT16 sMapY, INT8 bMa // Get town ID for use later.... bTownId = GetTownIdForSector( gWorldSectorX, gWorldSectorY ); - for( cnt=0; cntsGridNo ); - } - else - { - //Display the range to the target - DisplayRangeToTarget( MercPtrs[ gusSelectedSoldier ], usGridNo ); + //if the cursor is over someone + if ( gfUIFullTargetFound ) + { + //Display the range to the target + DisplayRangeToTarget( MercPtrs[gusSelectedSoldier], MercPtrs[gusUIFullTargetID]->sGridNo ); + } + else + { + //Display the range to the target + DisplayRangeToTarget( MercPtrs[gusSelectedSoldier], usGridNo ); + } } CHAR16 zOutputString[512]; @@ -3389,7 +3393,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) // Flugente: print out structure tileset if ( gGameExternalOptions.fPrintStructureTileset ) { - STRUCTURE * pStruct = FindStructure( usGridNo, (STRUCTURE_GENERIC) ); + STRUCTURE * pStruct = FindStructure( usGridNo, ( STRUCTURE_TYPE_DEFINED ) ); if ( pStruct ) { // if this is a multi-tile structure, be sure to use the base gridno @@ -3420,16 +3424,20 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) } } } - - extern BOOLEAN InARoom( INT32 sGridNo, UINT16 *pusRoomNo ); - - UINT16 usRoom; - if ( InARoom( usGridNo, &usRoom ) ) - { - swprintf( zOutputString, L"Room number: %d", usRoom ); - ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, zOutputString ); - } } + + extern BOOLEAN InARoom( INT32 sGridNo, UINT16 *pusRoomNo ); + + UINT16 usRoom; + if ( InARoom( usGridNo, &usRoom ) ) + { + swprintf( zOutputString, L"Room number: %d", usRoom ); + ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, zOutputString ); + } + + // display height + swprintf( zOutputString, L"Floor height: %d", gpWorldLevelData[usGridNo].sHeight ); + ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, zOutputString ); } } break; diff --git a/Tactical/XML_Background.cpp b/Tactical/XML_Background.cpp index 743f3cd3..a3998cec 100644 --- a/Tactical/XML_Background.cpp +++ b/Tactical/XML_Background.cpp @@ -138,6 +138,7 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha strcmp(name, "croucheddefense" ) == 0 || strcmp(name, "fortify_assignment" ) == 0 || strcmp(name, "hackerskill" ) == 0 || + strcmp(name, "burial_assignment" ) == 0 || strcmp(name, "druguse") == 0 || strcmp(name, "xenophobic") == 0 || strcmp(name, "corruptionspread") == 0 || @@ -597,6 +598,11 @@ backgroundEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curBackground.value[BG_HACKERSKILL] = min( 100, max( 0, (INT16)atol( pData->szCharData ) ) ); } + else if ( strcmp( name, "burial_assignment" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curBackground.value[BG_BURIAL_ASSIGNMENT] = min( 1000, max( -50, (INT16)atol( pData->szCharData ) ) ); + } else if(strcmp(name, "druguse") == 0) { pData->curElement = ELEMENT; diff --git a/Utils/Text.h b/Utils/Text.h index fada613b..dd41cef4 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -2960,6 +2960,7 @@ enum // menu entries TEXT_DISEASE_DIAGNOSIS, TEXT_DISEASE_TREATMENT, + TEXT_DISEASE_BURIAL, TEXT_DISEASE_CANCEL, // (undiagnosed) diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index 7a458879..f312f663 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -276,6 +276,7 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "DisarmModifier") == 0 || strcmp(name, "RepairModifier") == 0 || strcmp(name, "usHackingModifier" ) == 0 || + strcmp(name, "usBurialModifier" ) == 0 || strcmp(name, "usActionItemFlag") == 0 || strcmp(name, "clothestype") == 0 || @@ -1404,6 +1405,11 @@ itemEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curItem.usHackingModifier = min(100, (UINT8)atol( pData->szCharData ) ); } + else if ( strcmp( name, "usBurialModifier" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curItem.usBurialModifier = min( 100, (UINT8)atol( pData->szCharData ) ); + } else if(strcmp(name, "DamageChance") == 0) { pData->curElement = ELEMENT; @@ -2125,6 +2131,7 @@ BOOLEAN WriteItemStats() FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].DisarmModifier ); FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].RepairModifier ); FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].usHackingModifier ); + FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].usBurialModifier ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usDamageChance ); FilePrintf(hFile,"\t\t%4.2f\r\n", Item[cnt].dirtIncreaseFactor ); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index de301744..c161bca6 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -2475,6 +2475,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; @@ -2582,6 +2583,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -2648,6 +2650,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -6248,7 +6251,7 @@ STR16 zMarksMapScreenText[] = L"地图概况",//"Map Overview", // 24 // Flugente: disease texts describing what a map view does //文本描述疾病查看地图并做翻译。 - L"这个视图会展示出哪个地区爆发了瘟疫,这个数字表明,平均每个人的感染程度,颜色表示它的范围。 灰色=无病。 绿色到红色=不断升级的感染程度。", //L"This view shows in which sectors disease has broken out. The number indicates the mean magnitude of infection per person, the colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of infection.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // TODO.Translate // Flugente: weather texts describing what a map view does L"这个视图显示了目前的天气。没有颜色=晴天。青色为雨天。蓝色为雷暴。橙色为沙尘暴。白色为下雪",//L"This view shows current weather. No colour=Sunny. CYAN=Rain. BLUE=Thunderstorm. ORANGE=Sandstorm. WHITE=Snow.", @@ -8444,6 +8447,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|感|染|防|护", //L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39 L"|护|盾", //L"|S|h|i|e|l|d", L"|C|a|m|e|r|a", // TODO.Translate + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8490,6 +8494,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \n如果保存在物品栏\n降低\n传染给其他人的几率。", //L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.", L"\n \n拿在手里,就可以抵挡前方的伤害。", //L"\n \nIf equipped in a hand, this will block incoming damage.", L"\n \nYou can take photos with this.", // TODO.Translate + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -9063,6 +9068,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% 如果在蹲下状态,视野方向发现敌人,即可瞄准\n", //L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% 建设速度\n",//L" %s%d%% building speed\n", L"黑客技能: %s%d ",//L" hacking skill: %s%d ", + L" %s%d%% burial speed\n", // TODO.Translate }; STR16 szBackgroundTitleText[] = @@ -10996,6 +11002,7 @@ STR16 szDiseaseText[] = L"诊断", // L"Diagnosis", L"治疗", //L"Treatment", + L"Burial", // TODO.Translate L"取消", //L"Cancel",  L"\n\n%s (未诊断的) - %d / %d\n", //L"\n\n%s (undiagnosed) - %d / %d\n", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index c302cbb8..b3f38266 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -2474,6 +2474,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; @@ -2581,6 +2582,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -2647,6 +2649,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -6256,7 +6259,7 @@ STR16 zMarksMapScreenText[] = L"Map Overview", // 24 // Flugente: disease texts describing what a map view does TODO.Translate - L"This view shows in which sectors disease has broken out. The number indicates the mean magnitude of infection per person, the colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of infection.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // TODO.Translate // Flugente: weather texts describing what a map view does L"This view shows current weather. No colour=Sunny. CYAN=Rain. BLUE=Thunderstorm. ORANGE=Sandstorm. WHITE=Snow.", // TODO.Translate @@ -8461,6 +8464,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39 L"|S|h|i|e|l|d", // TODO.Translate L"|C|a|m|e|r|a", // TODO.Translate + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8507,6 +8511,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.", L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate L"\n \nYou can take photos with this.", // TODO.Translate + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -9083,6 +9088,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% building speed\n", L" hacking skill: %s%d ", // TODO.Translate + L" %s%d%% burial speed\n", // TODO.Translate }; STR16 szBackgroundTitleText[] = // TODO.Translate @@ -11014,6 +11020,7 @@ STR16 szDiseaseText[] = L"Diagnosis", L"Treatment", + L"Burial", // TODO.Translate L"Cancel", L"\n\n%s (undiagnosed) - %d / %d\n", // TODO.Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 81df9f6e..e91c5da7 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -2475,6 +2475,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; @@ -2582,6 +2583,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -2648,6 +2650,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -6249,7 +6252,7 @@ STR16 zMarksMapScreenText[] = L"Map Overview", // 24 // Flugente: disease texts describing what a map view does - L"This view shows in which sectors disease has broken out. The number indicates the mean magnitude of infection per person, the colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of infection.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // Flugente: weather texts describing what a map view does L"This view shows current weather. No colour=Sunny. CYAN=Rain. BLUE=Thunderstorm. ORANGE=Sandstorm. WHITE=Snow.", @@ -8445,6 +8448,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39 L"|S|h|i|e|l|d", L"|C|a|m|e|r|a", + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8491,6 +8495,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.", L"\n \nIf equipped in a hand, this will block incoming damage.", L"\n \nYou can take photos with this.", + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -9064,6 +9069,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% building speed\n", L" hacking skill: %s%d ", + L" %s%d%% burial speed\n", }; STR16 szBackgroundTitleText[] = @@ -10998,6 +11004,7 @@ STR16 szDiseaseText[] = L"Diagnosis", L"Treatment", + L"Burial", L"Cancel", L"\n\n%s (undiagnosed) - %d / %d\n", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 82c180e2..edcb0427 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -2483,6 +2483,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; @@ -2590,6 +2591,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -2656,6 +2658,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -6261,7 +6264,7 @@ STR16 zMarksMapScreenText[] = L"Écran carte", // 24 // Flugente: disease texts describing what a map view does TODO.Translate - L"This view shows in which sectors disease has broken out. The number indicates the mean magnitude of infection per person, the colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of infection.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // TODO.Translate // Flugente: weather texts describing what a map view does L"This view shows current weather. No colour=Sunny. CYAN=Rain. BLUE=Thunderstorm. ORANGE=Sandstorm. WHITE=Snow.", // TODO.Translate @@ -8448,6 +8451,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39 L"|S|h|i|e|l|d", // TODO.Translate L"|C|a|m|e|r|a", // TODO.Translate + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8494,6 +8498,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.", L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate L"\n \nYou can take photos with this.", // TODO.Translate + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -9065,6 +9070,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% building speed\n", L" hacking skill: %s%d ", // TODO.Translate + L" %s%d%% burial speed\n", // TODO.Translate }; STR16 szBackgroundTitleText[] = @@ -10996,6 +11002,7 @@ STR16 szDiseaseText[] = L"Diagnosis", L"Treatment", + L"Burial", // TODO.Translate L"Cancel", L"\n\n%s (undiagnosed) - %d / %d\n", // TODO.Translate diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 0e4cf9f7..12395fce 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -2488,6 +2488,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; STR16 pMilitiaString[] = @@ -2591,6 +2592,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; // refer to above for comments @@ -2655,6 +2657,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; // the contract options @@ -6101,7 +6104,7 @@ STR16 zMarksMapScreenText[] = L"Kartenübersicht", // 24 // Flugente: disease texts describing what a map view does TODO.Translate - L"This view shows in which sectors disease has broken out. The number indicates the mean magnitude of infection per person, the colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of infection.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // TODO.Translate // Flugente: weather texts describing what a map view does L"This view shows current weather. No colour=Sunny. CYAN=Rain. BLUE=Thunderstorm. ORANGE=Sandstorm. WHITE=Snow.", // TODO.Translate @@ -8277,6 +8280,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39 L"|S|h|i|e|l|d", // TODO.Translate L"|C|a|m|e|r|a", // TODO.Translate + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8323,6 +8327,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.", L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate L"\n \nYou can take photos with this.", // TODO.Translate + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -8895,6 +8900,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% building speed\n", L" hacking skill: %s%d ", // TODO.Translate + L" %s%d%% burial speed\n", // TODO.Translate }; STR16 szBackgroundTitleText[] = // TODO.Translate @@ -10826,6 +10832,7 @@ STR16 szDiseaseText[] = L"Diagnosis", L"Treatment", + L"Burial", // TODO.Translate L"Cancel", L"\n\n%s (undiagnosed) - %d / %d\n", // TODO.Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index f4aaeaf1..a138f072 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -2469,6 +2469,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; @@ -2576,6 +2577,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -2642,6 +2644,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -6239,7 +6242,7 @@ STR16 zMarksMapScreenText[] = L"Il contratto del mercenario non è assicurato", // Flugente: disease texts describing what a map view does TODO.Translate - L"This view shows in which sectors disease has broken out. The number indicates the mean magnitude of infection per person, the colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of infection.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // TODO.Translate // Flugente: weather texts describing what a map view does L"This view shows current weather. No colour=Sunny. CYAN=Rain. BLUE=Thunderstorm. ORANGE=Sandstorm. WHITE=Snow.", // TODO.Translate @@ -8451,6 +8454,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39 L"|S|h|i|e|l|d", // TODO.Translate L"|C|a|m|e|r|a", // TODO.Translate + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8497,6 +8501,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.", L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate L"\n \nYou can take photos with this.", // TODO.Translate + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -9074,6 +9079,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% building speed\n", L" hacking skill: %s%d ", // TODO.Translate + L" %s%d%% burial speed\n", // TODO.Translate }; STR16 szBackgroundTitleText[] = // TODO.Translate @@ -11005,6 +11011,7 @@ STR16 szDiseaseText[] = L"Diagnosis", L"Treatment", + L"Burial", // TODO.Translate L"Cancel", L"\n\n%s (undiagnosed) - %d / %d\n", // TODO.Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 884a4a8c..735274f9 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -2481,6 +2481,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; @@ -2588,6 +2589,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -2654,6 +2656,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -6257,7 +6260,7 @@ STR16 zMarksMapScreenText[] = L"Mapa", // 24 // Flugente: disease texts describing what a map view does TODO.Translate - L"This view shows in which sectors disease has broken out. The number indicates the mean magnitude of infection per person, the colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of infection.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // TODO.Translate // Flugente: weather texts describing what a map view does L"This view shows current weather. No colour=Sunny. CYAN=Rain. BLUE=Thunderstorm. ORANGE=Sandstorm. WHITE=Snow.", // TODO.Translate @@ -8463,6 +8466,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|I|n|f|e|c|t|i|o|n |P|r|o|t|e|c|t|i|o|n", // 39 L"|S|h|i|e|l|d", // TODO.Translate L"|C|a|m|e|r|a", // TODO.Translate + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8509,6 +8513,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \nIf kept in your inventory, this will\nlower\nthe chance to be infected by other people.", L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate L"\n \nYou can take photos with this.", // TODO.Translate + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -9087,6 +9092,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% building speed\n", L" hacking skill: %s%d ", // TODO.Translate + L" %s%d%% burial speed\n", // TODO.Translate }; STR16 szBackgroundTitleText[] = // TODO.Translate @@ -11018,6 +11024,7 @@ STR16 szDiseaseText[] = L"Diagnosis", L"Treatment", + L"Burial", // TODO.Translate L"Cancel", L"\n\n%s (undiagnosed) - %d / %d\n", // TODO.Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 603c959e..28dd57a8 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -2475,6 +2475,7 @@ STR16 pAssignmentStrings[] = L"GetIntel", L"DoctorM.", L"DMilitia", + L"Burial", }; @@ -2582,6 +2583,7 @@ STR16 pPersonnelAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -2648,6 +2650,7 @@ STR16 pLongAssignmentStrings[] = L"Get intel while disguised", L"Doctor wounded militia", L"Drill existing militia", + L"Bury corpses", }; @@ -6249,7 +6252,7 @@ STR16 zMarksMapScreenText[] = L"Стратегическая карта", // Flugente: disease texts describing what a map view does - L"Здесь показаны вспышки заболеваний по секторам. Число указывает средний показатель инфекции на человека, цвет - насколько широко распространена инфекция. СЕРЫЙ= нет информации о заболеваемости. ЗЕЛЁНЫЙ - КРАСНЫЙ = уровень роста заболеваемости.", + L"This view shows how many rotting corpses are in a sector. The white number are corpses, the green number is accumulated disease, the sector colour indicates how widespread it is. GREY= No disease known of. GREEN to RED = escalating levels of disease.", // TODO.Translate // Flugente: weather texts describing what a map view does L"Здесь паказана актуальная погода. Без цвета=солнечно, зеленый=дождь, Синий=Гроза, Оранжевый=песчаная буря, Белый=снег.", @@ -8445,6 +8448,7 @@ STR16 szUDBGenSecondaryStatsTooltipText[]= L"|И|н|ф|е|к|ц|и|о|н|н|а|я |з|а|щ|и|т|а", // 39 L"|S|h|i|e|l|d", // TODO.Translate L"|C|a|m|e|r|a", // TODO.Translate + L"|B|u|r|i|a|l |M|o|d|i|f|i|e|r", }; STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= @@ -8491,6 +8495,7 @@ STR16 szUDBGenSecondaryStatsExplanationsTooltipText[]= L"\n \nЕсли хранить в своём кармане,\nпонижается шанс заражения\n от других людей.", L"\n \nIf equipped in a hand, this will block incoming damage.", // TODO.Translate L"\n \nYou can take photos with this.", // TODO.Translate + L"\n \nThis item makes you more effective at burying corpses.", }; STR16 szUDBAdvStatsTooltipText[]= @@ -9064,6 +9069,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% enemy CTH if crouched against thick cover in their direction\n", L" %s%d%% кровотечение\n", L" Взлом: %s%d ", + L" %s%d%% burial speed\n", // TODO.Translate }; STR16 szBackgroundTitleText[] = @@ -10998,6 +11004,7 @@ STR16 szDiseaseText[] = L"Обследование", L"Лечение населения", + L"Burial", // TODO.Translate L"Отмена", L"\n\n%s (недиагностирована) - %d / %d\n",