diff --git a/GameSettings.cpp b/GameSettings.cpp index 9361c655..48c10eea 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -3543,8 +3543,6 @@ void LoadMoraleSettings() gMoraleSettings.bModifiers[MORALE_MOD_MAX] = iniReader.ReadInteger("Morale Modifiers Settings","MORALE_MOD_MAX", -1, 0, 100); - gMoraleSettings.sDrugAndAlcoholModifiers[DRUG_EFFECT_MORALE_MOD] = iniReader.ReadInteger("Morale Modifiers Settings","DRUG_EFFECT_MORALE_MOD", 150, 0, 10000); - gMoraleSettings.sDrugAndAlcoholModifiers[ALCOHOL_EFFECT_MORALE_MOD] = iniReader.ReadInteger("Morale Modifiers Settings","ALCOHOL_EFFECT_MORALE_MOD", 160, 0, 10000); gMoraleSettings.bModifiers[PHOBIC_LIMIT] = iniReader.ReadInteger("Morale Modifiers Settings","PHOBIC_LIMIT", 20, 0, 100); gMoraleSettings.bModifiers[MORALE_MODIFIER_SOCIABLE_ONE_MERC_NEARBY] = iniReader.ReadInteger("Morale Modifiers Settings","MORALE_MODIFIER_SOCIABLE_ONE_MERC_NEARBY", -2, -100, 100); diff --git a/GameSettings.h b/GameSettings.h index ff981a2c..d1d9ac6b 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1510,7 +1510,6 @@ typedef struct UINT8 ubHoursBetweenStrategicDelay; INT8 bValues[64]; INT8 bModifiers[32]; - INT16 sDrugAndAlcoholModifiers[2]; } MORALE_SETTINGS; typedef struct diff --git a/GameVersion.cpp b/GameVersion.cpp index 97087067..a8cc3674 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -15,9 +15,9 @@ #ifdef JA2EDITOR #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.7896 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.7896 (Development Build)" }; #endif // ------------------------------ @@ -27,11 +27,11 @@ //DEBUG BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.7896 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.7896 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Debug: v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: v1.13.7896 (Development Build)" }; #endif #elif defined CRIPPLED_VERSION @@ -46,16 +46,16 @@ //RELEASE BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.7896 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.7896 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Release v1.13.7889 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.7896 (Development Build)" }; #endif #endif -CHAR8 czVersionNumber[16] = { "Build 15.06.13" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 15.06.28" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/GameVersion.h b/GameVersion.h index dd840c97..ac942d9d 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -21,6 +21,7 @@ extern CHAR16 zTrackingNumber[16]; // Keeps track of the saved game version. Increment the saved game version whenever // you will invalidate the saved game file +#define DRUG_SYSTEM_REDONE 163 // Flugente: reworked the drug system #define MILITIA_PATH_PLOTTING 162 // Flugente: the player can plot militia paths in strategic, similar to player or helicopter travel #define STRATEGIC_TEAM_GROUPS 161 // Flugente: a change to the GROUP-structure allows any team to have strategic movement groups #define PMC_WEBSITE 160 // Flugente: a new PMC allows us to hire trained militia @@ -81,7 +82,7 @@ extern CHAR16 zTrackingNumber[16]; #define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes #define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system -#define SAVE_GAME_VERSION MILITIA_PATH_PLOTTING +#define SAVE_GAME_VERSION DRUG_SYSTEM_REDONE //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Laptop/IMP Background.cpp b/Laptop/IMP Background.cpp index 834dc283..3dd6246e 100644 --- a/Laptop/IMP Background.cpp +++ b/Laptop/IMP Background.cpp @@ -492,23 +492,38 @@ void AssignBackgroundHelpText( UINT16 ubNumber, MOUSE_REGION* pMouseregion ) } } + UINT8 strused = 0; for ( UINT8 i = 0; i < BG_MAX; ++i) { if ( BG_DISLIKEBG == i && zBackground[ubNumber].value[i] ) { - swprintf( atStr, szBackgroundText_Value[i] ); + swprintf( atStr, szBackgroundText_Value[strused] ); wcscat( apStr, atStr ); } else if ( BG_TRACKER_ABILITY == i && zBackground[ubNumber].value[i] ) { - swprintf( atStr, szBackgroundText_Value[i], (UINT16)((gSkillTraitValues.usSVTrackerMaxRange * zBackground[ubNumber].value[i]) / 100) ); + swprintf( atStr, szBackgroundText_Value[strused], (UINT16)((gSkillTraitValues.usSVTrackerMaxRange * zBackground[ubNumber].value[i]) / 100) ); wcscat( apStr, atStr ); } + else if ( BG_SMOKERTYPE == i ) + { + if ( zBackground[ubNumber].value[i] == 1 ) + swprintf( atStr, szBackgroundText_Value[strused] ); + else + swprintf( atStr, szBackgroundText_Value[strused + 1] ); + + wcscat( apStr, atStr ); + + // smoke has 2 texts, so extra increase of counter is needed + ++strused; + } else if ( zBackground[ ubNumber ].value[i] ) { - swprintf(atStr, szBackgroundText_Value[ i ], zBackground[ ubNumber ].value[i] > 0 ? L"+" : L"", zBackground[ ubNumber ].value[i] ); + swprintf( atStr, szBackgroundText_Value[strused], zBackground[ubNumber].value[i] > 0 ? L"+" : L"", zBackground[ubNumber].value[i] ); wcscat( apStr, atStr ); } + + ++strused; } } else diff --git a/Laptop/merccompare.cpp b/Laptop/merccompare.cpp index 67a1b2c1..c898ffbd 100644 --- a/Laptop/merccompare.cpp +++ b/Laptop/merccompare.cpp @@ -826,6 +826,27 @@ BOOLEAN DisplayMercData( UINT8 usProfileA, UINT8 usProfileB ) usPosY += DisplayWrappedString( usPosX + MCA_SIDEOFFSET + MCA_NUMBEROFFSET, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, (val > 0) ? FONT_MCOLOR_LTGREEN : (val < 0) ? FONT_MCOLOR_LTRED : MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 ); } + // smoker + INT16 smokerA = GetBackgroundValue( usProfileA, BG_SMOKERTYPE ); + INT16 smokerB = GetBackgroundValue( usProfileB, BG_SMOKERTYPE ); + if ( smokerA && smokerB ) + { + if ( smokerA != smokerB ) + val = -2; + else + val = 1; + + swprintf( sText, smokerA == 1 ? szBackgroundText_Value[BG_SMOKERTYPE] : szBackgroundText_Value[BG_SMOKERTYPE + 1] ); + DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 ); + swprintf( sText, L"%d", val ); + DisplayWrappedString( usPosX + MCA_NUMBEROFFSET, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, (val > 0) ? FONT_MCOLOR_LTGREEN : (val < 0) ? FONT_MCOLOR_LTRED : MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 ); + + swprintf( sText, smokerB == 1 ? szBackgroundText_Value[BG_SMOKERTYPE] : szBackgroundText_Value[BG_SMOKERTYPE + 1] ); + DisplayWrappedString( usPosX + MCA_SIDEOFFSET, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 ); + swprintf( sText, L"%d", val ); + usPosY += DisplayWrappedString( usPosX + MCA_SIDEOFFSET + MCA_NUMBEROFFSET, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, (val > 0) ? FONT_MCOLOR_LTGREEN : (val < 0) ? FONT_MCOLOR_LTRED : MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 ); + } + // after this, the lines are no longer synchronous - we just list each property on its own side usPosY2 = usPosY; diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 1c2b42a4..1552533e 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -1554,9 +1554,34 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for { if ( guiCurrentSaveGameVersion >= DYNAMIC_DIALOGUE ) { - if ( !FileRead( hFile, &this->usDynamicOpinionFlagmask, sizeof(usDynamicOpinionFlagmask), &uiNumBytesRead ) ) + if ( guiCurrentSaveGameVersion >= DRUG_SYSTEM_REDONE ) { - return(FALSE); + if ( !FileRead( hFile, &this->usDynamicOpinionFlagmask, sizeof(usDynamicOpinionFlagmask), &uiNumBytesRead ) ) + { + return(FALSE); + } + } + else + { + UINT32 tmp[NUM_PROFILES][5]; + if ( !FileRead( hFile, &tmp, sizeof(tmp), &uiNumBytesRead ) ) + { + return(FALSE); + } + + for ( UINT16 profile = 0; profile < NUM_PROFILES; ++profile ) + { + UINT8 i = 0; + for ( i = 0; i < 5; ++i ) + { + this->usDynamicOpinionFlagmask[profile][i] = tmp[profile][i]; + } + + for ( ; i < OPINION_FLAGMASKS_NUMBER; ++i ) + { + this->usDynamicOpinionFlagmask[profile][i] = tmp[profile][i]; + } + } } if ( !FileRead( hFile, &this->sDynamicOpinionLongTerm, sizeof(sDynamicOpinionLongTerm), &uiNumBytesRead ) ) @@ -1566,7 +1591,7 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for } else { - UINT32 tmp[NUM_PROFILES][3]; + UINT32 tmp[NUM_PROFILES][3]; if ( !FileRead( hFile, &tmp, sizeof(tmp), &uiNumBytesRead ) ) { return(FALSE); @@ -1574,7 +1599,13 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for for ( UINT16 profile = 0; profile < NUM_PROFILES; ++profile ) { - for ( UINT8 i = 0; i < 3; ++i ) + UINT8 i = 0; + for ( i = 0; i < 3; ++i ) + { + this->usDynamicOpinionFlagmask[profile][i] = tmp[profile][i]; + } + + for ( ; i < OPINION_FLAGMASKS_NUMBER; ++i ) { this->usDynamicOpinionFlagmask[profile][i] = tmp[profile][i]; } @@ -1724,10 +1755,13 @@ BOOLEAN SOLDIERTYPE::Save(HWFILE hFile) { return(FALSE); } - if ( !FileWrite( hFile, &this->drugs, sizeof(STRUCT_Drugs), &uiNumBytesWritten ) ) + + // Flugente: changed drug structure + if ( !FileWrite( hFile, &this->newdrugs, sizeof(DRUGS), &uiNumBytesWritten ) ) { return(FALSE); } + if ( !FileWrite( hFile, &this->stats, sizeof(STRUCT_Statistics), &uiNumBytesWritten ) ) { return(FALSE); @@ -2610,10 +2644,32 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) { return(FALSE); } - if ( !FileRead( hFile, &this->drugs, sizeof(STRUCT_Drugs), &uiNumBytesRead ) ) + + if ( guiCurrentSaveGameVersion < DRUG_SYSTEM_REDONE ) { - return(FALSE); + // read old drugs with a dummy structure of the old structs size (192) + UINT8 tmp[192]; + if ( !FileRead( hFile, &tmp, sizeof(tmp), &uiNumBytesRead ) ) + { + return(FALSE); + } + + /*if ( !FileRead( hFile, &this->drugs, sizeof(STRUCT_Drugs), &uiNumBytesRead ) ) + { + return(FALSE); + }*/ + + // clear new drugs + memset( &this->newdrugs, 0, sizeof(DRUGS) ); } + else + { + if ( !FileRead( hFile, &this->newdrugs, sizeof(DRUGS), &uiNumBytesRead ) ) + { + return(FALSE); + } + } + //Load STRUCT_Statistics numBytesRead = 0; buffer = 0; diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index b9d9dad1..0a3d7b72 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -70,6 +70,7 @@ #include "Disease.h" // added by Flugente #include "Queen Command.h" // added by Flugente #include "PMC.h" // added by Flugente + #include "Drugs And Alcohol.h" // added by Flugente for DoesMercHaveDisability( ... ) #endif #include #include @@ -2738,14 +2739,15 @@ UINT16 CalculateHealingPointsForDoctor(SOLDIERTYPE *pDoctor, UINT16 *pusMaxPts, usHealPts += usHealPts * gSkillTraitValues.usDODoctorAssignmentBonus * NUM_SKILL_TRAITS( pDoctor, DOCTOR_NT ) / 100; *pusMaxPts += *pusMaxPts * gSkillTraitValues.usDODoctorAssignmentBonus * NUM_SKILL_TRAITS( pDoctor, DOCTOR_NT ) / 100; } + // penalty for aggressive people - if ( gMercProfiles[ pDoctor->ubProfile ].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + if ( DoesMercHavePersonality( pDoctor, CHAR_TRAIT_AGGRESSIVE ) ) { usHealPts -= usHealPts / 10; *pusMaxPts -= *pusMaxPts / 10; } // bonus for phlegmatic people - else if ( gMercProfiles[ pDoctor->ubProfile ].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC ) + else if ( DoesMercHavePersonality( pDoctor, CHAR_TRAIT_PHLEGMATIC ) ) { usHealPts += usHealPts / 20; *pusMaxPts += *pusMaxPts / 20; @@ -2831,14 +2833,15 @@ UINT8 CalculateRepairPointsForRepairman(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts usRepairPts += usRepairPts * gSkillTraitValues.usTERepairSpeedBonus * (NUM_SKILL_TRAITS( pSoldier, TECHNICIAN_NT )) / 100; *pusMaxPts += *pusMaxPts * gSkillTraitValues.usTERepairSpeedBonus * (NUM_SKILL_TRAITS( pSoldier, TECHNICIAN_NT )) / 100; } + // Penalty for aggressive people - if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_AGGRESSIVE ) ) { usRepairPts -= usRepairPts / 10; // -10% *pusMaxPts -= *pusMaxPts / 10; } // Bonus for phlegmatic people - else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PHLEGMATIC ) ) { usRepairPts += usRepairPts / 20; // +5% *pusMaxPts += *pusMaxPts / 20; @@ -3015,10 +3018,11 @@ UINT32 CalculateSnitchGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) usValue += 25 * NUM_SKILL_TRAITS( pSoldier, STEALTHY_OT ); } - if( gMercProfiles[ pSoldier->ubProfile ].bDisability == DEAF ) + if ( DoesMercHaveDisability( pSoldier, DEAF ) ) { usValue = usValue/2; } + // adjust for fatigue ReducePointsForFatigue( pSoldier, &usValue ); @@ -3136,7 +3140,7 @@ UINT32 CalculateSnitchInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPt if ( gGameOptions.fNewTraitSystem ) { - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_ASSERTIVE ) ) friendlyvalue += 30; } @@ -5092,8 +5096,9 @@ void FatigueCharacter( SOLDIERTYPE *pSoldier ) { bMaxBreathLoss = (bMaxBreathLoss * (100 - gSkillTraitValues.ubSVBreathForTravellingReduction * NUM_SKILL_TRAITS( pSoldier, SURVIVAL_NT )) / 100); } + // primitive people get exhausted slower - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_PRIMITIVE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PRIMITIVE ) ) { switch ( pSoldier->bAssignment ) { @@ -5121,8 +5126,8 @@ void FatigueCharacter( SOLDIERTYPE *pSoldier ) break; } } - // Picifist actually gain morale, when on peaceful assignments - else if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_PACIFIST ) + // Pacifists actually gain morale, when on peaceful assignments + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PACIFIST ) ) { switch ( pSoldier->bAssignment ) { @@ -5537,9 +5542,12 @@ void HandleDiseaseDiagnosis() for ( int i = 0; i < NUM_DISEASES; ++i ) { // if teammember has disease, but this is not yet known - if ( pTeamSoldier->sDiseasePoints[i] > 0 && !(pTeamSoldier->sDiseaseFlag[i] & SOLDIERDISEASE_DIAGNOSED) ) + if ( pTeamSoldier->sDiseasePoints[i] > 0 && !(pTeamSoldier->sDiseaseFlag[i] & SOLDIERDISEASE_DIAGNOSED) && Disease[i].sInfectionPtsOutbreak > 0 ) { - if ( Chance( skill ) ) + // whether an infection is diagnosed also depends on how high it is compared to an outbreak + FLOAT infectedfraction = ((FLOAT)pTeamSoldier->sDiseasePoints[i] / (FLOAT)Disease[i].sInfectionPtsOutbreak); + + if ( infectedfraction > 0.0f && Chance((UINT32)(100 * infectedfraction)) && Chance( skill ) ) { // doctor discovered a disease - make it known pTeamSoldier->AnnounceDisease( i ); @@ -5763,7 +5771,7 @@ void HandleGatheringInformationBySoldier( SOLDIERTYPE* pSoldier ) FLOAT fBaseChance = ( EffectiveLeadership(pSoldier) + EffectiveWisdom(pSoldier) + EffectiveExpLevel(pSoldier) * 10 ) / 3000.0f; - if( gMercProfiles[ pSoldier->ubProfile ].bDisability == DEAF ) + if ( DoesMercHaveDisability( pSoldier, DEAF ) ) { fBaseChance /= 2.0; } @@ -6146,16 +6154,18 @@ INT16 GetSoldierTrainingPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, UINT16 *pus bTrainingBonus += gSkillTraitValues.ubTGBonusOnPractising; //sTrainingPts += (sTrainingPts * gSkillTraitValues.ubTGBonusOnPractising / 100); } + // bonus for practising for intellectuals - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_INTELLECTUAL ) ) { // +10% *pusMaxPts += (*pusMaxPts / 10); bTrainingBonus += 10; //sTrainingPts += (sTrainingPts / 10); } + // bonus for practising for intellectuals - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_AGGRESSIVE ) ) { switch (bTrainStat) { @@ -6268,16 +6278,18 @@ INT16 GetSoldierStudentPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, UINT16 *pusM bTrainingBonus += gSkillTraitValues.ubTGBonusOnPractising; //sTrainingPts += (sTrainingPts * gSkillTraitValues.ubTGBonusOnPractising / 100); } + // bonus for practising for intellectuals - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_INTELLECTUAL ) ) { // +10% *pusMaxPts += (*pusMaxPts / 10); bTrainingBonus += 10; //sTrainingPts += (sTrainingPts / 10); } + // bonus for practising for intellectuals - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_AGGRESSIVE ) ) { switch (bTrainStat) { @@ -7388,17 +7400,17 @@ INT16 GetTownTrainPtsForCharacter( SOLDIERTYPE *pTrainer, UINT16 *pusMaxPts ) sTrainingBonus += gSkillTraitValues.ubTGBonusToTrainMilitia; } // +10% for Assertive people - if ( gMercProfiles[pTrainer->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE ) + if ( DoesMercHavePersonality( pTrainer, CHAR_TRAIT_ASSERTIVE ) ) { sTrainingBonus += 10; } // -5% for Aggressive people - else if ( gMercProfiles[pTrainer->ubProfile].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + else if ( DoesMercHavePersonality( pTrainer, CHAR_TRAIT_AGGRESSIVE ) ) { sTrainingBonus -= 5; } // +5% for Phlegmatic people - else if ( gMercProfiles[pTrainer->ubProfile].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC ) + else if ( DoesMercHavePersonality( pTrainer, CHAR_TRAIT_PHLEGMATIC ) ) { sTrainingBonus += 5; } diff --git a/Strategic/Facilities.cpp b/Strategic/Facilities.cpp index f7b81dd3..6ecaedd2 100644 --- a/Strategic/Facilities.cpp +++ b/Strategic/Facilities.cpp @@ -1840,9 +1840,13 @@ void HandleRisksForSoldierFacilityAssignment( SOLDIERTYPE *pSoldier, UINT8 ubFac } // Add effects - pSoldier->AddDrugValues( DRUG_TYPE_ALCOHOL, Drug[DRUG_TYPE_ALCOHOL].ubDrugEffect, Drug[DRUG_TYPE_ALCOHOL].ubDrugTravelRate, Drug[DRUG_TYPE_ALCOHOL].ubDrugSideEffect ); + CreateItem( ALCOHOL, Item[ALCOHOL].usPortionSize, &gTempObject ); + + ApplyConsumable( pSoldier, &gTempObject, TRUE, FALSE ); - // ATE: Make guy collapse from heart attack if too much stuff taken.... + //pSoldier->AddDrugValues( DRUG_TYPE_ALCOHOL, Drug[DRUG_TYPE_ALCOHOL].ubDrugEffect, Drug[DRUG_TYPE_ALCOHOL].ubDrugTravelRate, Drug[DRUG_TYPE_ALCOHOL].ubDrugSideEffect ); + + /*// ATE: Make guy collapse from heart attack if too much stuff taken.... if ( pSoldier->drugs.bDrugSideEffectRate[ DRUG_TYPE_ALCOHOL ] > ( Drug[DRUG_TYPE_ALCOHOL].ubDrugSideEffect * 3 ) ) { if ( pSoldier->ubProfile == LARRY_NORMAL ) @@ -1938,7 +1942,7 @@ void HandleRisksForSoldierFacilityAssignment( SOLDIERTYPE *pSoldier, UINT8 ubFac gMercProfiles[ pSoldier->ubProfile ].records.usTimesStatDamaged++; gMercProfiles[ pSoldier->ubProfile ].records.usFacilityAccidents++; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - } + }*/ break; case RISK_LOYALTY_LOCAL: Result *= GAIN_PTS_PER_LOYALTY_PT; // Transform points into actual loyalty. diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index bfa594be..3fc72554 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -20,6 +20,7 @@ #include "Strategic AI.h" #include "Tactical Save.h" // added by Flugente #include "DynamicDialogue.h" // added by Flugente for HandleDynamicOpinions() + #include "Drugs And Alcohol.h" // added by Flugente for HourlyDrugUpdate() #endif #include "Luaglobal.h" @@ -41,6 +42,7 @@ void HourlyQuestUpdate(); void HourlyLarryUpdate(); +void HourlySmokerUpdate(); void HourlyStealUpdate(); // Flugente: certain characters might steal equipment (backgrounds) void HourlySnitchUpdate(); // anv: decreasing cooldown after exposition @@ -60,8 +62,6 @@ void HourlyHelicopterRepair(); void HourlyGatheringInformation(); -void UpdateRegenCounters( void ); - void HandleMinuteUpdate() { } @@ -117,6 +117,8 @@ CHAR16 zString[128]; HourlyLarryUpdate(); + HourlySmokerUpdate( ); + HourlyStealUpdate(); HourlySnitchUpdate(); @@ -139,10 +141,7 @@ CHAR16 zString[128]; HourlyHelicopterRepair(); #endif - - if ( GetWorldHour() % 6 == 0 ) // 4 times a day - { UpdateRegenCounters(); - } + HourlyDrugUpdate(); // WANNE: This check should avoid the resaving of a loaded auto-save game, when entering tactical BOOLEAN doAutoSave = TRUE; @@ -255,19 +254,6 @@ CHAR16 zString[128]; } } -void UpdateRegenCounters( void ) -{ - UINT8 ubID; - - for ( ubID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; ubID <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubID++ ) - { - if ( MercPtrs[ ubID ]->bRegenBoostersUsedToday > 0 ) - { - MercPtrs[ ubID ]->bRegenBoostersUsedToday--; - } - } -} - void HandleQuarterHourUpdate() { //if the game hasnt even started yet ( we havent arrived in the sector ) dont process this @@ -528,6 +514,39 @@ void HourlyLarryUpdate() } } } +#include "Interface.h" +// Flugente: mercs that are smokers occasionally consume smokes if they have some in their inventory +void HourlySmokerUpdate( ) +{ + SOLDIERTYPE * pSoldier = NULL; + OBJECTTYPE* pObj = NULL; + + for ( UINT32 cnt = gTacticalStatus.Team[OUR_TEAM].bFirstID; cnt <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++cnt ) + { + pSoldier = MercPtrs[cnt]; + + if ( pSoldier && pSoldier->bActive && !pSoldier->flags.fMercAsleep ) + { + // if we are a smoker, there is a chance that we will look fo cigarettes in our inventory, and consume them if we find any + if ( Chance(33) && pSoldier->GetBackgroundValue( BG_SMOKERTYPE ) == 1 ) + { + INT8 invsize = (INT8)pSoldier->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 ( pSoldier->inv[bLoop].exists( ) && Item[pSoldier->inv[bLoop].usItem].cigarette ) + { + pObj = &(pSoldier->inv[bLoop]); + + if ( ApplyConsumable( pSoldier, pObj, FALSE, FALSE ) ) + { + break; + } + } + } + } + } + } +} // anv: decrease exposed snitch cooldown (for simplified exposition handling) void HourlySnitchUpdate() diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index d6767461..92243175 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -2351,7 +2351,7 @@ void DrawCharStats( INT16 sCharNum ) SetFontBackground(FONT_BLACK); // strength - swprintf( sString, L"%d", pSoldier->stats.bStrength); + swprintf( sString, L"%d", pSoldier->stats.bStrength + pSoldier->bExtraStrength ); // SANDRO - if damaged stat we could regain, show in red until repaired if ( ( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0 )) || (gGameOptions.fFoodSystem && pSoldier->usStarveDamageStrength > 0) ) @@ -2369,6 +2369,10 @@ void DrawCharStats( INT16 sCharNum ) SetFontForeground( FONT_RED ); } } + else if ( pSoldier->bExtraStrength ) + { + SetRGBFontForeground( 250, 5, 250 ); + } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); @@ -2379,7 +2383,7 @@ void DrawCharStats( INT16 sCharNum ) DrawString(sString,usX, STR_Y,CHAR_FONT ); // dexterity - swprintf( sString, L"%d", pSoldier->stats.bDexterity ); + swprintf( sString, L"%d", pSoldier->stats.bDexterity + pSoldier->bExtraDexterity ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_DEXTERITY] > 0 )) @@ -2397,6 +2401,10 @@ void DrawCharStats( INT16 sCharNum ) SetFontForeground( FONT_RED ); } } + else if ( pSoldier->bExtraDexterity ) + { + SetRGBFontForeground( 250, 5, 250 ); + } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); @@ -2407,7 +2415,7 @@ void DrawCharStats( INT16 sCharNum ) DrawString(sString,usX, DEX_Y,CHAR_FONT ); // agility - swprintf( sString, L"%d", pSoldier->stats.bAgility ); + swprintf( sString, L"%d", pSoldier->stats.bAgility + pSoldier->bExtraAgility ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_AGILITY] > 0 )) @@ -2425,6 +2433,10 @@ void DrawCharStats( INT16 sCharNum ) SetFontForeground( FONT_RED ); } } + else if ( pSoldier->bExtraAgility ) + { + SetRGBFontForeground( 250, 5, 250 ); + } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); @@ -2435,7 +2447,7 @@ void DrawCharStats( INT16 sCharNum ) DrawString(sString,usX, AGL_Y,CHAR_FONT ); // wisdom - swprintf( sString, L"%d", pSoldier->stats.bWisdom ); + swprintf( sString, L"%d", pSoldier->stats.bWisdom + pSoldier->bExtraWisdom ); // SANDRO - if damaged stat we could regain, show in red until repaired if( gGameOptions.fNewTraitSystem && ( pSoldier->ubCriticalStatDamage[DAMAGED_STAT_WISDOM] > 0 )) @@ -2453,6 +2465,10 @@ void DrawCharStats( INT16 sCharNum ) SetFontForeground( FONT_RED ); } } + else if ( pSoldier->bExtraWisdom ) + { + SetRGBFontForeground( 250, 5, 250 ); + } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); @@ -2491,7 +2507,7 @@ void DrawCharStats( INT16 sCharNum ) DrawString(sString,usX, LDR_Y,CHAR_FONT ); // experience level - swprintf( sString, L"%d", pSoldier->stats.bExpLevel ); + swprintf( sString, L"%d", pSoldier->stats.bExpLevel + pSoldier->bExtraExpLevel ); if( ( GetJA2Clock() < CHANGE_STAT_RECENTLY_DURATION + pSoldier->timeChanges.uiChangeLevelTime)&&( pSoldier->timeChanges.uiChangeLevelTime != 0 ) ) { @@ -2504,6 +2520,10 @@ void DrawCharStats( INT16 sCharNum ) SetFontForeground( FONT_RED ); } } + else if ( pSoldier->bExtraExpLevel ) + { + SetRGBFontForeground( 250, 5, 250 ); + } else { SetFontForeground(CHAR_TEXT_FONT_COLOR); @@ -9535,50 +9555,12 @@ void MAPInvClickCamoCallback( MOUSE_REGION *pRegion, INT32 iReason ) if ( gpItemPointer && pSoldier ) { - BOOLEAN fGoodAPs = FALSE; - BOOLEAN fDoSound = FALSE; - // We are doing this ourselve, continue if ( pSoldier->stats.bLife >= CONSCIOUSNESS ) { - // Try to apply camo.... - if ( ApplyCammo( pSoldier, gpItemPointer, &fGoodAPs ) ) + if ( ApplyConsumable( pSoldier, gpItemPointer, FALSE, TRUE ) ) { - if ( fGoodAPs ) - { - fDoSound = TRUE; - - // WANNE: We should only delete the face, if there was a camo we applied. - // This should fix the bug and crashes with missing faces - if ( gGameExternalOptions.fShowCamouflageFaces ) - { - // Flugente: refresh face regardless of result of SetCamoFace(), otherwise applying a rag will not clean the picture - SetCamoFace( pSoldier ); - DeleteSoldierFace( pSoldier );// remove face - gpItemPointerSoldier->iFaceIndex = InitSoldierFace( pSoldier );// create new face - } - } - } - else if ( !gGameOptions.fFoodSystem && ApplyCanteen( pSoldier, gpItemPointer, &fGoodAPs, TRUE ) ) - { - ; - } - else if ( ApplyElixir( pSoldier, gpItemPointer, &fGoodAPs ) ) - { - fDoSound = TRUE; - } - else if ( ApplyDrugs( pSoldier, gpItemPointer ) ) - { - fGoodAPs = TRUE; - fDoSound = TRUE; - } - else if ( gGameOptions.fFoodSystem && ApplyFood( pSoldier, gpItemPointer, FALSE, FALSE ) ) - { - fGoodAPs = TRUE; - } - else if ( ApplyClothes( pSoldier, gpItemPointer ) ) - { - fGoodAPs = TRUE; + UpdateMercBodyRegionHelpText( ); } else { @@ -9595,20 +9577,6 @@ void MAPInvClickCamoCallback( MOUSE_REGION *pRegion, INT32 iReason ) //EndItemPointer( ); MAPEndItemPointer( ); } - - if ( fGoodAPs ) - { - // Dirty - fInterfacePanelDirty = DIRTYLEVEL2; - - UpdateMercBodyRegionHelpText( ); - } - - if ( fDoSound ) - { - // Say OK acknowledge.... - pSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 ); - } } } } diff --git a/Tactical/Arms Dealer Init.cpp b/Tactical/Arms Dealer Init.cpp index bc725599..8c3a91aa 100644 --- a/Tactical/Arms Dealer Init.cpp +++ b/Tactical/Arms Dealer Init.cpp @@ -1013,7 +1013,7 @@ UINT32 GetArmsDealerItemTypeFromItemNumber( UINT16 usItem ) break; case IC_MISC: { - if ( Item [usItem].alcohol ) + if ( Item [usItem].alcohol > 0.0f ) return( ARMS_DEALER_ALCOHOL ); else if ( Item [usItem].electronic ) return( ARMS_DEALER_ELECTRONICS ); diff --git a/Tactical/Campaign.cpp b/Tactical/Campaign.cpp index 34c09af3..cdae2615 100644 --- a/Tactical/Campaign.cpp +++ b/Tactical/Campaign.cpp @@ -183,8 +183,7 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh if (usNumChances == 0) return; - - + usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile->bExpLevel); usSubpointsPerLevel = SubpointsPerPoint(EXPERAMT, pProfile->bExpLevel); @@ -262,15 +261,13 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh // training always affected by wisdom fAffectedByWisdom = TRUE; } - - + // stats/skills of 0 can NEVER be improved! if ( bCurrentRating < 0 ) { return; } - // loop once for each chance to improve for (uiCnt = 0; uiCnt < usNumChances; uiCnt++) { diff --git a/Tactical/Disease.cpp b/Tactical/Disease.cpp index a51e7e76..65cad5f8 100644 --- a/Tactical/Disease.cpp +++ b/Tactical/Disease.cpp @@ -19,6 +19,7 @@ #include "strategic.h" #include "DynamicDialogue.h" #include +#include "Drugs And Alcohol.h" // for DoesMercHaveDisability( ... ) //GLOBALS DISEASE Disease[NUM_DISEASES]; @@ -422,7 +423,7 @@ void HandlePossibleInfection( SOLDIERTYPE *pSoldier, SOLDIERTYPE* pOtherSoldier, if ( aInfectionType == INFECTION_TYPE_TROPICS || aInfectionType == INFECTION_TYPE_SWAMP ) { // if we are afraid of insects, we will be more careful around them - lower chance to be infected - if ( gMercProfiles[pSoldier->ubProfile].bDisability == FEAR_OF_INSECTS ) + if ( DoesMercHaveDisability( pSoldier, FEAR_OF_INSECTS ) ) dChance *= 0.7f; } else if ( aInfectionType == INFECTION_TYPE_CONTACT_HUMAN ) diff --git a/Tactical/Disease.h b/Tactical/Disease.h index 4e3da3ee..f42742c4 100644 --- a/Tactical/Disease.h +++ b/Tactical/Disease.h @@ -98,6 +98,7 @@ typedef struct INT8 sNeedToSleep; // +/- need to sleep INT16 sDrinkModifier; // +/- % water consumption INT16 sFoodModifier; // +/- % water consumption + FLOAT moralemodifier; // a modifier to total morale } DISEASE; //GLOBALS diff --git a/Tactical/Drugs And Alcohol.cpp b/Tactical/Drugs And Alcohol.cpp index 241956e6..e8489e94 100644 --- a/Tactical/Drugs And Alcohol.cpp +++ b/Tactical/Drugs And Alcohol.cpp @@ -23,6 +23,301 @@ class OBJECTTYPE; class SOLDIERTYPE; +BOOLEAN ApplyDrugs_New( SOLDIERTYPE *pSoldier, UINT16 usItem, UINT16 uStatusUsed ) +{ + // If not a drug, return + if ( !Item[usItem].drugtype || !uStatusUsed || !pSoldier ) + return(FALSE); + + UINT32 drugused = Item[usItem].drugtype; + + // we might not use up the entire item, so reduce effects accordingly + FLOAT effectivepercentage = uStatusUsed / 100.0; + + // if this alcohol, alcohol resistance can lower the effects + if ( Item[usItem].alcohol > 0.0f ) + { + effectivepercentage = effectivepercentage * ((100.0 - pSoldier->GetBackgroundValue( BG_RESI_ALCOHOL )) / 100.0); + + FLOAT weight = pSoldier->GetBodyWeight( ); + + // the alcohol amounts in the xml are intended for a person with weight 80. We thus have to alter the effective value + if ( weight > 0.0f ) + { + effectivepercentage *= 80.0f / weight; + } + } + + // we now add drug, disease, personality and disability effects + // every effect has a chance of happening (not entering a chance, so 0, always results in a effect for xml editing simplicity reasons) + + // add effects + std::vector vec_drug = NewDrug[drugused].drug_effects; + + std::vector::iterator drug_effects_itend = vec_drug.end( ); + for ( std::vector::iterator drug_effects_it = vec_drug.begin( ); drug_effects_it != drug_effects_itend; ++drug_effects_it ) + { + if ( !(*drug_effects_it).chance || Chance( (*drug_effects_it).chance ) ) + { + // if we are already under influence of this effect, merge them, otherwise just add effect + if ( pSoldier->newdrugs.duration[(*drug_effects_it).effect] ) + { + INT32 effectsum_existing = pSoldier->newdrugs.duration[(*drug_effects_it).effect] * pSoldier->newdrugs.size[(*drug_effects_it).effect]; + INT32 effectsum_new = (*drug_effects_it).duration * (*drug_effects_it).size; + + INT32 effectsum_total = effectsum_existing + effectsum_new * effectivepercentage; + + UINT16 newduration = (pSoldier->newdrugs.duration[(*drug_effects_it).effect] + (*drug_effects_it).duration) / 2; + + if ( newduration ) + { + INT32 newsize = effectsum_total / newduration; + + pSoldier->newdrugs.duration[(*drug_effects_it).effect] = newduration; + pSoldier->newdrugs.size[(*drug_effects_it).effect] = newsize; + } + } + else + { + pSoldier->newdrugs.duration[(*drug_effects_it).effect] = (*drug_effects_it).duration; + pSoldier->newdrugs.size[(*drug_effects_it).effect] = (*drug_effects_it).size * effectivepercentage; + } + } + } + + // add diseases + std::vector vec_disease = NewDrug[drugused].disease_effects; + + std::vector::iterator disease_effects_itend = vec_disease.end( ); + for ( std::vector::iterator disease_effects_it = vec_disease.begin( ); disease_effects_it != disease_effects_itend; ++disease_effects_it ) + { + if ( !(*disease_effects_it).chance || Chance( (*disease_effects_it).chance ) ) + { + pSoldier->AddDiseasePoints( (*disease_effects_it).disease, (*disease_effects_it).size * effectivepercentage ); + } + } + + // add disability + std::vector vec_disability = NewDrug[drugused].disability_effects; + + std::vector::iterator disability_effects_itend = vec_disability.end( ); + for ( std::vector::iterator disability_effects_it = vec_disability.begin( ); disability_effects_it != disability_effects_itend; ++disability_effects_it ) + { + if ( !(*disability_effects_it).chance || Chance( (*disability_effects_it).chance ) ) + { + if ( pSoldier->newdrugs.drugdisability == (*disability_effects_it).disability ) + { + pSoldier->newdrugs.drugdisability_duration += (*disability_effects_it).duration * effectivepercentage; + } + else + { + pSoldier->newdrugs.drugdisability = (*disability_effects_it).disability; + pSoldier->newdrugs.drugdisability_duration = (*disability_effects_it).duration * effectivepercentage; + } + } + } + + // add personality + std::vector vec_personality = NewDrug[drugused].personality_effects; + + std::vector::iterator personality_effects_itend = vec_personality.end( ); + for ( std::vector::iterator personality_effects_it = vec_personality.begin( ); personality_effects_it != personality_effects_itend; ++personality_effects_it ) + { + if ( !(*personality_effects_it).chance || Chance( (*personality_effects_it).chance ) ) + { + if ( pSoldier->newdrugs.drugpersonality == (*personality_effects_it).personality ) + { + pSoldier->newdrugs.drugpersonality_duration += (*personality_effects_it).duration * effectivepercentage; + } + else + { + pSoldier->newdrugs.drugpersonality = (*personality_effects_it).personality; + pSoldier->newdrugs.drugpersonality_duration = (*personality_effects_it).duration * effectivepercentage; + } + } + } + + // do switch for Larry!! + if ( pSoldier->ubProfile == LARRY_NORMAL ) + { + pSoldier = SwapLarrysProfiles( pSoldier ); + } + else if ( pSoldier->ubProfile == LARRY_DRUNK ) + { + gMercProfiles[LARRY_DRUNK].bNPCData = 0; + } + + if ( NewDrug[drugused].opinionevent ) + { + HandleDynamicOpinionChange( pSoldier, OPINIONEVENT_ADDICT, TRUE, TRUE ); + } + + if ( Item[usItem].alcohol > 0.0f ) + { + FLOAT weight = pSoldier->GetBodyWeight( ); + + // the alcohol amounts in the xml are intended for a person with weight 80. We thus have to alter the effective value + if ( weight > 0.0f ) + { + // added promille = alcohol added (g) / (weight of person (kg) * 0.7) + FLOAT addedpromille = (Item[usItem].alcohol * effectivepercentage) / (weight * 0.7); + + pSoldier->newdrugs.drinkstaken += addedpromille; + } + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[MSG_DRANK_SOME], pSoldier->GetName( ), ShortItemNames[usItem] ); + + HandleDynamicOpinionTeamDrinking( pSoldier ); + } + else + { + // set flag: we are on non-alcoholic drugs + pSoldier->usSoldierFlagMask |= SOLDIER_DRUGGED; + + if ( gMercProfiles[pSoldier->ubProfile].ubNumTimesDrugUseInLifetime != 255 ) + { + gMercProfiles[pSoldier->ubProfile].ubNumTimesDrugUseInLifetime++; + } + + if ( Item[usItem].cigarette ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[MSG_MERC_TOOK_CIGARETTE], pSoldier->GetName( ), ShortItemNames[usItem] ); + } + else + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[MSG_MERC_TOOK_DRUG], pSoldier->GetName( ) ); + } + } + + // Dirty panel + fInterfacePanelDirty = DIRTYLEVEL2; + + return TRUE; +} + +void HandleEndTurnDrugAdjustments_New( SOLDIERTYPE *pSoldier ) +{ + // some effects are handled here + if ( pSoldier->newdrugs.size[DRUG_EFFECT_HP] ) + { + // increase life + pSoldier->stats.bLife = __min( pSoldier->stats.bLife + pSoldier->newdrugs.size[DRUG_EFFECT_HP], pSoldier->stats.bLifeMax ); + + //SANDRO - Insta-healable injury reduction + if ( pSoldier->newdrugs.size[DRUG_EFFECT_HP] > 0 ) + { + pSoldier->iHealableInjury = max( 0, (pSoldier->iHealableInjury - (100 * pSoldier->newdrugs.size[DRUG_EFFECT_HP])) ); + } + + if ( pSoldier->stats.bLife == pSoldier->stats.bLifeMax ) + { + pSoldier->bBleeding = 0; + pSoldier->iHealableInjury = 0; + } + else if ( pSoldier->bBleeding + pSoldier->stats.bLife > pSoldier->stats.bLifeMax ) + { + // got to reduce amount of bleeding + pSoldier->bBleeding = (pSoldier->stats.bLifeMax - pSoldier->stats.bLife); + } + } + + pSoldier->bExtraStrength += pSoldier->newdrugs.size[DRUG_EFFECT_STR]; + pSoldier->bExtraDexterity += pSoldier->newdrugs.size[DRUG_EFFECT_DEX]; + pSoldier->bExtraAgility += pSoldier->newdrugs.size[DRUG_EFFECT_AGI]; + pSoldier->bExtraWisdom += pSoldier->newdrugs.size[DRUG_EFFECT_WIS]; + + BOOLEAN fStillDrugged = FALSE; + + // as time progresses, effects wear off + for ( UINT8 i = 0; i < DRUG_EFFECT_MAX; ++i ) + { + pSoldier->newdrugs.duration[i] = max( 0, pSoldier->newdrugs.duration[i] - 1 ); + + if ( !pSoldier->newdrugs.duration[i] ) + pSoldier->newdrugs.size[i] = 0; + else + fStillDrugged = TRUE; + } + + pSoldier->newdrugs.drugpersonality_duration = max( 0, pSoldier->newdrugs.drugpersonality_duration - 1 ); + + if ( !pSoldier->newdrugs.drugpersonality_duration ) + pSoldier->newdrugs.drugpersonality = 0; + else + fStillDrugged = TRUE; + + pSoldier->newdrugs.drugdisability_duration = max( 0, pSoldier->newdrugs.drugdisability_duration - 1 ); + + if ( !pSoldier->newdrugs.drugdisability_duration ) + pSoldier->newdrugs.drugdisability = 0; + else + fStillDrugged = TRUE; + + if ( !fStillDrugged ) + { + pSoldier->usSoldierFlagMask &= ~SOLDIER_DRUGGED; + + fInterfacePanelDirty = DIRTYLEVEL1; + } +} + +INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier ) +{ + if ( pSoldier->usSoldierFlagMask2 & SOLDIER_HUNGOVER ) + { + return HUNGOVER; + } + + if ( pSoldier->newdrugs.drinkstaken <= 0.01 ) + { + return SOBER; + } + else if ( pSoldier->newdrugs.drinkstaken <= 0.7 ) + { + return FEELING_GOOD; + } + else if ( pSoldier->newdrugs.drinkstaken <= 2.0 ) + { + return BORDERLINE; + } + + return DRUNK; +} + +// does a merc have a disability/personality, or is he under drugs that simulate this? +BOOLEAN DoesMercHaveDisability( SOLDIERTYPE *pSoldier, UINT8 aVal ) +{ + if ( pSoldier->ubProfile != NO_PROFILE ) + { + if ( gMercProfiles[pSoldier->ubProfile].bDisability == aVal ) + return TRUE; + + if ( pSoldier->newdrugs.drugdisability == aVal ) + return TRUE; + } + + return FALSE; +} + +BOOLEAN DoesMercHavePersonality( SOLDIERTYPE *pSoldier, UINT8 aVal ) +{ + // personalities are new trait system only! + if ( !gGameOptions.fNewTraitSystem ) + return FALSE; + + if ( pSoldier->ubProfile != NO_PROFILE ) + { + if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == aVal ) + return TRUE; + + if ( pSoldier->newdrugs.drugpersonality == aVal ) + return TRUE; + } + + return FALSE; +} + +//------------------------------------------------------- /*UINT8 ubDrugTravelRate[] = { 4, 2 }; UINT8 ubDrugWearoffRate[] = { 2, 2 }; @@ -43,7 +338,7 @@ INT32 giDrunkModifier[] = #define HANGOVER_BP_REDUCE 200 -BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject ) +/*BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject ) { UINT32 ubDrugType; INT8 bRegenPointsGained; @@ -262,9 +557,9 @@ BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject ) ApplyFood( pSoldier, pObject, TRUE, TRUE ); return( TRUE ); -} +}*/ -void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier ) +/*void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier ) { INT32 cnt, cnt2; INT32 iNumLoops; @@ -508,72 +803,36 @@ void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier ) // if all drug effects have ended, delete flag if ( !MercUnderTheInfluence(pSoldier) ) pSoldier->usSoldierFlagMask &= ~SOLDIER_DRUGGED; -} +}*/ void HandleAPEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT16 *pubPoints ) { - INT8 bDrunkLevel; - INT16 sPoints = (*pubPoints); - - // Are we in a side effect or good effect? - if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] ) - { - // Adjust! - sPoints += pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ]; - } - else if ( pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_ADRENALINE ] ) - { - // Adjust! - sPoints -= pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_ADRENALINE ]; - - if ( sPoints < APBPConstants[AP_MINIMUM] ) - { - sPoints = APBPConstants[AP_MINIMUM]; - } - } + *pubPoints += pSoldier->newdrugs.size[DRUG_EFFECT_AP]; - bDrunkLevel = GetDrunkLevel( pSoldier ); - - if ( bDrunkLevel == HUNGOVER ) + if ( GetDrunkLevel( pSoldier ) == HUNGOVER ) { // Reduce.... - sPoints -= HANGOVER_AP_REDUCE; + *pubPoints -= HANGOVER_AP_REDUCE; - if ( sPoints < APBPConstants[AP_MINIMUM] ) + if ( *pubPoints < APBPConstants[AP_MINIMUM] ) { - sPoints = APBPConstants[AP_MINIMUM]; + *pubPoints = APBPConstants[AP_MINIMUM]; } } - - (*pubPoints) = sPoints; } void HandleBPEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT16 *psPointReduction ) { - INT8 bDrunkLevel; - - // Are we in a side effect or good effect? - if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] ) - { - // Adjust! - (*psPointReduction) -= ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] * APBPConstants[BP_RATIO_RED_PTS_TO_NORMAL] ); - } - else if ( pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_ADRENALINE ] ) - { - // Adjust! - (*psPointReduction) += ( pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_ADRENALINE ] * APBPConstants[BP_RATIO_RED_PTS_TO_NORMAL] ); - } - - bDrunkLevel = GetDrunkLevel( pSoldier ); - - if ( bDrunkLevel == HUNGOVER ) + *psPointReduction -= pSoldier->newdrugs.size[DRUG_EFFECT_BP]; + + if ( GetDrunkLevel( pSoldier ) == HUNGOVER ) { // Reduce.... (*psPointReduction) += HANGOVER_BP_REDUCE; } } -void HandleDamageResistanceEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT32 *psPointReduction ) +/*void HandleDamageResistanceEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT32 *psPointReduction ) { // Are we in a side effect or good effect? if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_RESISTANCE ] ) @@ -586,9 +845,9 @@ void HandleDamageResistanceEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT32 *psPoi // Adjust! (*psPointReduction) -= pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_RESISTANCE ]; } -} +}*/ -INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier ) +/*INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier ) { INT8 bNumDrinks; @@ -618,14 +877,14 @@ INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier ) { return( DRUNK ); } -} +}*/ INT32 EffectStatForBeingDrunk( SOLDIERTYPE *pSoldier, INT32 iStat ) { return( ( iStat * giDrunkModifier[ GetDrunkLevel( pSoldier ) ] / 100 ) ); } -BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier ) +/*BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier ) { for (UINT8 cnt = DRUG_TYPE_ADRENALINE; cnt < DRUG_TYPE_MAX; ++cnt) { @@ -634,9 +893,20 @@ BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier ) } return( FALSE ); +}*/ + +BOOLEAN MercDruggedOrDrunk( SOLDIERTYPE *pSoldier ) +{ + if ( pSoldier->newdrugs.drinkstaken ) + return TRUE; + + if ( pSoldier->usSoldierFlagMask & SOLDIER_DRUGGED ) + return TRUE; + + return FALSE; } -BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier, UINT8 aDrugType ) +/*BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier, UINT8 aDrugType ) { // in case of wrong inout, stay safe if ( aDrugType >= DRUG_TYPE_MAX ) @@ -653,18 +923,26 @@ BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier, UINT8 aDrugType ) return( TRUE ); return( FALSE ); -} +}*/ -BOOLEAN MercDruggedButNotDrunk( SOLDIERTYPE *pSoldier ) +BOOLEAN MercDrugged( SOLDIERTYPE *pSoldier ) { - for (UINT8 cnt = DRUG_TYPE_ADRENALINE; cnt < DRUG_TYPE_MAX; ++cnt) + return (pSoldier->usSoldierFlagMask & SOLDIER_DRUGGED); +} + +void HourlyDrugUpdate( ) +{ + for ( UINT16 ubID = gTacticalStatus.Team[OUR_TEAM].bFirstID; ubID <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++ubID ) { - if ( cnt == DRUG_TYPE_ALCOHOL ) - continue; + // every hour, we lower our alcohol counter + if ( MercPtrs[ubID]->newdrugs.drinkstaken > 0.0f ) + { + MercPtrs[ubID]->newdrugs.drinkstaken = max( 0.0, MercPtrs[ubID]->newdrugs.drinkstaken - 0.15f ); - if ( MercUnderTheInfluence(pSoldier, cnt) ) - return TRUE; + if ( MercPtrs[ubID]->newdrugs.drinkstaken <= 0.0f ) + { + MercPtrs[ubID]->usSoldierFlagMask2 &= ~SOLDIER_HUNGOVER; + } + } } - - return( FALSE ); } diff --git a/Tactical/Drugs And Alcohol.h b/Tactical/Drugs And Alcohol.h index 4f220750..b30ce916 100644 --- a/Tactical/Drugs And Alcohol.h +++ b/Tactical/Drugs And Alcohol.h @@ -3,18 +3,99 @@ #include "Soldier Control.h" -#define SOBER 0 +class DRUG_EFFECT +{ + /*bool operator==(const DRUG_EFFECT& other) + { + return ( effect == other.effect && + duration == other.duration && + size == other.size && + chance == other.chance); + } + + bool operator!=(const DRUG_EFFECT& other) + { + return !(*this == other); + }*/ + +public: + + UINT8 effect; + UINT16 duration; + INT16 size; + UINT8 chance; +}; + +typedef struct +{ + UINT8 disease; + INT32 size; + UINT8 chance; +} DISEASE_EFFECT; + +typedef struct +{ + UINT8 disability; + UINT16 duration; + UINT8 chance; +} DISABILITY_EFFECT; + +typedef struct +{ + UINT8 personality; + UINT16 duration; + UINT8 chance; +} PERSONALITY_EFFECT; + +typedef struct +{ + UINT8 uiIndex; + CHAR16 szName[80]; // name, used for display + BOOLEAN opinionevent; + + std::vector drug_effects; + std::vector disease_effects; + std::vector disability_effects; + std::vector personality_effects; +} DRUG; + +//GLOBALS +#define NEW_DRUGS_MAX 100 + +extern DRUG NewDrug[NEW_DRUGS_MAX]; + +enum { + SOBER = 0, + FEELING_GOOD, + BORDERLINE, + DRUNK, + HUNGOVER, +}; + +BOOLEAN ApplyDrugs_New( SOLDIERTYPE *pSoldier, UINT16 usItem, UINT16 uStatusUsed ); + +void HandleEndTurnDrugAdjustments_New( SOLDIERTYPE *pSoldier ); + +INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier ); + +// does a merc have a disability/personality, or is he under drugs that simulate this? +BOOLEAN DoesMercHaveDisability( SOLDIERTYPE *pSoldier, UINT8 aVal ); +BOOLEAN DoesMercHavePersonality( SOLDIERTYPE *pSoldier, UINT8 aVal ); + +//---------------------------------------------------------------------------------------- + +/*#define SOBER 0 #define FEELING_GOOD 1 #define BORDERLINE 2 #define DRUNK 3 -#define HUNGOVER 4 +#define HUNGOVER 4 */ -#define REGEN_POINTS_PER_BOOSTER 4 -#define LIFE_GAIN_PER_REGEN_POINT 10 +//#define REGEN_POINTS_PER_BOOSTER 4 +//#define LIFE_GAIN_PER_REGEN_POINT 10 -extern UINT8 gbPlayerNum; +//extern UINT8 gbPlayerNum; -enum { +/*enum { DRUG_TYPE_ADRENALINE = 0, DRUG_TYPE_ALCOHOL, DRUG_TYPE_REGENERATION, @@ -73,9 +154,9 @@ enum { #define DRUG_MISC_15 0x10000000 //268435456 #define DRUG_MISC_16 0x20000000 //536870912 #define DRUG_MISC_17 0x40000000 //1073741824 -#define DRUG_MISC_18 0x80000000 //2147483648 +#define DRUG_MISC_18 0x80000000 //2147483648*/ -typedef struct +/*typedef struct { UINT8 ubType; // type of drug: bit field UINT8 ubDrugTravelRate; @@ -89,19 +170,22 @@ typedef struct } DRUGTYPE; //GLOBALS -extern DRUGTYPE Drug[DRUG_TYPE_MAX]; +extern DRUGTYPE Drug[DRUG_TYPE_MAX];*/ -BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject ); +//BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject ); -void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier ); +//void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier ); void HandleAPEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT16 *pubPoints ); void HandleBPEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT16 *psPoints ); -void HandleDamageResistanceEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT32 *psPoints ); +//void HandleDamageResistanceEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT32 *psPoints ); -INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier ); +//INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier ); INT32 EffectStatForBeingDrunk( SOLDIERTYPE *pSoldier, INT32 iStat ); -BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier ); -BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier, UINT8 aDrugType ); -BOOLEAN MercDruggedButNotDrunk( SOLDIERTYPE *pSoldier ); +//BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier ); +BOOLEAN MercDruggedOrDrunk( SOLDIERTYPE *pSoldier ); +//BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier, UINT8 aDrugType ); +BOOLEAN MercDrugged( SOLDIERTYPE *pSoldier ); + +void HourlyDrugUpdate(); #endif diff --git a/Tactical/DynamicDialogue.cpp b/Tactical/DynamicDialogue.cpp index b29693d3..558fa30b 100644 --- a/Tactical/DynamicDialogue.cpp +++ b/Tactical/DynamicDialogue.cpp @@ -198,6 +198,17 @@ INT8 SoldierRelation( SOLDIERTYPE* pSoldierA, SOLDIERTYPE* pSoldierB ) bOpinion -= 2; } + // smoker + INT16 smokerA = pSoldierA->GetBackgroundValue( BG_SMOKERTYPE ); + INT16 smokerB = pSoldierB->GetBackgroundValue( BG_SMOKERTYPE ); + if ( smokerA && smokerB ) + { + if ( smokerA != smokerB ) + bOpinion -= 2; + else + bOpinion += 1; + } + if ( pSoldierA->HasBackgroundFlag( BACKGROUND_XENOPHOBIC ) && pSoldierB->ubProfile != NO_PROFILE && gMercProfiles[pSoldierA->ubProfile].usBackground != gMercProfiles[pSoldierB->ubProfile].usBackground ) bOpinion -= gGameExternalOptions.sMoraleModXenophobicBackGround; @@ -1818,7 +1829,7 @@ void HandleDynamicOpinionRetreat( ) void HandleDynamicOpinionTeamDrinking( SOLDIERTYPE* pSoldier ) { // need to be drunk for this - if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE || !MercUnderTheInfluence( pSoldier, DRUG_TYPE_ALCOHOL ) ) + if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE || !pSoldier->newdrugs.drinkstaken <= 0.0 ) return; SOLDIERTYPE* pTeamSoldier = NULL; @@ -1829,7 +1840,7 @@ void HandleDynamicOpinionTeamDrinking( SOLDIERTYPE* pSoldier ) // everybody other merc in the same sector can get updated if they are drugged too if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile && pTeamSoldier->sSectorX == pSoldier->sSectorX && pTeamSoldier->sSectorY == pSoldier->sSectorY && pTeamSoldier->bSectorZ == pSoldier->bSectorZ && - MercUnderTheInfluence( pTeamSoldier, DRUG_TYPE_ALCOHOL ) && + pTeamSoldier->newdrugs.drinkstaken > 0.0 && !(pTeamSoldier->bAssignment == IN_TRANSIT || pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) ) { @@ -2252,12 +2263,12 @@ void HandleDynamicOpinionChange( SOLDIERTYPE* pSoldier, UINT8 usEvent, BOOLEAN f case OPINIONEVENT_BRUTAL_BAD: // if we are a good guy or a pacifist, then we dislike excessive violence if ( gMercProfiles[pTeamSoldier->ubProfile].ubMiscFlags3 & PROFILE_MISC_FLAG3_GOODGUY || - gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_PACIFIST ) + DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_PACIFIST ) ) usEventUsed = OPINIONEVENT_BRUTAL_BAD; // if we are malicious, agressive or a psycho, then we like it - else if ( gMercProfiles[pTeamSoldier->ubProfile].bDisability == PSYCHO || MercUnderTheInfluence( pTeamSoldier, DRUG_TYPE_PSYCHO ) || - gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE || - gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_MALICIOUS ) + else if ( DoesMercHaveDisability( pTeamSoldier, PSYCHO ) || + DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_AGGRESSIVE ) || + DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_MALICIOUS ) ) usEventUsed = OPINIONEVENT_BRUTAL_GOOD; else continue; @@ -2272,7 +2283,7 @@ void HandleDynamicOpinionChange( SOLDIERTYPE* pSoldier, UINT8 usEvent, BOOLEAN f if ( pTeamSoldier->ubTargetID == pSoldier->ubTargetID && pTeamSoldier->sTargetGridNo == pSoldier->sTargetGridNo ) { // are we ambitious enough to care about kill counts? - if ( gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE || gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_SHOWOFF ) + if ( DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_ASSERTIVE ) || DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_SHOWOFF ) ) { // did we have enough AP to claim we were about to finish them? if ( !EnoughPoints( pTeamSoldier, 60, 0, FALSE ) ) @@ -2291,16 +2302,15 @@ void HandleDynamicOpinionChange( SOLDIERTYPE* pSoldier, UINT8 usEvent, BOOLEAN f case OPINIONEVENT_BATTLE_TOOK_PRISONER: // we only care if we prefer the enemy to be taken alive if ( !(gMercProfiles[pTeamSoldier->ubProfile].ubMiscFlags3 & PROFILE_MISC_FLAG3_GOODGUY || - gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL || - gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_PACIFIST) ) - continue; + DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_INTELLECTUAL ) || + DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_PACIFIST ) ) ) + continue; break; case OPINIONEVENT_CIV_ATTACKER: // psychos or malicious characters dont care - if ( gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_MALICIOUS || - gMercProfiles[pTeamSoldier->ubProfile].bDisability == PSYCHO || - MercUnderTheInfluence( pTeamSoldier, DRUG_TYPE_PSYCHO ) ) + if ( DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_MALICIOUS ) || + DoesMercHaveDisability( pTeamSoldier, PSYCHO ) ) continue; break; diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index 316e2a19..72fec5e7 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -2149,8 +2149,8 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE bNumRightIcons++; } - // Flugente: add drug symbol if drugged (without alcohol 'drug') - if ( MercDruggedButNotDrunk( MercPtrs[ pFace->ubSoldierID ] ) ) + // Flugente: add drug symbol if drugged (without alcohol) + if ( MercDrugged( MercPtrs[pFace->ubSoldierID] ) ) { DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 7 ); bNumRightIcons++; diff --git a/Tactical/Food.cpp b/Tactical/Food.cpp index 64e76173..a9b28819 100644 --- a/Tactical/Food.cpp +++ b/Tactical/Food.cpp @@ -100,7 +100,64 @@ void AddFoodpoints( INT32& arCurrentFood, INT32 aVal ) arCurrentFood = max(arCurrentFood, FOOD_MIN); } -BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, BOOLEAN fForce, BOOLEAN fForceFromDrugs ) +BOOLEAN DoesSoldierRefuseToEat( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj ) +{ + if ( gGameOptions.fFoodSystem ) + { + // static variables to remember the last food someone was forced to eat + static UINT8 lasteater = 0; + static UINT16 lastitem = 0; + + UINT32 foodtype = Item[pObj->usItem].foodtype; + + if ( !foodtype ) + return FALSE; + + // check if we are willing to eat this: if we're filled, the merc refuses + if ( ((Food[foodtype].bFoodPoints > 0 && pSoldier->bFoodLevel > FoodMoraleMods[FOOD_MERC_REFUSAL].bThreshold) || Food[foodtype].bFoodPoints <= 0) && + ((Food[foodtype].bDrinkPoints > 0 && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_MERC_REFUSAL].bThreshold) || Food[foodtype].bDrinkPoints <= 0) ) + { + // Say quote! + TacticalCharacterDialogue( pSoldier, QUOTE_PRE_NOT_SMART ); + + return TRUE; + } + + // we have to determine wether the food is rotten, that might influence its condition and poison us + FLOAT foodcondition = (*pObj)[0]->data.bTemperature / OVERHEATING_MAX_TEMPERATURE; + + // food in bad condition is harmful! + if ( foodcondition < FOOD_BAD_THRESHOLD ) + { + // if we can choose to reject a food and haven't yet done so with this type of bad food, do so. Works only once + if ( (lasteater != pSoldier->ubID || lastitem != pObj->usItem) ) + { + lasteater = pSoldier->ubID; + lastitem = pObj->usItem; + + // notification + // do we eat or drink this stuff? + UINT8 type = AP_EAT; + if ( Food[foodtype].bDrinkPoints > Food[foodtype].bFoodPoints ) + type = AP_DRINK; + + if ( type == AP_EAT ) + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFoodTextStr[STR_FOOD_DONOTWANT_EAT], pSoldier->GetName( ), Item[pObj->usItem].szItemName ); + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFoodTextStr[STR_FOOD_DONOTWANT_DRINK], pSoldier->GetName( ), Item[pObj->usItem].szItemName ); + + // Say quote! + TacticalCharacterDialogue( pSoldier, QUOTE_PRE_NOT_SMART ); + + return TRUE; + } + } + } + + return FALSE; +} + +BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, UINT16 usPointsToUse ) { // static variables to remember the last food someone was forced to eat static UINT8 lasteater = 0; @@ -128,46 +185,13 @@ BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, BOOLEAN fForce, B UINT8 type = AP_EAT; if ( Food[foodtype].bDrinkPoints > Food[foodtype].bFoodPoints ) type = AP_DRINK; - - // return if we don't have enough APs - if ( !fForceFromDrugs && !EnoughPoints( pSoldier, APBPConstants[type], 0, TRUE ) ) - { - return( FALSE ); - } - - // check if we are willing to eat this: if we're filled, the merc refuses - if ( !fForceFromDrugs && ( ( Food[foodtype].bFoodPoints > 0 && pSoldier->bFoodLevel > FoodMoraleMods[FOOD_MERC_REFUSAL].bThreshold ) || Food[foodtype].bFoodPoints <= 0 ) && ( ( Food[foodtype].bDrinkPoints > 0 && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_MERC_REFUSAL].bThreshold ) || Food[foodtype].bDrinkPoints <= 0 ) ) - { - // Say quote! - TacticalCharacterDialogue( pSoldier, 61 ); - - return( FALSE); - } - + // we have to determine wether the food is rotten, that might influence its condition and poison us FLOAT foodcondition = (*pObject)[0]->data.bTemperature / OVERHEATING_MAX_TEMPERATURE; // food in bad condition is harmful! - if ( !fForceFromDrugs && foodcondition < FOOD_BAD_THRESHOLD ) - { - // if we can choose to reject a food and haven't yet done so with this type of bad food, do so. Works only once - if ( !fForce && ( lasteater != pSoldier->ubID || lastitem != pObject->usItem) ) - { - lasteater = pSoldier->ubID; - lastitem = pObject->usItem; - - // notification - if ( type == AP_EAT ) - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFoodTextStr[STR_FOOD_DONOTWANT_EAT], pSoldier->GetName(), Item[pObject->usItem].szItemName ); - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szFoodTextStr[STR_FOOD_DONOTWANT_DRINK], pSoldier->GetName(), Item[pObject->usItem].szItemName ); - - // Say quote! - TacticalCharacterDialogue( pSoldier, 61 ); - - return( FALSE); - } - + if ( foodcondition < FOOD_BAD_THRESHOLD ) + { // determine the max nutritional value INT32 maxpts = max(Food[foodtype].bFoodPoints, Food[foodtype].bDrinkPoints); @@ -178,7 +202,7 @@ BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, BOOLEAN fForce, B FLOAT conditionmodifier = 0.5f * (1.0f + sqrt(foodcondition)); - FLOAT percentualsize = min(Food[foodtype].ubPortionSize, (*pObject)[0]->data.objectStatus) / 100.0f; + FLOAT percentualsize = usPointsToUse / 100.0f; INT32 foodpts = (INT32) (Food[foodtype].bFoodPoints * percentualsize * conditionmodifier ); INT32 drinkpts = (INT32) (Food[foodtype].bDrinkPoints * percentualsize * conditionmodifier ); @@ -240,17 +264,14 @@ BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, BOOLEAN fForce, B else if ( (*pObject)[0]->data.sObjectFlag & INFECTED && gGameExternalOptions.fDiseaseContaminatesItems ) pSoldier->Infect( 0 ); - // now remove a portion of the food item (or the whole item altogether) - UINT16 ptsconsumed = UseKitPoints( pObject, Food[foodtype].ubPortionSize, pSoldier ); - INT32 sBPAdjustment = 0; // if the food is more of a drink, we also restore breath points if ( Food[foodtype].bDrinkPoints > Food[foodtype].bFoodPoints ) { - sBPAdjustment = 2 * ptsconsumed * -(100 - pSoldier->bBreath); + sBPAdjustment = 2 * usPointsToUse * -(100 - pSoldier->bBreath); } - DeductPoints( pSoldier, APBPConstants[type], sBPAdjustment ); + DeductPoints( pSoldier, 0, sBPAdjustment ); // let it be known that we are eating if ( pSoldier->bTeam == gbPlayerNum && gGameExternalOptions.fFoodEatingSounds ) @@ -370,7 +391,7 @@ void HourlyFoodSituationUpdate( SOLDIERTYPE *pSoldier ) INT8 sectortemperaturemod = SectorTemperature( 0, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ ); // if we are heat intolerant, increase modifier - if ( sectortemperaturemod > 0 && (gMercProfiles[ pSoldier->ubProfile ].bDisability == HEAT_INTOLERANT || MercUnderTheInfluence(pSoldier, DRUG_TYPE_HEATINTOLERANT) ) ) + if ( sectortemperaturemod > 0 && DoesMercHaveDisability( pSoldier, HEAT_INTOLERANT ) ) ++sectortemperaturemod; FLOAT temperaturemodifier = (FLOAT)(3 + sectortemperaturemod)/3; @@ -648,7 +669,7 @@ void EatFromInventory( SOLDIERTYPE *pSoldier, BOOLEAN fcanteensonly ) for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ... { // ... if Item exists and is food ... - if (pSoldier->inv[bLoop].exists() == true && Item[pSoldier->inv[bLoop].usItem].foodtype > 0 ) + if ( pSoldier->inv[bLoop].exists() && Item[pSoldier->inv[bLoop].usItem].foodtype ) { OBJECTTYPE * pObj = &(pSoldier->inv[bLoop]); // ... get pointer for this item ... @@ -680,14 +701,9 @@ void EatFromInventory( SOLDIERTYPE *pSoldier, BOOLEAN fcanteensonly ) // if we're thirsty or hungry, and this is nutritious, consume it if ( ( pSoldier->bDrinkLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bDrinkPoints > 0 ) || ( pSoldier->bFoodLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bFoodPoints > 0 ) ) { - while ( (*pObj)[0]->data.objectStatus > 1 ) + // cannot reject to eat this, we chose to eat this ourself! + while ( (*pObj)[0]->data.objectStatus > 1 && ApplyConsumable( pSoldier, pObj, TRUE, FALSE ) ) { - // if food is also a drug, ApplyDrugs will also call ApplyFood - if ( Item[pObj->usItem].drugtype > 0 ) - ApplyDrugs( pSoldier, pObj ); - else - ApplyFood( pSoldier, pObj, TRUE, FALSE ); // cannot reject to eat this, we chose to eat this ourself! - // if we're full, finish if ( pSoldier->bFoodLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold ) return; @@ -701,7 +717,7 @@ void EatFromInventory( SOLDIERTYPE *pSoldier, BOOLEAN fcanteensonly ) for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ... { // ... if Item exists and is food ... - if (pSoldier->inv[bLoop].exists() == true && Item[pSoldier->inv[bLoop].usItem].foodtype > 0 ) + if ( pSoldier->inv[bLoop].exists() && Item[pSoldier->inv[bLoop].usItem].foodtype ) { OBJECTTYPE * pObj = &(pSoldier->inv[bLoop]); // ... get pointer for this item ... @@ -719,14 +735,9 @@ void EatFromInventory( SOLDIERTYPE *pSoldier, BOOLEAN fcanteensonly ) // if we're thirsty or hungry, and this is nutritious, consume it if ( ( pSoldier->bDrinkLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bDrinkPoints > 0 ) || ( pSoldier->bFoodLevel < FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold && Food[foodtype].bFoodPoints > 0 ) ) { - while ( (*pObj)[0]->data.objectStatus > 1 ) + // cannot reject to eat this, we chose to eat this ourself! + while ( (*pObj)[0]->data.objectStatus > 1 && ApplyConsumable( pSoldier, pObj, TRUE, FALSE ) ) { - // if food is also a drug, ApplyDrugs will also call ApplyFood - if ( Item[pObj->usItem].drugtype > 0 ) - ApplyDrugs( pSoldier, pObj ); - else - ApplyFood( pSoldier, pObj, TRUE, FALSE ); // cannot reject to eat this, we chose to eat this ourself! - // if we're full, finish if ( ( pSoldier->bFoodLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold || Food[foodtype].bFoodPoints == 0 ) && ( pSoldier->bDrinkLevel > FoodMoraleMods[FOOD_MERC_START_CONSUME].bThreshold|| Food[foodtype].bDrinkPoints == 0 ) ) return; diff --git a/Tactical/Food.h b/Tactical/Food.h index 796b7547..8c76febc 100644 --- a/Tactical/Food.h +++ b/Tactical/Food.h @@ -52,7 +52,6 @@ typedef struct CHAR16 szName[80]; // name of this food INT32 bFoodPoints; // points that will be added to our drink level INT32 bDrinkPoints; // points that will be added to our drink level - UINT16 ubPortionSize; // how much is 'eaten' as a portion (percentage) FLOAT usDecayRate; // rate at which food decays } FOODTYPE; @@ -76,9 +75,11 @@ typedef enum WATER_POISONOUS // there is water, but it is poisoned (swamps and polluted sectors) } FoodSectorWaterSupply; +BOOLEAN DoesSoldierRefuseToEat( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj ); + // eat a food object. if fForce = FALSE, the soldier can reject to eat this once // if fForceFromDrugs = TRUE, we HAVE to eat this, because we already got the effects from the ApplyDrugs-function (item is both drug and food) -BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, BOOLEAN fForce, BOOLEAN fForceFromDrugs ); +BOOLEAN ApplyFood( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, UINT16 usPointsToUse ); void GetFoodSituation( SOLDIERTYPE *pSoldier, UINT8* pFoodSituation, UINT8* pWaterSituation ); void FoodMaxMoraleModifiy( SOLDIERTYPE *pSoldier, UINT8* pubMaxMorale ); diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index 08ecb2e1..9fadd5e7 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -474,7 +474,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) ) { // Flugente: drugs can temporarily cause a merc to go psycho - if ( (pSoldier->ubProfile != NO_PROFILE) && ( (gMercProfiles[ pSoldier->ubProfile ].bDisability == PSYCHO) || MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) ) + if ( DoesMercHaveDisability( pSoldier, PSYCHO ) ) { // psychos might possibly switch to burst if they can // Changed by ADB, rev 1513 @@ -549,7 +549,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa // SANDRO - changed Random to PreRandom to avoid save-load mania // Flugente: drugs can temporarily cause a merc to go psycho - if((pSoldier->ubProfile != NO_PROFILE) && ( (gMercProfiles[ pSoldier->ubProfile ].bDisability == PSYCHO) || MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) && PreRandom(100) < 20) + if ( DoesMercHaveDisability( pSoldier, PSYCHO ) && PreRandom( 100 ) < 20 ) { chanceToMisfire = diceSides; ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 26 ], pSoldier->GetName() ); diff --git a/Tactical/Interface Enhanced.cpp b/Tactical/Interface Enhanced.cpp index 823a4233..64c0ea91 100644 --- a/Tactical/Interface Enhanced.cpp +++ b/Tactical/Interface Enhanced.cpp @@ -2571,7 +2571,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr } //////////////////// ALCOHOL - if (Item[ gpItemDescObject->usItem ].alcohol) + if ( Item[gpItemDescObject->usItem].alcohol > 0.0f ) { swprintf( pStr, L"%s%s", szUDBGenSecondaryStatsTooltipText[ 22 ], szUDBGenSecondaryStatsExplanationsTooltipText[ 22 ]); SetRegionFastHelpText( &(gUDBFasthelpRegions[ iFirstDataRegion + cnt ]), pStr ); @@ -4090,7 +4090,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr cnt++; } ////////////////////// PORTION SIZE - if ( Food[foodtype].ubPortionSize != 0 ) + if ( Item[gpItemDescObject->usItem].usPortionSize != 0 ) { if (cnt >= sFirstLine && cnt < sLastLine) { @@ -5769,8 +5769,8 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject ) } cnt++; } - if ( ( Food[Item[gpItemDescObject->usItem].foodtype].ubPortionSize > 0 ) || - ( fComparisonMode && Food[Item[gpComparedItemDescObject->usItem].foodtype].ubPortionSize > 0 ) ) + if ( (Item[gpItemDescObject->usItem].usPortionSize > 0) || + (fComparisonMode && Item[gpComparedItemDescObject->usItem].usPortionSize > 0) ) { //////////////////// PORTION SIZE if (cnt >= sFirstLine && cnt < sLastLine) @@ -6129,8 +6129,8 @@ void DrawSecondaryStats( OBJECTTYPE * gpItemDescObject ) } //////////////////// ALCOHOL - if ( ( Item[ gpItemDescObject->usItem ].alcohol ) || - ( fComparisonMode && Item[ gpComparedItemDescObject->usItem ].alcohol ) ) + if ( (Item[gpItemDescObject->usItem].alcohol > 0.0f) || + (fComparisonMode && Item[gpComparedItemDescObject->usItem].alcohol > 0.0f) ) { BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoSecondaryIcon, 22, gItemDescGenSecondaryRegions[cnt].sLeft+sOffsetX, gItemDescGenSecondaryRegions[cnt].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL ); cnt++; @@ -14057,10 +14057,10 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject ) cnt++; } ////////////////////////// PORTION SIZE - iModifier[0] = Food[fFoodtype].ubPortionSize; + iModifier[0] = Item[gpItemDescObject->usItem].usPortionSize; if( fComparisonMode ) { - iComparedModifier[0] = Food[fComparedFoodtype].ubPortionSize; + iComparedModifier[0] = Item[gpItemDescObject->usItem].usPortionSize; iModifier[0] = iComparedModifier[0] - iModifier[0]; } sTop = gItemDescAdvRegions[cnt-sFirstLine][1].sTop; diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index 88012a92..033b9e10 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -2810,7 +2810,7 @@ BOOLEAN CompatibleItemForApplyingOnMerc( OBJECTTYPE *pTestObject ) // ATE: Would be nice to have flag here to check for these types.... if ( Item[usItem].camouflagekit || usItem == ADRENALINE_BOOSTER || usItem == REGEN_BOOSTER || usItem == SYRINGE_3 || usItem == SYRINGE_4 || usItem == SYRINGE_5 || - Item[usItem].alcohol || Item[usItem].canteen || usItem == JAR_ELIXIR || (usItem == 1022 && gGameExternalOptions.fCamoRemoving) ) // Added rag usable on self - SANDRO + Item[usItem].alcohol > 0.0f || Item[usItem].canteen || usItem == JAR_ELIXIR || (usItem == 1022 && gGameExternalOptions.fCamoRemoving) ) // Added rag usable on self - SANDRO { return( TRUE ); } diff --git a/Tactical/Interface Panels.cpp b/Tactical/Interface Panels.cpp index 06dd9712..a8ce9736 100644 --- a/Tactical/Interface Panels.cpp +++ b/Tactical/Interface Panels.cpp @@ -2766,19 +2766,19 @@ void RenderSMPanel( BOOLEAN *pfDirty ) mprintf( SM_CAMMO_PERCENT_X, SM_CAMMO_PERCENT_Y, L"%%" ); #endif - UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeAgilityTime, ( BOOLEAN ) ( gpSMCurrentMerc->usValueGoneUp & AGIL_INCREASE? TRUE: FALSE ), ( BOOLEAN ) ( ( gGameOptions.fNewTraitSystem && ( gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_AGILITY] > 0 )) ? TRUE : FALSE), MercUnderTheInfluence(gpSMCurrentMerc, DRUG_TYPE_AGILITY)); // SANDRO + UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeAgilityTime, (BOOLEAN)(gpSMCurrentMerc->usValueGoneUp & AGIL_INCREASE ? TRUE : FALSE), (BOOLEAN)((gGameOptions.fNewTraitSystem && (gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_AGILITY] > 0)) ? TRUE : FALSE), gpSMCurrentMerc->bExtraAgility != 0 ); // SANDRO swprintf( sString, L"%2d", gpSMCurrentMerc->stats.bAgility + gpSMCurrentMerc->bExtraAgility ); FindFontRightCoordinates(SM_AGI_X, SM_AGI_Y ,SM_STATS_WIDTH ,SM_STATS_HEIGHT ,sString, BLOCKFONT2, &usX, &usY); mprintf( usX, usY , sString ); - UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeDexterityTime,( BOOLEAN ) ( gpSMCurrentMerc->usValueGoneUp & DEX_INCREASE? TRUE: FALSE ), ( BOOLEAN ) ( ( gGameOptions.fNewTraitSystem && ( gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_DEXTERITY] > 0 )) ? TRUE : FALSE), MercUnderTheInfluence(gpSMCurrentMerc, DRUG_TYPE_DEXTERITY)); // SANDRO + UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeDexterityTime, (BOOLEAN)(gpSMCurrentMerc->usValueGoneUp & DEX_INCREASE ? TRUE : FALSE), (BOOLEAN)((gGameOptions.fNewTraitSystem && (gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_DEXTERITY] > 0)) ? TRUE : FALSE), gpSMCurrentMerc->bExtraDexterity != 0 ); // SANDRO swprintf( sString, L"%2d", gpSMCurrentMerc->stats.bDexterity + gpSMCurrentMerc->bExtraDexterity ); FindFontRightCoordinates(SM_DEX_X, SM_DEX_Y ,SM_STATS_WIDTH ,SM_STATS_HEIGHT ,sString, BLOCKFONT2, &usX, &usY); mprintf( usX, usY , sString ); - UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeStrengthTime, ( BOOLEAN )( gpSMCurrentMerc->usValueGoneUp & STRENGTH_INCREASE?TRUE: FALSE ), ( BOOLEAN ) ( (( gGameOptions.fNewTraitSystem && ( gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0 )) || (gGameOptions.fFoodSystem && gpSMCurrentMerc->usStarveDamageStrength > 0) ) ? TRUE : FALSE), MercUnderTheInfluence(gpSMCurrentMerc, DRUG_TYPE_STRENGTH)); // SANDRO + UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeStrengthTime, (BOOLEAN)(gpSMCurrentMerc->usValueGoneUp & STRENGTH_INCREASE ? TRUE : FALSE), (BOOLEAN)(((gGameOptions.fNewTraitSystem && (gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_STRENGTH] > 0)) || (gGameOptions.fFoodSystem && gpSMCurrentMerc->usStarveDamageStrength > 0)) ? TRUE : FALSE), gpSMCurrentMerc->bExtraStrength != 0 ); // SANDRO swprintf( sString, L"%2d", gpSMCurrentMerc->stats.bStrength + gpSMCurrentMerc->bExtraStrength ); FindFontRightCoordinates(SM_STR_X, SM_STR_Y ,SM_STATS_WIDTH ,SM_STATS_HEIGHT ,sString, BLOCKFONT2, &usX, &usY); @@ -2790,7 +2790,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) FindFontRightCoordinates(SM_CHAR_X, SM_CHAR_Y ,SM_STATS_WIDTH ,SM_STATS_HEIGHT ,sString, BLOCKFONT2, &usX, &usY); mprintf( usX, usY , sString ); - UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeWisdomTime,( BOOLEAN ) ( gpSMCurrentMerc->usValueGoneUp & WIS_INCREASE? TRUE: FALSE ), ( BOOLEAN ) ( ( gGameOptions.fNewTraitSystem && ( gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_WISDOM] > 0 )) ? TRUE : FALSE), MercUnderTheInfluence(gpSMCurrentMerc, DRUG_TYPE_WISDOM)); // SANDRO + UpdateStatColor( gpSMCurrentMerc->timeChanges.uiChangeWisdomTime, (BOOLEAN)(gpSMCurrentMerc->usValueGoneUp & WIS_INCREASE ? TRUE : FALSE), (BOOLEAN)((gGameOptions.fNewTraitSystem && (gpSMCurrentMerc->ubCriticalStatDamage[DAMAGED_STAT_WISDOM] > 0)) ? TRUE : FALSE), gpSMCurrentMerc->bExtraWisdom != 0 ); // SANDRO swprintf( sString, L"%2d", gpSMCurrentMerc->stats.bWisdom + gpSMCurrentMerc->bExtraWisdom ); FindFontRightCoordinates(SM_WIS_X, SM_WIS_Y ,SM_STATS_WIDTH ,SM_STATS_HEIGHT ,sString, BLOCKFONT2, &usX, &usY); @@ -3093,7 +3093,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) } else { - if ( MercUnderTheInfluence( gpSMCurrentMerc ) ) + if ( MercDruggedOrDrunk( gpSMCurrentMerc ) ) { SetFontBackground( FONT_MCOLOR_BLACK ); //SetFontForeground( FONT_MCOLOR_LTBLUE ); @@ -3316,50 +3316,12 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason ) // If we do not have an item in hand, start moving it if ( gpItemPointer ) { - BOOLEAN fGoodAPs = FALSE; - BOOLEAN fDoSound = FALSE; - // We are doing this ourselve, continue if ( gpSMCurrentMerc->stats.bLife >= CONSCIOUSNESS ) { - // Try to apply camo.... - if ( ApplyCammo( gpSMCurrentMerc, gpItemPointer, &fGoodAPs ) ) + if ( ApplyConsumable( gpSMCurrentMerc, gpItemPointer, FALSE, TRUE ) ) { - if ( fGoodAPs ) - { - fDoSound = TRUE; - // WANNE: We should only delete the face, if there was a camo we applied. - // This should fix the bug and crashes with missing faces - if (gGameExternalOptions.fShowCamouflageFaces ) - { - // Flugente: refresh face regardless of result of SetCamoFace(), otherwise applying a rag will not clean the picture - SetCamoFace( gpSMCurrentMerc ); - DeleteSoldierFace( gpSMCurrentMerc );// remove face - gpSMCurrentMerc->iFaceIndex = InitSoldierFace( gpSMCurrentMerc );// create new face - } - } - } - else if ( !gGameOptions.fFoodSystem && ApplyCanteen( gpSMCurrentMerc, gpItemPointer, &fGoodAPs, TRUE ) ) - { - ; - } - else if ( ApplyElixir( gpSMCurrentMerc, gpItemPointer, &fGoodAPs ) ) - { - fDoSound = TRUE; - } - else if ( ApplyDrugs( gpSMCurrentMerc, gpItemPointer ) ) - { - fGoodAPs = TRUE; - fDoSound = TRUE; - } - else if ( gGameOptions.fFoodSystem && ApplyFood( gpSMCurrentMerc, gpItemPointer, FALSE, FALSE ) ) - { - fGoodAPs = TRUE; - } - else if ( ApplyClothes( gpSMCurrentMerc, gpItemPointer ) ) - { - fGoodAPs = TRUE; } else { @@ -3375,18 +3337,6 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason ) gbCompatibleApplyItem = FALSE; EndItemPointer( ); } - - if ( fGoodAPs ) - { - // Dirty - fInterfacePanelDirty = DIRTYLEVEL2; - } - - if ( fDoSound ) - { - // Say OK acknowledge.... - gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 ); - } } } } @@ -5688,7 +5638,7 @@ void RenderTEAMPanel( BOOLEAN fDirty ) } else { - if ( MercUnderTheInfluence( pSoldier ) ) + if ( MercDruggedOrDrunk( pSoldier ) ) { SetFontBackground( FONT_MCOLOR_BLACK ); //SetFontForeground( FONT_MCOLOR_LTBLUE ); @@ -7085,7 +7035,7 @@ void CleanUpStack( OBJECTTYPE * pObj, OBJECTTYPE * pCursorObj ) { INT16 bMaxPoints; - if ( !(Item[ pObj->usItem ].usItemClass & IC_AMMO || Item[ pObj->usItem ].usItemClass & IC_KIT || Item[ pObj->usItem ].usItemClass & IC_MEDKIT || Item[pObj->usItem].canteen || Item[pObj->usItem].gascan || Item[pObj->usItem].alcohol ) ) + if ( !(Item[pObj->usItem].usItemClass & IC_AMMO || Item[pObj->usItem].usItemClass & IC_KIT || Item[pObj->usItem].usItemClass & IC_MEDKIT || Item[pObj->usItem].canteen || Item[pObj->usItem].gascan || Item[pObj->usItem].alcohol > 0.0f) ) { return; } diff --git a/Tactical/Interface.h b/Tactical/Interface.h index b72a5148..d495fd09 100644 --- a/Tactical/Interface.h +++ b/Tactical/Interface.h @@ -191,8 +191,9 @@ enum { BG_PERC_DISEASE_TREAT, BG_TRACKER_ABILITY, BG_AMBUSH_RADIUS, - + BG_DISLIKEBG, // dislike any other background that has the negative of this value set + BG_SMOKERTYPE, // 0: doesnt care about smoking 1: will consume cigarettes, dislikes non-smokers 2: will refuse to smoke, dislikes smokers BG_MAX, }; @@ -204,7 +205,7 @@ typedef struct CHAR16 szShortName[20]; // abbreviated name for laptop display CHAR16 szDescription[256]; // description of background, should explain the abilities - UINT64 uiFlags; // this flagmask defines what speial properties this background has (on/off behaviour) + UINT64 uiFlags; // this flagmask defines what special properties this background has (on/off behaviour) INT16 value[BG_MAX]; // property values } BACKGROUND_VALUES; diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 05376005..e1d71ea7 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -1047,7 +1047,7 @@ typedef struct BOOLEAN camouflagekit; BOOLEAN locksmithkit; BOOLEAN mine; - BOOLEAN alcohol; + FLOAT alcohol; BOOLEAN hardware; BOOLEAN medical; BOOLEAN gascan; @@ -1170,6 +1170,9 @@ typedef struct INT16 sBackpackWeightModifier; //modifier to weight calculation to climb. BOOLEAN fAllowClimbing; //does item allow climbing while wearing it + BOOLEAN cigarette; // Flugenete: this item can be smoked + UINT8 usPortionSize; // Flugente: for consumables: how much of this item is consumed at once + } INVTYPE; diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 93bad729..7debb463 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -1253,7 +1253,9 @@ std::map LBEPocketPopup; // { /* Knife Pocket */ 5, 0, 1, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } //}; -DRUGTYPE Drug[DRUG_TYPE_MAX]; +//DRUGTYPE Drug[DRUG_TYPE_MAX]; + +DRUG NewDrug[NEW_DRUGS_MAX]; FOODTYPE Food[FOOD_TYPE_MAX]; @@ -9363,57 +9365,37 @@ void WaterDamage( SOLDIERTYPE *pSoldier ) DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 ); } -BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs, BOOLEAN fUseAPs ) +BOOLEAN ApplyCamo( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16& usrPointsToUse ) { // Added - SANDRO - INT8 bPointsToUse; - UINT16 usTotalKitPoints; - UINT16 iRemainingCamoAfterRemoving; - - (*pfGoodAPs) = TRUE; - - if (pObj->exists() == false) - return( FALSE ); - + INT8 bPointsToUse; + UINT16 iRemainingCamoAfterRemoving; + ////////////////////////////////////////////////////////////////////////////// // added possibility to remove all camo by using a rag on self - SANDRO - if ( HasItemFlag(pObj->usItem, CAMO_REMOVAL) && gGameExternalOptions.fCamoRemoving) + if ( HasItemFlag( usItem, CAMO_REMOVAL ) && gGameExternalOptions.fCamoRemoving ) { - if ( fUseAPs && !EnoughPoints( pSoldier, (APBPConstants[AP_CAMOFLAGE]/2), 0, TRUE ) ) - { - (*pfGoodAPs) = FALSE; - return( TRUE ); - } // 100 should be enough. The third value "0" means we will remove all types of camo ReduceCamoFromSoldier( pSoldier, 100, 0 ); // damage the rag :) - actually you would need to flag it damagable in the items.XML - DamageItem( pObj, 22, FALSE ); - - if ( fUseAPs ) - DeductPoints( pSoldier, (APBPConstants[AP_CAMOFLAGE] / 2), 0 ); + usrPointsToUse = min( 22, usrPointsToUse ); // Reload palettes.... if ( pSoldier->bInSector ) { pSoldier->CreateSoldierPalettes( ); } + return( TRUE ); } - else if ( !Item[pObj->usItem].camouflagekit ) + else if ( !Item[usItem].camouflagekit ) { return( FALSE ); } ////////////////////////////////////////////////////////////////////////////// - - if ( fUseAPs && !EnoughPoints( pSoldier, APBPConstants[AP_CAMOFLAGE], 0, TRUE ) ) - { - (*pfGoodAPs) = FALSE; - return( TRUE ); - } - - usTotalKitPoints = TotalPoints( pObj ); - if (usTotalKitPoints == 0) + + if ( usrPointsToUse == 0 ) { // HUH??? return( FALSE ); @@ -9426,26 +9408,25 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP if (gGameExternalOptions.fCamoRemoving) { - int totalCamo = pSoldier->bCamo + pSoldier->urbanCamo + pSoldier->desertCamo + pSoldier->snowCamo; // First, check if we have an item with major JUNGLE camobonus - if ( (Item[pObj->usItem].camobonus > Item[pObj->usItem].urbanCamobonus) && - (Item[pObj->usItem].camobonus > Item[pObj->usItem].desertCamobonus) && - (Item[pObj->usItem].camobonus > Item[pObj->usItem].snowCamobonus) ) + if ( (Item[usItem].camobonus > Item[usItem].urbanCamobonus) && + (Item[usItem].camobonus > Item[usItem].desertCamobonus) && + (Item[usItem].camobonus > Item[usItem].snowCamobonus) ) { - if ( pSoldier->bCamo >= gGameExternalOptions.bCamoKitArea || Item[pObj->usItem].camobonus == 0 ) + if ( pSoldier->bCamo >= gGameExternalOptions.bCamoKitArea || Item[usItem].camobonus == 0 ) return( FALSE ); // determine how much we can add bPointsToUse = __max( 0, ( gGameExternalOptions.bCamoKitArea - pSoldier->bCamo ) ); // check how much of the kit we need for that - bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[pObj->usItem].camobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[usItem].camobonus / 100.0 ) ); // limit to what we have in the kit - bPointsToUse = __min( bPointsToUse, usTotalKitPoints ); + bPointsToUse = __min( bPointsToUse, usrPointsToUse ); // determine how much we will add - int iJungleCamoAdded = (int)(Item[pObj->usItem].camobonus * bPointsToUse / 100 ); + int iJungleCamoAdded = (int)(Item[usItem].camobonus * bPointsToUse / 100 ); // if we have already too much different camo on ourselves, reduce some or all if ( (totalCamo + iJungleCamoAdded) > gGameExternalOptions.bCamoKitArea ) @@ -9471,26 +9452,27 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP { pSoldier->bCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->bCamo + iJungleCamoAdded ); } + // update with amount that we really used - bPointsToUse = ( (FLOAT)iJungleCamoAdded / ( (FLOAT)Item[pObj->usItem].camobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)iJungleCamoAdded / ( (FLOAT)Item[usItem].camobonus / 100.0 ) ); } // Second, check if we have an item with major URBAN camobonus - else if ( (Item[pObj->usItem].urbanCamobonus > Item[pObj->usItem].camobonus) && - (Item[pObj->usItem].urbanCamobonus > Item[pObj->usItem].desertCamobonus) && - (Item[pObj->usItem].urbanCamobonus > Item[pObj->usItem].snowCamobonus) ) + else if ( (Item[usItem].urbanCamobonus > Item[usItem].camobonus) && + (Item[usItem].urbanCamobonus > Item[usItem].desertCamobonus) && + (Item[usItem].urbanCamobonus > Item[usItem].snowCamobonus) ) { - if ( pSoldier->urbanCamo >= gGameExternalOptions.bCamoKitArea || Item[pObj->usItem].urbanCamobonus == 0 ) + if ( pSoldier->urbanCamo >= gGameExternalOptions.bCamoKitArea || Item[usItem].urbanCamobonus == 0 ) return( FALSE ); // determine how much we can add bPointsToUse = __max( 0, ( gGameExternalOptions.bCamoKitArea - pSoldier->urbanCamo ) ); // check how much of the kit we need for that - bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[pObj->usItem].urbanCamobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[usItem].urbanCamobonus / 100.0 ) ); // limit to what we have in the kit - bPointsToUse = __min( bPointsToUse, usTotalKitPoints ); + bPointsToUse = __min( bPointsToUse, usrPointsToUse ); // determine how much we will add - int iUrbanCamoAdded = (int)(Item[pObj->usItem].urbanCamobonus * bPointsToUse / 100 ); + int iUrbanCamoAdded = (int)(Item[usItem].urbanCamobonus * bPointsToUse / 100 ); // if we have already too much different camo on ourselves, reduce some or all if ( (totalCamo + iUrbanCamoAdded) > gGameExternalOptions.bCamoKitArea ) @@ -9517,25 +9499,25 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP pSoldier->urbanCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->urbanCamo + iUrbanCamoAdded ); } // update with amount that we really used - bPointsToUse = ( (FLOAT)iUrbanCamoAdded / ( (FLOAT)Item[pObj->usItem].urbanCamobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)iUrbanCamoAdded / ( (FLOAT)Item[usItem].urbanCamobonus / 100.0 ) ); } // Third, check if we have an item with major DESERT camobonus - else if ( (Item[pObj->usItem].desertCamobonus > Item[pObj->usItem].camobonus) && - (Item[pObj->usItem].desertCamobonus > Item[pObj->usItem].urbanCamobonus) && - (Item[pObj->usItem].desertCamobonus > Item[pObj->usItem].snowCamobonus) ) + else if ( (Item[usItem].desertCamobonus > Item[usItem].camobonus) && + (Item[usItem].desertCamobonus > Item[usItem].urbanCamobonus) && + (Item[usItem].desertCamobonus > Item[usItem].snowCamobonus) ) { - if ( pSoldier->desertCamo >= gGameExternalOptions.bCamoKitArea || Item[pObj->usItem].desertCamobonus == 0 ) + if ( pSoldier->desertCamo >= gGameExternalOptions.bCamoKitArea || Item[usItem].desertCamobonus == 0 ) return( FALSE ); // determine how much we can add bPointsToUse = __max( 0, ( gGameExternalOptions.bCamoKitArea - pSoldier->desertCamo ) ); // check how much of the kit we need for that - bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[pObj->usItem].desertCamobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[usItem].desertCamobonus / 100.0 ) ); // limit to what we have in the kit - bPointsToUse = __min( bPointsToUse, usTotalKitPoints ); + bPointsToUse = __min( bPointsToUse, usrPointsToUse ); // determine how much we will add - int iDesertCamoAdded = (int)(Item[pObj->usItem].desertCamobonus * bPointsToUse / 100 ); + int iDesertCamoAdded = (int)(Item[usItem].desertCamobonus * bPointsToUse / 100 ); // if we have already too much different camo on ourselves, reduce some or all if ( (totalCamo + iDesertCamoAdded) > gGameExternalOptions.bCamoKitArea ) @@ -9562,25 +9544,25 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP pSoldier->desertCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->desertCamo + iDesertCamoAdded ); } // update with amount that we really used - bPointsToUse = ( (FLOAT)iDesertCamoAdded / ( (FLOAT)Item[pObj->usItem].desertCamobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)iDesertCamoAdded / ( (FLOAT)Item[usItem].desertCamobonus / 100.0 ) ); } // Fourth, check if we have an item with major SNOW camobonus - else if ( (Item[pObj->usItem].snowCamobonus > Item[pObj->usItem].camobonus) && - (Item[pObj->usItem].snowCamobonus > Item[pObj->usItem].urbanCamobonus) && - (Item[pObj->usItem].snowCamobonus > Item[pObj->usItem].desertCamobonus) ) + else if ( (Item[usItem].snowCamobonus > Item[usItem].camobonus) && + (Item[usItem].snowCamobonus > Item[usItem].urbanCamobonus) && + (Item[usItem].snowCamobonus > Item[usItem].desertCamobonus) ) { - if ( pSoldier->snowCamo >= gGameExternalOptions.bCamoKitArea || Item[pObj->usItem].snowCamobonus == 0 ) + if ( pSoldier->snowCamo >= gGameExternalOptions.bCamoKitArea || Item[usItem].snowCamobonus == 0 ) return( FALSE ); // determine how much we can add bPointsToUse = __max( 0, ( gGameExternalOptions.bCamoKitArea - pSoldier->snowCamo ) ); // check how much of the kit we need for that - bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[pObj->usItem].snowCamobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)bPointsToUse / ( (FLOAT)Item[usItem].snowCamobonus / 100.0 ) ); // limit to what we have in the kit - bPointsToUse = __min( bPointsToUse, usTotalKitPoints ); + bPointsToUse = __min( bPointsToUse, usrPointsToUse ); // determine how much we will add - int iSnowCamoAdded = (int)(Item[pObj->usItem].snowCamobonus * bPointsToUse / 100 ); + int iSnowCamoAdded = (int)(Item[usItem].snowCamobonus * bPointsToUse / 100 ); // if we have already too much different camo on ourselves, reduce some or all if ( (totalCamo + iSnowCamoAdded) > gGameExternalOptions.bCamoKitArea ) @@ -9607,7 +9589,7 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP pSoldier->snowCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->snowCamo + iSnowCamoAdded ); } // update with amount that we really used - bPointsToUse = ( (FLOAT)iSnowCamoAdded / ( (FLOAT)Item[pObj->usItem].snowCamobonus / 100.0 ) ); + bPointsToUse = ( (FLOAT)iSnowCamoAdded / ( (FLOAT)Item[usItem].snowCamobonus / 100.0 ) ); } else // the item has no major camo, return return( FALSE ); @@ -9627,13 +9609,13 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP } bPointsToUse = (gGameExternalOptions.bCamoKitArea - iKitCamo); - bPointsToUse = __min( bPointsToUse, usTotalKitPoints ); + bPointsToUse = __min( bPointsToUse, usrPointsToUse ); //figure out proportions of each to be applied, one item can theoretically have more than one camouflage type this way - int urban = (int)(Item[pObj->usItem].urbanCamobonus * bPointsToUse / 100 ); - int jungle = (int)(Item[pObj->usItem].camobonus * bPointsToUse / 100 ); - int desert = (int)(Item[pObj->usItem].desertCamobonus * bPointsToUse / 100 ); - int snow = (int)(Item[pObj->usItem].snowCamobonus * bPointsToUse / 100 ); + int urban = (int)(Item[usItem].urbanCamobonus * bPointsToUse / 100 ); + int jungle = (int)(Item[usItem].camobonus * bPointsToUse / 100 ); + int desert = (int)(Item[usItem].desertCamobonus * bPointsToUse / 100 ); + int snow = (int)(Item[usItem].snowCamobonus * bPointsToUse / 100 ); pSoldier->bCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->bCamo + jungle ); pSoldier->urbanCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->urbanCamo + urban ); @@ -9641,10 +9623,7 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP pSoldier->snowCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->snowCamo + snow ); } - UseKitPoints( pObj, bPointsToUse, pSoldier ); - - if ( fUseAPs ) - DeductPoints( pSoldier, APBPConstants[AP_CAMOFLAGE], 0 ); + usrPointsToUse = bPointsToUse; // Reload palettes.... if ( pSoldier->bInSector ) @@ -9655,8 +9634,62 @@ BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAP return( TRUE ); } +BOOLEAN ApplyCanteen( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16 usPointsToUse ) +{ + if ( !Item[usItem].canteen ) + { + return(FALSE); + } + + if ( usPointsToUse == 0 ) + { + // HUH??? + return(FALSE); + } + + if ( pSoldier->bTeam == gbPlayerNum ) + { + if ( gMercProfiles[pSoldier->ubProfile].bSex == MALE ) + { + PlayJA2Sample( DRINK_CANTEEN_MALE, RATE_11025, MIDVOLUME, 1, MIDDLEPAN ); + } + else + { + PlayJA2Sample( DRINK_CANTEEN_FEMALE, RATE_11025, MIDVOLUME, 1, MIDDLEPAN ); + } + } + + // CJC Feb 9. Canteens don't seem effective enough, so doubled return from them + DeductPoints( pSoldier, 0, (INT16)(2 * usPointsToUse * -(100 - pSoldier->bBreath)) ); + + return(TRUE); +} + +#define MAX_HUMAN_CREATURE_SMELL (NORMAL_HUMAN_SMELL_STRENGTH - 1) + +BOOLEAN ApplyElixir( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16& usrPointsToUse ) +{ + if ( usItem != JAR_ELIXIR ) + { + return(FALSE); + } + + if ( usrPointsToUse == 0 ) + { + // HUH??? + return(FALSE); + } + + INT16 sPointsToUse = (MAX_HUMAN_CREATURE_SMELL - pSoldier->aiData.bMonsterSmell) * 2; + usrPointsToUse = __min( sPointsToUse, usrPointsToUse ); + + pSoldier->aiData.bMonsterSmell += sPointsToUse / 2; + + return(TRUE); +} + // Flugente: apply clothes, and eventually disguise -BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fUseAPs ) +BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16 usPointsToUse ) { // this will only work with the new trait system if (!gGameOptions.fNewTraitSystem) @@ -9665,20 +9698,13 @@ BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fUseAPs return FALSE; } - if ( !pSoldier || pObj->exists() == false ) + if ( !pSoldier ) return( FALSE ); UINT8 skilllevel = NUM_SKILL_TRAITS( pSoldier, COVERT_NT ); - - INT16 apcost = (APBPConstants[AP_DISGUISE] * ( 100 - gSkillTraitValues.sCODisguiseAPReduction * skilllevel))/100; - if ( fUseAPs && !EnoughPoints( pSoldier, apcost, 0, TRUE ) ) - { - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NOT_ENOUGH_APS] ); - return( FALSE ); - } // determine clothes type - UINT32 clothestype = Item[pObj->usItem].clothestype; + UINT32 clothestype = Item[usItem].clothestype; // if not a clothes item, nothing to see here if ( clothestype == 0 || clothestype > CLOTHES_MAX ) @@ -9760,11 +9786,6 @@ BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fUseAPs SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal ); pSoldier->CreateSoldierPalettes(); - - UseKitPoints( pObj, 100, pSoldier ); - - if ( fUseAPs ) - DeductPoints( pSoldier, apcost, 0 ); } if ( pSoldier->usSoldierFlagMask & SOLDIER_NEW_VEST && pSoldier->usSoldierFlagMask & SOLDIER_NEW_PANTS ) @@ -9810,93 +9831,6 @@ BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fUseAPs return( TRUE ); } -BOOLEAN ApplyCanteen( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs, BOOLEAN fUseAPs ) -{ - INT16 sPointsToUse; - UINT16 usTotalKitPoints; - - (*pfGoodAPs) = TRUE; - - if (!Item[pObj->usItem].canteen || pObj->exists() == false) - { - return( FALSE ); - } - - usTotalKitPoints = TotalPoints( pObj ); - if (usTotalKitPoints == 0) - { - // HUH??? - return( FALSE ); - } - - if ( fUseAPs && !EnoughPoints( pSoldier, APBPConstants[AP_DRINK], 0, TRUE ) ) - { - (*pfGoodAPs) = FALSE; - return( TRUE ); - } - - if ( pSoldier->bTeam == gbPlayerNum ) - { - if ( gMercProfiles[ pSoldier->ubProfile ].bSex == MALE ) - { - PlayJA2Sample( DRINK_CANTEEN_MALE, RATE_11025, MIDVOLUME, 1, MIDDLEPAN ); - } - else - { - PlayJA2Sample( DRINK_CANTEEN_FEMALE, RATE_11025, MIDVOLUME, 1, MIDDLEPAN ); - } - } - - sPointsToUse = __min( 20, usTotalKitPoints ); - - // CJC Feb 9. Canteens don't seem effective enough, so doubled return from them - if ( fUseAPs ) - DeductPoints( pSoldier, APBPConstants[AP_DRINK], (INT16) (2 * sPointsToUse * -(100 - pSoldier->bBreath) ) ); - - UseKitPoints( pObj, sPointsToUse, pSoldier ); - - return( TRUE ); -} - -#define MAX_HUMAN_CREATURE_SMELL (NORMAL_HUMAN_SMELL_STRENGTH - 1) - -BOOLEAN ApplyElixir( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs ) -{ - INT16 sPointsToUse; - UINT16 usTotalKitPoints; - - (*pfGoodAPs) = TRUE; - - if (pObj->usItem != JAR_ELIXIR || pObj->exists() == false) - { - return( FALSE ); - } - - usTotalKitPoints = TotalPoints( pObj ); - if (usTotalKitPoints == 0) - { - // HUH??? - return( FALSE ); - } - - if (!EnoughPoints( pSoldier, APBPConstants[AP_CAMOFLAGE], 0, TRUE ) ) - { - (*pfGoodAPs) = FALSE; - return( TRUE ); - } - - DeductPoints( pSoldier, APBPConstants[AP_CAMOFLAGE], 0 ); - - sPointsToUse = ( MAX_HUMAN_CREATURE_SMELL - pSoldier->aiData.bMonsterSmell ) * 2; - sPointsToUse = __min( sPointsToUse, usTotalKitPoints ); - - UseKitPoints( pObj, sPointsToUse, pSoldier ); - - pSoldier->aiData.bMonsterSmell += sPointsToUse / 2; - - return( TRUE ); -} - UINT32 ConvertProfileMoneyValueToObjectTypeMoneyValue( UINT8 ubStatus ) { return( ubStatus * 50 ); @@ -11564,7 +11498,7 @@ INT16 GetTotalVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) bonus += GetDayVisionRangeBonus(pSoldier, bLightLevel); } - // Flugente: drugs can alter our sight + /*// Flugente: drugs can alter our sight if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_VISION ] ) { bonus += 10; @@ -11572,7 +11506,7 @@ INT16 GetTotalVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) else if ( pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_VISION ] ) { bonus -= 10; - } + }*/ // Flugente: add sight range bonus due to disabilities, traits etc. (not equipment) bonus += pSoldier->GetSightRangeBonus(); @@ -11713,11 +11647,11 @@ UINT8 GetPercentTunnelVision( SOLDIERTYPE * pSoldier ) } } - // Flugente: drugs can alter our vision + /*// Flugente: drugs can alter our vision if ( pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_TUNNELVISION ] ) { bonus = __min(100, bonus + 25); - } + } */ if ( !PTR_OURTEAM ) // Madd: adjust tunnel vision by difficulty level bonus /= gGameOptions.ubDifficultyLevel; diff --git a/Tactical/Items.h b/Tactical/Items.h index 95de03d8..48a07abb 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -196,8 +196,10 @@ void WaterDamage( SOLDIERTYPE *pSoldier ); INT8 FindObj( SOLDIERTYPE * pSoldier, UINT16 usItem, INT8 bLower = 0, INT8 bUpper = NUM_INV_SLOTS ); -BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs, BOOLEAN fUseAPs = TRUE ); -BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fUseAPs = TRUE ); // Flugente: apply clothes, and eventually disguise +BOOLEAN ApplyCamo( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16& usrPointsToUse ); +BOOLEAN ApplyCanteen( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16 usPointsToUse ); +BOOLEAN ApplyElixir( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16& usrPointsToUse ); +BOOLEAN ApplyClothes( SOLDIERTYPE * pSoldier, UINT16 usItem, UINT16 usPointsToUse ); // Flugente: apply clothes, and eventually disguise UINT32 ConvertProfileMoneyValueToObjectTypeMoneyValue( UINT8 ubStatus ); UINT8 ConvertObjectTypeMoneyValueToProfileMoneyValue( UINT32 uiMoneyAmount ); @@ -212,9 +214,6 @@ UINT16 FindReplacementMagazineIfNecessary( UINT16 usOldGun, UINT16 usOldAmmo, UI BOOLEAN DamageItemOnGround( OBJECTTYPE * pObject, INT32 sGridNo, INT8 bLevel, INT32 iDamage, UINT8 ubOwner ); -BOOLEAN ApplyCanteen( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs, BOOLEAN fUseAPs = TRUE ); -BOOLEAN ApplyElixir( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs ); - BOOLEAN CompatibleFaceItem( UINT16 usItem1, UINT16 usItem2 ); UINT32 MoneySlotLimit( INT8 bSlot ); diff --git a/Tactical/Morale.cpp b/Tactical/Morale.cpp index f0ceb78f..bb3cc45f 100644 --- a/Tactical/Morale.cpp +++ b/Tactical/Morale.cpp @@ -165,23 +165,23 @@ BOOLEAN IsShowOffNearBy( SOLDIERTYPE * pSoldier ); // Added by SANDRO INT8 GetMoraleModifier( SOLDIERTYPE * pSoldier ) { + INT8 morale = 0; + if (pSoldier->flags.uiStatusFlags & SOLDIER_PC) { if (pSoldier->aiData.bMorale > 50) { // give +1 at 55, +3 at 65, up to +5 at 95 and above - return( (pSoldier->aiData.bMorale - 45) / 10 ); + morale = (pSoldier->aiData.bMorale - 45) / 10; } else { // give penalties down to -20 at 0 (-2 at 45, -4 by 40...) - return( (pSoldier->aiData.bMorale - 50) * 2 / 5 ); + morale = (pSoldier->aiData.bMorale - 50) * 2 / 5; } } else { - INT8 morale = 0; - // use AI morale switch( pSoldier->aiData.bAIMorale ) { @@ -196,12 +196,12 @@ INT8 GetMoraleModifier( SOLDIERTYPE * pSoldier ) default: morale = 0; } - - // Flugente: morale modifiers - morale = max(morale, morale * pSoldier->GetMoraleModifier()); - - return morale; } + + // Flugente: morale modifiers + morale = max( morale, morale * pSoldier->GetMoraleModifier( ) ); + + return morale; } void DecayTacticalMorale( SOLDIERTYPE * pSoldier ) @@ -259,19 +259,8 @@ void DecayTacticalMoraleModifiers( void ) { continue; } - - // Flugente: drugs can temporarily cause a merc get a new disability - // therefore we change this routine - BOOLEAN isClaustrophobic = gMercProfiles[ pSoldier->ubProfile ].bDisability == CLAUSTROPHOBIC ? TRUE : FALSE; - BOOLEAN isNervous = gMercProfiles[ pSoldier->ubProfile ].bDisability == NERVOUS ? TRUE : FALSE; - - if ( MercUnderTheInfluence(pSoldier, DRUG_TYPE_CLAUSTROPHOBIC) ) - isClaustrophobic = TRUE; - - if ( MercUnderTheInfluence(pSoldier, DRUG_TYPE_NERVOUS) ) - isNervous = TRUE; - - if ( isClaustrophobic ) + + if ( DoesMercHaveDisability( pSoldier, CLAUSTROPHOBIC ) ) { if ( pSoldier->bSectorZ > 0 ) { @@ -283,7 +272,7 @@ void DecayTacticalMoraleModifiers( void ) } } - if ( isNervous ) + if ( DoesMercHaveDisability( pSoldier, NERVOUS ) ) { if ( pSoldier->aiData.bMorale < 50 ) { @@ -396,9 +385,8 @@ void RefreshSoldierMorale( SOLDIERTYPE * pSoldier ) //iActualMorale = DEFAULT_MORALE + (INT32) pSoldier->aiData.bTeamMoraleMod + (INT32) pSoldier->aiData.bTacticalMoraleMod + (INT32) pSoldier->aiData.bStrategicMoraleMod + (INT32) (CurrentPlayerProgressPercentage() / 5); iActualMorale = gMoraleSettings.ubDefaultMorale + (INT32) pSoldier->aiData.bTeamMoraleMod + (INT32) pSoldier->aiData.bTacticalMoraleMod + (INT32) pSoldier->aiData.bStrategicMoraleMod + (INT32) (CurrentPlayerProgressPercentage() / 5); - // ATE: Modify morale based on drugs.... - iActualMorale += ( ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] * gMoraleSettings.sDrugAndAlcoholModifiers[DRUG_EFFECT_MORALE_MOD] ) / 100 ); - iActualMorale += ( ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ALCOHOL ] * gMoraleSettings.sDrugAndAlcoholModifiers[ALCOHOL_EFFECT_MORALE_MOD] ) / 100 ); + // Flugente: drug system has been redone + iActualMorale += pSoldier->newdrugs.size[DRUG_EFFECT_MORALE]; iActualMorale = __min( 100, iActualMorale ); iActualMorale = __max( 0, iActualMorale ); @@ -593,13 +581,14 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent ) break; } } + // Check for character traits - if ( pProfile->bCharacterTrait == CHAR_TRAIT_OPTIMIST ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_OPTIMIST ) ) { bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OPTIMIST];//1; } // Fearless character does not suffer morale loss for these so much - else if( pProfile->bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_DAUNTLESS ) ) { switch ( bMoraleEvent ) { @@ -774,7 +763,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I HandleMoraleEventForSoldier( pTeamSoldier, MORALE_BATTLE_WON ); } // SANDRO - Assertive people don't care about actions of others - else if ( !gGameOptions.fNewTraitSystem || gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait != CHAR_TRAIT_ASSERTIVE ) + else if ( !gGameOptions.fNewTraitSystem || !DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_ASSERTIVE ) ) { HandleMoraleEventForSoldier( pTeamSoldier, MORALE_HEARD_BATTLE_WON ); } @@ -799,10 +788,11 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I if ( !HAS_SKILL_TRAIT( pTeamSoldier, COVERT_NT ) || ( (pTeamSoldier->usSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) == 0) ) { // SANDRO - no penalty for pacifists to run away - if ( gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait != CHAR_TRAIT_PACIFIST ) + if ( DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_PACIFIST ) ) HandleMoraleEventForSoldier( pTeamSoldier, MORALE_RAN_AWAY ); + // Double morale drop for aggressive people - if ( gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + if ( DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_AGGRESSIVE ) ) HandleMoraleEventForSoldier( pTeamSoldier, MORALE_RAN_AWAY ); } } @@ -825,7 +815,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I } } // SANDRO - Assertive people don't care about actions of others - else if ( !gGameOptions.fNewTraitSystem || gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait != CHAR_TRAIT_ASSERTIVE ) + else if ( !gGameOptions.fNewTraitSystem || !DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_ASSERTIVE ) ) { HandleMoraleEventForSoldier( pTeamSoldier, MORALE_HEARD_BATTLE_LOST ); } @@ -854,7 +844,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I if ( gGameOptions.fNewTraitSystem && bMoraleEvent != MORALE_DEIDRANNA_KILLED) { if ( !SOLDIER_IN_SECTOR( pTeamSoldier, sMapX, sMapY, bMapZ ) && ( gMoraleSettings.bValues[bMoraleEvent] > 0 ) && //( gbMoraleEvent[bMoraleEvent].bChange > 0 ) && - gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE ) + DoesMercHavePersonality( pTeamSoldier, CHAR_TRAIT_ASSERTIVE ) ) { // No morale gain for assertive people from actions of others } @@ -1270,11 +1260,13 @@ void HourlyMoraleUpdate( void ) { bTeamMoraleModChange = 0; } + // SANDRO - morale is going down faster if not fighting for malicious characters - if ( gGameOptions.fNewTraitSystem && pProfile->bCharacterTrait == CHAR_TRAIT_MALICIOUS ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_MALICIOUS ) ) { bTeamMoraleModChange += gMoraleSettings.bModifiers[MORALE_MODIFIER_MALICIOUS_HOURLY_DECAY];//-= 1; } + pSoldier->aiData.bTeamMoraleMod += bTeamMoraleModChange; pSoldier->aiData.bTeamMoraleMod = __min( pSoldier->aiData.bTeamMoraleMod, gMoraleSettings.bModifiers[MORALE_MOD_MAX] ); pSoldier->aiData.bTeamMoraleMod = __max( pSoldier->aiData.bTeamMoraleMod, -gMoraleSettings.bModifiers[MORALE_MOD_MAX] ); @@ -1567,18 +1559,22 @@ void RememberSnitchableEvent( UINT8 ubTargetProfile, UINT8 ubSecondaryTargetProf SoldierRelation( pSoldier, pSnitch )*gSkillTraitValues.fSNTMercOpinionAboutSnitchBonusModifier + SoldierRelation( pSnitch, pSoldier )*gSkillTraitValues.fSNTSnitchOpinionAboutMercBonusModifier + gMercProfiles[ubSnitchProfile].bLeadership*gSkillTraitValues.fSNTSnitchLeadershipBonusModifer); + if ( pSoldier->bAssignment == pSnitch->bAssignment ) { sSnitchingChance += gSkillTraitValues.bSNTSameAssignmentBonus; } - if ( gMercProfiles[pSnitch->ubProfile].bCharacterTrait == CHAR_TRAIT_SOCIABLE ) + + if ( DoesMercHavePersonality( pSnitch, CHAR_TRAIT_SOCIABLE ) ) { sSnitchingChance += gSkillTraitValues.bSNTSociableMercBonus; } - if ( gMercProfiles[pSnitch->ubProfile].bCharacterTrait == CHAR_TRAIT_LONER ) + + if ( DoesMercHavePersonality( pSnitch, CHAR_TRAIT_LONER ) ) { sSnitchingChance += gSkillTraitValues.bSNTLonerMercBonus; } + if ( ubEventType == SNITCH_HATED_PERSON ) { if ( gSkillTraitValues.bSNTMercOpinionAboutMercTreshold != HATED_OPINION ) @@ -1588,7 +1584,7 @@ void RememberSnitchableEvent( UINT8 ubTargetProfile, UINT8 ubSecondaryTargetProf (FLOAT)(gSkillTraitValues.bSNTMercOpinionAboutMercTreshold - HATED_OPINION))); } } - if ( gMercProfiles[pSnitch->ubProfile].bDisability == DEAF ) + if ( DoesMercHaveDisability( pSnitch, DEAF ) ) { sSnitchingChance /= 2; } @@ -1686,13 +1682,13 @@ BOOLEAN IsShowOffNearBy( SOLDIERTYPE * pSoldier ) } // Are we from our team an dalive? if ( pTeammate->bTeam == pSoldier->bTeam && pTeammate->stats.bLife >= OKLIFE && - gMercProfiles[ pTeammate->ubProfile ].bCharacterTrait == CHAR_TRAIT_SHOWOFF && PythSpacesAway( pSoldier->sGridNo, pTeammate->sGridNo ) <= 15) + DoesMercHavePersonality( pTeammate, CHAR_TRAIT_SHOWOFF ) && PythSpacesAway( pSoldier->sGridNo, pTeammate->sGridNo ) <= 15 ) { if ( (pSoldier->ubBodyType <= STOCKYMALE && pTeammate->ubBodyType <= STOCKYMALE) || (pSoldier->ubBodyType == REGFEMALE && pTeammate->ubBodyType == REGFEMALE) ) { // phlegmatic character can ignore one - if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC && !fOneException) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PHLEGMATIC ) && !fOneException ) { fOneException = TRUE; } diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index e5111850..9a594bd2 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -2463,7 +2463,7 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE else // ATE; First check for profile // Forgetful guy might forget his path - if ( (pSoldier->bTeam == gbPlayerNum) && ( pSoldier->ubProfile != NO_PROFILE ) && gMercProfiles[pSoldier->ubProfile].bDisability == FORGETFUL ) + if ( (pSoldier->bTeam == gbPlayerNum) && DoesMercHaveDisability( pSoldier, FORGETFUL ) ) { if ( pSoldier->ubNumTilesMovesSinceLastForget < 255 ) { @@ -3233,33 +3233,17 @@ void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fF // possibly say personality quote if ( (pSoldier->bTeam == gbPlayerNum) && (pSoldier->ubProfile != NO_PROFILE && pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__PLAYER_CHARACTER) && !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_PERSONALITY) ) { - switch ( gMercProfiles[ pSoldier->ubProfile ].bDisability ) - { - case PSYCHO: - if ( Random( 50 ) == 0 ) - { - TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY; + if ( DoesMercHaveDisability( pSoldier, PSYCHO ) ) + { + if ( Random( 50 ) == 0 ) + { + TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); + pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY; - // Flugente: dynamic opinions - HandleDynamicOpinionChange( pSoldier, OPINIONEVENT_ANNOYINGDISABILITY, TRUE, TRUE ); - } - break; - default: - // Flugente: drugs can temporarily cause a merc to go psycho - if ( MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) - { - if ( Random( 50 ) == 0 ) - { - TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT ); - pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY; - - // Flugente: dynamic opinions - HandleDynamicOpinionChange( pSoldier, OPINIONEVENT_ANNOYINGDISABILITY, TRUE, TRUE ); - } - } - break; - } + // Flugente: dynamic opinions + HandleDynamicOpinionChange( pSoldier, OPINIONEVENT_ANNOYINGDISABILITY, TRUE, TRUE ); + } + } } UpdateForContOverPortrait( pSoldier, TRUE ); @@ -8230,9 +8214,9 @@ INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier ) // SANDRO - check for character traits if ( gGameOptions.fNewTraitSystem ) { - if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_INTELLECTUAL ) ) bTolerance += -2; - else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_DAUNTLESS ) ) bTolerance += 2; } else @@ -10897,12 +10881,13 @@ INT8 CalcEffectiveShockLevel( SOLDIERTYPE * pSoldier ) { bShockForCower = (INT8)((bShockForCower * (100 - gSkillTraitValues.ubSLFearResistance * NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT )) /100) + 0.5); } + // Check for character traits - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_INTELLECTUAL ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_INTELLECTUAL ) ) { bShockForCower = (INT8)((bShockForCower * 23 / 20 ) + 0.5); // +15% as shock } - else if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_DAUNTLESS ) ) { bShockForCower = (INT8)((bShockForCower * 17 / 20 ) + 0.5); // -15% as shock } @@ -10910,6 +10895,7 @@ INT8 CalcEffectiveShockLevel( SOLDIERTYPE * pSoldier ) // Flugente: personal fear resistance bShockForCower = (INT8)((bShockForCower * (100 - pSoldier->GetFearResistanceBonus()) / 100 ) + 0.5); } + return bShockForCower; } diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index 4c21901e..ec131aa5 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -1185,14 +1185,15 @@ INT32 AdjustBreathPts( SOLDIERTYPE * pSoldier , INT32 iBPCost ) { sBreathFactor += 100; } + // SANDRO - Less breath consumption for Primitive chars - if ( gGameOptions.fNewTraitSystem && gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_PRIMITIVE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PRIMITIVE ) ) { sBreathFactor -= 15; // -15% breath consumption } - // if a non-swimmer type is thrashing around in deep water - if ( (pSoldier->ubProfile != NO_PROFILE ) && (gMercProfiles[ pSoldier->ubProfile ].bDisability == NONSWIMMER) ) + // if a non-swimmer type is thrashing around in deep water + if ( DoesMercHaveDisability( pSoldier, NONSWIMMER ) ) { if ( pSoldier->usAnimState == DEEP_WATER_TRED || pSoldier->usAnimState == DEEP_WATER_SWIM) { @@ -1258,11 +1259,12 @@ void UnusedAPsToBreath( SOLDIERTYPE * pSoldier ) // Adjust for on drugs HandleBPEffectDueToDrugs( pSoldier, &sBreathChange ); - if ( sBreathChange > 0 ) + // Flugente: why would we forbid losing breath in realtime? + /*if ( sBreathChange > 0 ) { sBreathChange = 0; - } - else + }*/ + if ( sBreathChange < 0 ) { // We have a gain, now limit this depending on what we were doing... // OK for RT, look at how many tiles we have moved, our last move anim diff --git a/Tactical/SkillCheck.cpp b/Tactical/SkillCheck.cpp index 61bcce04..ebd8d3bd 100644 --- a/Tactical/SkillCheck.cpp +++ b/Tactical/SkillCheck.cpp @@ -199,12 +199,12 @@ INT8 EffectiveExpLevel( SOLDIERTYPE * pSoldier ) if (pSoldier->ubProfile != NO_PROFILE) { // Flugente: drugs can temporarily cause a merc to be claustrophobic - if ( ( (gMercProfiles[ pSoldier->ubProfile ].bDisability == CLAUSTROPHOBIC) || MercUnderTheInfluence(pSoldier, DRUG_TYPE_CLAUSTROPHOBIC) ) && pSoldier->bActive && pSoldier->bInSector && gbWorldSectorZ > 0) + if ( DoesMercHaveDisability( pSoldier, CLAUSTROPHOBIC ) && pSoldier->bActive && pSoldier->bInSector && gbWorldSectorZ > 0 ) { // claustrophobic! iEffExpLevel -= 2; } - else if ( ( (gMercProfiles[ pSoldier->ubProfile ].bDisability == FEAR_OF_INSECTS) || MercUnderTheInfluence(pSoldier, DRUG_TYPE_FEAROFINSECTS) )&& MercIsInTropicalSector( pSoldier ) ) + else if ( DoesMercHaveDisability( pSoldier, FEAR_OF_INSECTS ) && MercIsInTropicalSector( pSoldier ) ) { // SANDRO - fear of insects, and we are in tropical sector iEffExpLevel -= 1; @@ -674,7 +674,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod ) iChance -= 15; } // also added a small penalty for fear of insects in tropical sectors - else if ( ( (gMercProfiles[ pSoldier->ubProfile ].bDisability == FEAR_OF_INSECTS) || MercUnderTheInfluence(pSoldier, DRUG_TYPE_FEAROFINSECTS) ) && MercIsInTropicalSector( pSoldier )) + else if ( DoesMercHaveDisability( pSoldier, FEAR_OF_INSECTS ) && MercIsInTropicalSector( pSoldier ) ) { // fear of insects, and we are in tropical sector iChance -= 5; @@ -682,7 +682,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod ) // character traits influence // Sociable - better performance in groups - if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_SOCIABLE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_SOCIABLE ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pSoldier->ubProfile, CHAR_TRAIT_SOCIABLE ); if ( bNumMercs > 2 ) @@ -691,7 +691,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod ) iChance += 2; } // Loner - better performance when alone - else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_LONER ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_LONER ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pSoldier->ubProfile, CHAR_TRAIT_LONER ); if ( bNumMercs == 0 ) @@ -700,7 +700,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod ) iChance += 2; } // Aggressive - penalty for actions needing patience - else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_AGGRESSIVE ) ) { switch ( bReason ) { @@ -717,7 +717,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod ) } } // Phlegmatic - bonus for actions needing patience - else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PHLEGMATIC ) ) { switch ( bReason ) { @@ -734,7 +734,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod ) } } // Show-off - better performance if some babes around to impress - else if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_SHOWOFF ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_SHOWOFF ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pSoldier->ubProfile, CHAR_TRAIT_SHOWOFF ); if ( bNumMercs > 1 ) @@ -934,7 +934,7 @@ INT16 CalcTrapDetectLevel( SOLDIERTYPE * pSoldier, BOOLEAN fExamining ) bDetectLevel += (INT8) PreRandom(bDetectLevel / 3 + 2); } // SANDRO - optimists just don't even think about the traps, randomly ignoring this all - else if ( gGameOptions.fNewTraitSystem && gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_OPTIMIST ) + else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_OPTIMIST ) ) { if ( Chance(50) ) bDetectLevel = 1; diff --git a/Tactical/Soldier Add.cpp b/Tactical/Soldier Add.cpp index e9dc3014..0424386c 100644 --- a/Tactical/Soldier Add.cpp +++ b/Tactical/Soldier Add.cpp @@ -1875,16 +1875,12 @@ BOOLEAN IsMercOnTeamAndInOmertaAlreadyAndAlive(UINT8 ubMercID) // GetSoldierIDFromMercID() Gets the Soldier ID from the Merc Profile ID, else returns -1 INT16 GetSoldierIDFromMercID(UINT8 ubMercID) { - UINT16 cnt; - UINT8 ubLastTeamID; - SOLDIERTYPE *pTeamSoldier; + SOLDIERTYPE *pTeamSoldier = NULL; - cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; - - ubLastTeamID = gTacticalStatus.Team[ OUR_TEAM ].bLastID; + UINT16 cnt = gTacticalStatus.Team[OUR_TEAM].bFirstID; // look for all mercs on the same team, - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= ubLastTeamID; ++cnt, pTeamSoldier++) + for ( pTeamSoldier = MercPtrs[cnt]; cnt <= gTacticalStatus.Team[OUR_TEAM].bLastID; ++cnt, ++pTeamSoldier ) { if ( pTeamSoldier->ubProfile == ubMercID ) { @@ -1893,7 +1889,7 @@ INT16 GetSoldierIDFromMercID(UINT8 ubMercID) } } - return( -1 ); + return -1 ; } diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index d338d662..a30de04b 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -1829,7 +1829,7 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier ) // enemy on sight, don't pretend we don't see him! if ( pSoldier->ubProfile != NO_PROFILE ) { - if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait != CHAR_TRAIT_SHOWOFF && Random( 10 ) < 9 ) + if ( Random( 10 ) < 9 && !DoesMercHavePersonality( pSoldier, CHAR_TRAIT_SHOWOFF ) ) { continue; } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 2ff220c3..65fd7f34 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -636,7 +636,7 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src) flags.ConvertFrom_101_To_102( src ); timeChanges.ConvertFrom_101_To_102( src ); timeCounters.ConvertFrom_101_To_102( src ); - drugs.ConvertFrom_101_To_102( src ); + //drugs.ConvertFrom_101_To_102( src ); stats.ConvertFrom_101_To_102( src ); pathing.ConvertFrom_101_To_102( src ); inv = src.inv; @@ -1105,7 +1105,8 @@ void SOLDIERTYPE::initialize( ) memset( &flags, 0, sizeof(STRUCT_Flags) ); memset( &timeChanges, 0, sizeof(STRUCT_TimeChanges) ); memset( &timeCounters, 0, sizeof(STRUCT_TimeCounters) ); - memset( &drugs, 0, sizeof(STRUCT_Drugs) ); + //memset( &drugs, 0, sizeof(STRUCT_Drugs) ); + memset( &newdrugs, 0, sizeof(DRUGS) ); memset( &stats, 0, sizeof(STRUCT_Statistics) ); memset( &pathing, 0, sizeof(STRUCT_Pathing) ); } @@ -2033,23 +2034,23 @@ INT16 SOLDIERTYPE::CalcActionPoints( void ) if ( this->ubProfile != NO_PROFILE ) { // Flugente: drugs can temporarily cause a merc to be claustrophobic - if ( ((gMercProfiles[this->ubProfile].bDisability == CLAUSTROPHOBIC) || MercUnderTheInfluence( this, DRUG_TYPE_CLAUSTROPHOBIC )) && (gbWorldSectorZ > 0) ) + if ( DoesMercHaveDisability( this, CLAUSTROPHOBIC ) && gbWorldSectorZ > 0 ) { ubPoints = (ubPoints * APBPConstants[AP_CLAUSTROPHOBE]) / 10; } - else if ( ((gMercProfiles[this->ubProfile].bDisability == FEAR_OF_INSECTS) || MercUnderTheInfluence( this, DRUG_TYPE_FEAROFINSECTS )) && (MercSeesCreature( this )) ) + else if ( DoesMercHaveDisability( this, FEAR_OF_INSECTS ) && MercSeesCreature( this ) ) { ubPoints = (ubPoints * APBPConstants[AP_AFRAID_OF_INSECTS]) / 10; } - else if ( ((gMercProfiles[this->ubProfile].bDisability == FEAR_OF_INSECTS) || MercUnderTheInfluence( this, DRUG_TYPE_FEAROFINSECTS )) && (MercIsInTropicalSector( this )) ) + else if ( DoesMercHaveDisability( this, HEAT_INTOLERANT ) && MercIsInTropicalSector( this ) ) { ubPoints = (ubPoints * 9) / 10; } } - // Adjusat APs due to drugs... + // Adjust APs due to drugs... HandleAPEffectDueToDrugs( this, &ubPoints ); - + //Madd // if ( this->bTeam != CIV_TEAM && this->bTeam != gbPlayerNum && gGameOptions.ubDifficultyLevel == DIF_LEVEL_INSANE ) // ubPoints += 5; // everything and everyone moves a little faster against you on insane... @@ -2153,7 +2154,7 @@ void SOLDIERTYPE::CalcNewActionPoints( void ) this->bActionPoints = APBPConstants[AP_MIN_LIMIT]; // Don't max out if we are drugged.... - if ( !MercUnderTheInfluence( this, DRUG_TYPE_ADRENALINE ) && !MercUnderTheInfluence( this, DRUG_TYPE_AGILITY ) ) + if ( !this->newdrugs.size[DRUG_EFFECT_AP] && !this->newdrugs.size[DRUG_EFFECT_AGI] ) { /////////////////////////////////////////////////////////////////////////////////////////// // SANDRO - following code messed a bit @@ -7600,7 +7601,7 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou // ATE: Add decay effect sfor drugs... //if ( fFromRealTime ) //&& iRealTimeCounter % 300 ) { - HandleEndTurnDrugAdjustments( this ); + HandleEndTurnDrugAdjustments_New( this ); } // ATE: Don't bleed if in AUTO BANDAGE! @@ -7760,26 +7761,7 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou if ( (this->bTeam == gbPlayerNum) && (this->ubProfile != NO_PROFILE) ) { - // Flugente: drugs can temporarily cause a merc get a new disability - // therefore we change this routine - BOOLEAN isHeatIntolerant = gMercProfiles[this->ubProfile].bDisability == HEAT_INTOLERANT ? TRUE : FALSE; - BOOLEAN isFearOfInsects = gMercProfiles[this->ubProfile].bDisability == FEAR_OF_INSECTS ? TRUE : FALSE; - BOOLEAN isClaustrophobic = gMercProfiles[this->ubProfile].bDisability == CLAUSTROPHOBIC ? TRUE : FALSE; - BOOLEAN isNervous = gMercProfiles[this->ubProfile].bDisability == NERVOUS ? TRUE : FALSE; - - if ( MercUnderTheInfluence( this, DRUG_TYPE_HEATINTOLERANT ) ) - isHeatIntolerant = TRUE; - - if ( MercUnderTheInfluence( this, DRUG_TYPE_FEAROFINSECTS ) ) - isFearOfInsects = TRUE; - - if ( MercUnderTheInfluence( this, DRUG_TYPE_CLAUSTROPHOBIC ) ) - isClaustrophobic = TRUE; - - if ( MercUnderTheInfluence( this, DRUG_TYPE_NERVOUS ) ) - isNervous = TRUE; - - if ( isHeatIntolerant ) + if ( DoesMercHaveDisability( this, HEAT_INTOLERANT ) ) { if ( MercIsHot( this ) ) { @@ -7795,7 +7777,7 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou } } - if ( isFearOfInsects ) + if ( DoesMercHaveDisability( this, FEAR_OF_INSECTS ) ) { if ( MercSeesCreature( this ) ) { @@ -7811,7 +7793,7 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou } } - if ( isClaustrophobic ) + if ( DoesMercHaveDisability( this, CLAUSTROPHOBIC ) ) { if ( gbWorldSectorZ > 0 && Random( 6 - gbWorldSectorZ ) == 0 ) { @@ -7828,7 +7810,7 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou } } - if ( isNervous ) + if ( DoesMercHaveDisability( this, NERVOUS ) ) { if ( DistanceToClosestFriend( this ) > NERVOUS_RADIUS ) { @@ -8857,7 +8839,7 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier // If a moving animation and w/re on drugs, increase speed.... if ( gAnimControl[pSoldier->usAnimState].uiFlags & ANIM_MOVING ) { - if ( MercUnderTheInfluence( pSoldier, DRUG_TYPE_ADRENALINE ) ) + if ( pSoldier->newdrugs.size[DRUG_EFFECT_AP] ) { pSoldier->sAniDelay = pSoldier->sAniDelay / 2; } @@ -12070,8 +12052,10 @@ void SOLDIERTYPE::EVENT_SoldierBeginBladeAttack( INT32 sGridNo, UINT8 ubDirectio if ( ubTargetID != NOBODY && ((MercPtrs[ubTargetID]->stats.bLife < OKLIFE && MercPtrs[ubTargetID]->stats.bLife > 0) || (MercPtrs[ubTargetID]->bBreath < OKBREATH && MercPtrs[ubTargetID]->bCollapsed)) ) { this->aiData.uiPendingActionData4 = ubTargetID; + // add regen bonus - this->bRegenerationCounter++; + this->newdrugs.size[DRUG_EFFECT_HP] += 10; + this->EVENT_InitNewSoldierAnim( MONSTER_BEGIN_EATTING_FLESH, 0, FALSE ); } else @@ -12547,7 +12531,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginKnifeThrowAttack( INT32 sGridNo, UINT8 ubDir DebugAttackBusy( String( "Begin knife throwing attack: ATB %d\n", gTacticalStatus.ubAttackBusyCount ) ); // SANDRO - new animation for throwing for big mercs by PasHancock - if ( this->ubBodyType == BIGMALE && ((this->ubProfile != NO_PROFILE && gMercProfiles[this->ubProfile].bCharacterTrait == CHAR_TRAIT_SHOWOFF) || (HAS_SKILL_TRAIT( this, THROWING_NT ) && gGameOptions.fNewTraitSystem) || (HAS_SKILL_TRAIT( this, THROWING_OT ) && !gGameOptions.fNewTraitSystem)) ) + if ( this->ubBodyType == BIGMALE && (DoesMercHavePersonality( this, CHAR_TRAIT_SHOWOFF ) || (HAS_SKILL_TRAIT( this, THROWING_NT ) && gGameOptions.fNewTraitSystem) || (HAS_SKILL_TRAIT( this, THROWING_OT ) && !gGameOptions.fNewTraitSystem))) { this->EVENT_InitNewSoldierAnim( THROW_KNIFE_SP_BM, 0, FALSE ); } @@ -14568,7 +14552,7 @@ INT32 SOLDIERTYPE::GetDamageResistance( BOOLEAN fAutoResolve, BOOLEAN fCalcBreat //////////////////////////////////////////////////////////////////////////////////// // Flugente: drugs can now have an effect on damage resistance - HandleDamageResistanceEffectDueToDrugs( this, &resistance ); + resistance += this->newdrugs.size[DRUG_EFFECT_PHYS_RES]; resistance += this->GetBackgroundValue( BG_RESI_PHYSICAL ); @@ -14590,7 +14574,7 @@ INT8 SOLDIERTYPE::GetHearingBonus( ) bonus += GetHearingRangeBonus( this ); // pSoldier->inv[bSlot][0]->data.objectStatus / 20 + 1; } - if ( gMercProfiles[this->ubProfile].bDisability == DEAF ) + if ( DoesMercHaveDisability( this, DEAF ) ) bonus -= 5; if ( NightTime( ) ) @@ -14608,7 +14592,7 @@ INT16 SOLDIERTYPE::GetSightRangeBonus( ) { INT16 bonus = 0; - if ( gMercProfiles[this->ubProfile].bDisability == SHORTSIGHTED ) + if ( DoesMercHaveDisability( this, SHORTSIGHTED ) ) bonus -= 10; return bonus; @@ -16795,7 +16779,7 @@ INT8 SOLDIERTYPE::GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubT if ( this->ubProfile != NO_PROFILE ) { // Sociable - better performance in groups - if ( gMercProfiles[this->ubProfile].bCharacterTrait == CHAR_TRAIT_SOCIABLE ) + if ( DoesMercHavePersonality( this, CHAR_TRAIT_SOCIABLE ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( this->ubProfile, CHAR_TRAIT_SOCIABLE ); if ( bNumMercs > 2 ) @@ -16804,7 +16788,7 @@ INT8 SOLDIERTYPE::GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubT modifier += 2; } // Loner - better performance when alone - else if ( gMercProfiles[this->ubProfile].bCharacterTrait == CHAR_TRAIT_LONER ) + else if ( DoesMercHavePersonality( this, CHAR_TRAIT_LONER ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( this->ubProfile, CHAR_TRAIT_LONER ); if ( bNumMercs == 0 ) @@ -16813,13 +16797,13 @@ INT8 SOLDIERTYPE::GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubT modifier += 2; } // Aggressive - bonus on bursts/autofire - else if ( gMercProfiles[this->ubProfile].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + else if ( DoesMercHavePersonality( this, CHAR_TRAIT_AGGRESSIVE ) ) { if ( (this->bDoBurst || this->bDoAutofire) && !ubAimTime ) modifier += 10; } // Show-off - better performance if some babes around to impress - else if ( gMercProfiles[this->ubProfile].bCharacterTrait == CHAR_TRAIT_SHOWOFF ) + else if ( DoesMercHavePersonality( this, CHAR_TRAIT_SHOWOFF ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( this->ubProfile, CHAR_TRAIT_SHOWOFF ); if ( bNumMercs > 1 ) @@ -16837,15 +16821,16 @@ INT8 SOLDIERTYPE::GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubT } // Small penalty for fear of insects in tropical sectors // Flugente: drugs can temporarily cause a merc get a new disability - else if ( ((gMercProfiles[this->ubProfile].bDisability == FEAR_OF_INSECTS) || MercUnderTheInfluence( this, DRUG_TYPE_FEAROFINSECTS )) && MercIsInTropicalSector( this ) ) + else if ( DoesMercHaveDisability( this, FEAR_OF_INSECTS ) && MercIsInTropicalSector( this ) ) { // fear of insects, and we are in tropical sector modifier -= 5; } } } + // Dauntless - penalty for not taking proper cover - if ( ubTargetProfile != NOBODY ) + if ( ubTargetProfile != NO_PROFILE ) { if ( gMercProfiles[ubTargetProfile].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) modifier += 5; @@ -16854,7 +16839,7 @@ INT8 SOLDIERTYPE::GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubT else { // this rather unlogical bonus for psychotic characters applies only with old traits - if ( this->ubProfile != NO_PROFILE && gMercProfiles[this->ubProfile].bDisability == PSYCHO || MercUnderTheInfluence( this, DRUG_TYPE_PSYCHO ) ) + if ( DoesMercHaveDisability( this, PSYCHO ) ) { modifier += AIM_BONUS_PSYCHO; } @@ -16863,14 +16848,14 @@ INT8 SOLDIERTYPE::GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubT return modifier; } -void SOLDIERTYPE::AddDrugValues( UINT8 uDrugType, UINT8 usEffect, UINT8 usTravelRate, UINT8 usSideEffect ) +/*void SOLDIERTYPE::AddDrugValues( UINT8 uDrugType, UINT8 usEffect, UINT8 usTravelRate, UINT8 usSideEffect ) { // in case of wrong inout, stay safe if ( uDrugType >= DRUG_TYPE_MAX ) return; // Flugente: backgrounds - if ( this->ubProfile != NOBODY && uDrugType == DRUG_TYPE_ALCOHOL ) + if ( uDrugType == DRUG_TYPE_ALCOHOL ) { usEffect = usEffect * ((100 - this->GetBackgroundValue( BG_RESI_ALCOHOL )) / 100); usSideEffect = usSideEffect * ((100 - this->GetBackgroundValue( BG_RESI_ALCOHOL )) / 100); @@ -16896,7 +16881,7 @@ void SOLDIERTYPE::AddDrugValues( UINT8 uDrugType, UINT8 usEffect, UINT8 usTravel // set flag: we are on drugs this->usSoldierFlagMask |= SOLDIER_DRUGGED; -} +}*/ void SOLDIERTYPE::HandleFlashLights( ) { @@ -17222,11 +17207,23 @@ FLOAT SOLDIERTYPE::GetMoraleModifier( ) FLOAT mod = 1.0f; UINT8 officertype = OFFICER_NONE; - if ( HighestEnemyOfficersInSector( officertype ) ) + if ( bTeam == ENEMY_TEAM && HighestEnemyOfficersInSector( officertype ) ) { mod += gGameExternalOptions.dEnemyOfficerMoraleModifier * officertype; } + // Flugente: disease + if ( gGameExternalOptions.fDisease ) + { + FLOAT diseaseeffect = 1.0f; + for ( int i = 0; i < NUM_DISEASES; ++i ) + { + diseaseeffect *= 1.0f - (1.0f - Disease[i].moralemodifier) * this->GetDiseaseMagnitude( i ); + } + + mod *= diseaseeffect; + } + return mod; } @@ -17234,11 +17231,11 @@ INT16 SOLDIERTYPE::GetInterruptModifier( UINT8 usDistance ) { INT16 bonus = 0; - // drugs can alter our perception + /*// drugs can alter our perception if ( this->drugs.bDrugEffect[DRUG_TYPE_PERCEPTION] ) bonus += 2; else if ( this->drugs.bDrugSideEffect[DRUG_TYPE_PERCEPTION] ) - bonus -= 2; + bonus -= 2;*/ // if we are listening on our radio, our mind will be somewhere else... we will be less focused if ( this->IsRadioListening( ) ) @@ -19008,6 +19005,46 @@ INT8 SOLDIERTYPE::GetSleepBreathRegeneration( ) return bMaxBreathRegain; } +// Flugente: assumed character weight (without any items) +FLOAT SOLDIERTYPE::GetBodyWeight() +{ + switch ( this->ubBodyType ) + { + case REGMALE: + case MANCIV: + return 85.0f; + break; + + case BIGMALE: + case STOCKYMALE: + return 110.0f; + break; + + case REGFEMALE: + return 75.0f; + break; + + case FATCIV: + return 100.0f; + break; + + case MINICIV: + case DRESSCIV: + return 60.0f; + break; + + case HATKIDCIV: + case KIDCIV: + return 40.0f; + break; + + case CRIPPLECIV: + return 75.0f; + break; + } + + return 80.0f; +} INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) { @@ -20039,45 +20076,7 @@ void SOLDIERTYPE::EVENT_SoldierApplyItemToPerson( INT32 sGridNo, UINT8 ubDirecti if ( success ) { - if ( Item[usItem].canteen ) - { - if ( !gGameOptions.fFoodSystem ) - { - BOOLEAN tmp = FALSE; - success = ApplyCanteen( pSoldier, pObj, &tmp, FALSE ); - } - else - { - success = ApplyFood( pSoldier, pObj, TRUE, TRUE ); - } - } - else if ( Item[usItem].drugtype ) - { - // applying drugs also handles food items - success = ApplyDrugs( pSoldier, pObj ); - } - else if ( Item[usItem].camouflagekit ) - { - BOOLEAN tmp = FALSE; - success = ApplyCammo( pSoldier, pObj, &tmp, FALSE ); - - if ( success ) - { - // WANNE: We should only delete the face, if there was a camo we applied. - // This should fix the bug and crashes with missing faces - if ( gGameExternalOptions.fShowCamouflageFaces == TRUE ) - { - // Flugente: refresh face regardless of result of SetCamoFace(), otherwise applying a rag will not clean the picture - SetCamoFace( pSoldier ); - DeleteSoldierFace( pSoldier );// remove face - pSoldier->iFaceIndex = InitSoldierFace( pSoldier );// create new face - } - - // Dirty - fInterfacePanelDirty = DIRTYLEVEL2; - } - } - else if ( Item[usItem].gasmask ) + if ( Item[usItem].gasmask ) { // put this item into a (at best empty) faceslot if no gasmask is been worn INT8 bSlot = FindGasMask( pSoldier ); @@ -20100,17 +20099,14 @@ void SOLDIERTYPE::EVENT_SoldierApplyItemToPerson( INT32 sGridNo, UINT8 ubDirecti } } } - else if ( Item[usItem].clothestype ) - { - ApplyClothes( pSoldier, pObj, FALSE ); - - // Dirty - fInterfacePanelDirty = DIRTYLEVEL2; - } - else if ( Item[ usItem ].usItemClass == IC_BOMB ) + else if ( Item[usItem].usItemClass == IC_BOMB ) { success = AutoPlaceObject( pSoldier, pObj, FALSE ); } + else if ( ApplyConsumable( pSoldier, pObj, TRUE, TRUE ) ) + { + success = TRUE; + } } DeductPoints( this, GetAPsToApplyItem( this, sGridNo ), APBPConstants[BP_APPLYITEM], AFTERACTION_INTERRUPT ); @@ -21856,27 +21852,30 @@ BOOLEAN ResolvePendingInterrupt( SOLDIERTYPE * pSoldier, UINT8 ubInterruptType ) iInjuryPenalty = (200 * (pInterrupter->stats.bLifeMax - pInterrupter->stats.bLife + ((pInterrupter->stats.bLifeMax - pInterrupter->stats.bLife - pInterrupter->bBleeding) / 2))) / (pInterrupter->stats.bLifeMax); uiReactionTime = (uiReactionTime * (100 + iInjuryPenalty * (100 - (3 * EffectiveExpLevel( pInterrupter ))) / 100) / 100); } + // adjust by breath down if ( pSoldier->bBreath < 100 ) { // +1% per 2 points of breath down uiReactionTime = (uiReactionTime * (100 + ((100 - pSoldier->bBreath) / 2)) / 100); } + // adjust for getting aid, being in gas or being in shock if ( pInterrupter->flags.uiStatusFlags & SOLDIER_GASSED ) uiReactionTime = (uiReactionTime * (100 + AIM_PENALTY_GASSED) / 100); + if ( pInterrupter->ubServiceCount > 0 ) uiReactionTime = (uiReactionTime * (100 + AIM_PENALTY_GETTINGAID) / 100); + if ( pInterrupter->aiData.bShock ) uiReactionTime = (uiReactionTime * (100 + (pInterrupter->aiData.bShock * 20)) / 100); // this is severe, 20% per point - // Phlegmatic characters has slightly longer reaction time - if ( pSoldier->ubProfile != NO_PROFILE ) + + // Phlegmatic characters has slightly longer reaction time + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PHLEGMATIC ) ) { - if ( gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC ) - { - uiReactionTime = ((uiReactionTime * 110) / 100); - } + uiReactionTime = ((uiReactionTime * 110) / 100); } + // finally divide back by 10 to get the needed result (round properly) uiReactionTime = ((uiReactionTime + 5) / 10); @@ -22869,7 +22868,7 @@ void HandleVolunteerRecruitment( SOLDIERTYPE* pRecruiter, SOLDIERTYPE* pTarget ) FLOAT leadershipfactor = EffectiveLeadership( pRecruiter ) / 100.0; // bonus for assertive characters - if ( gMercProfiles[pRecruiter->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE ) + if ( DoesMercHavePersonality( pRecruiter, CHAR_TRAIT_ASSERTIVE ) ) leadershipfactor *= 1.05; FLOAT recruitmodifier = (100 + pRecruiter->GetBackgroundValue( BG_PERC_APPROACH_RECRUIT )) / 100.0; @@ -22892,3 +22891,164 @@ void HandleVolunteerRecruitment( SOLDIERTYPE* pRecruiter, SOLDIERTYPE* pTarget ) } } } + +// Flugente: apply a consumable item on a soldier. Returns true if item was successfully interacted with +BOOLEAN ApplyConsumable( SOLDIERTYPE* pSoldier, OBJECTTYPE *pObj, BOOLEAN fForce, BOOLEAN fUseAPs ) +{ + if ( !pSoldier || !pObj ) + return FALSE; + + // if it's not a kit or a misc item, we cannot consume it + if ( !(Item[pObj->usItem].usItemClass & (IC_KIT | IC_MISC)) ) + return FALSE; + + BOOLEAN fDoSound = FALSE; + + // use portionsize, if none was entered, use full item + UINT8 portionsize = Item[pObj->usItem].usPortionSize; + if ( !portionsize ) + portionsize = 100; + + // how much of this item do we use up + UINT16 statusused = min( portionsize, (*pObj)[0]->data.objectStatus ); + if ( !statusused ) + return FALSE; + + // if we check for APs, do so - if we don't have enough, stop + if ( fUseAPs ) + { + // an object can be consumed in several ways (like food that is also a drug), but each consumption might have a different AP cost. + // as it would be very odd if an effect does not happen because the corresponding AP cost could not be met, we analyze the item first and determine the AP cost. + // We then either apply everything or nothing + UINT16 apcost = 0; + + if ( HasItemFlag( pObj->usItem, CAMO_REMOVAL ) && gGameExternalOptions.fCamoRemoving ) + { + apcost = max( apcost, (APBPConstants[AP_CAMOFLAGE] / 2) ); + } + + if ( Item[pObj->usItem].camouflagekit ) + { + apcost = max( apcost, APBPConstants[AP_CAMOFLAGE] ); + } + + if ( Item[pObj->usItem].canteen ) + { + apcost = max( apcost, APBPConstants[AP_DRINK] ); + } + + if ( pObj->usItem == JAR_ELIXIR ) + { + apcost = max( apcost, APBPConstants[AP_CAMOFLAGE] ); + } + + if ( Item[pObj->usItem].clothestype ) + { + INT16 disguise_apcost = (APBPConstants[AP_DISGUISE] * (100 - gSkillTraitValues.sCODisguiseAPReduction * NUM_SKILL_TRAITS( pSoldier, COVERT_NT ))) / 100; + + apcost = max( apcost, disguise_apcost ); + } + + if ( Item[pObj->usItem].drugtype ) + { + apcost = max( apcost, APBPConstants[AP_DRINK] ); + } + + if ( Item[pObj->usItem].foodtype ) + { + // do we eat or drink this stuff? + UINT8 apcost_type = AP_EAT; + if ( Food[Item[pObj->usItem].foodtype].bDrinkPoints > Food[Item[pObj->usItem].foodtype].bFoodPoints ) + apcost_type = AP_DRINK; + + apcost = max( apcost, APBPConstants[apcost_type] ); + } + + if ( !fForce && !EnoughPoints( pSoldier, apcost, 0, TRUE ) ) + { + return FALSE; + } + } + + // under certain conditions, a merc can but simply does not want to consume an item, and can refuse if not forced to. + if ( !fForce ) + { + if ( DoesSoldierRefuseToEat( pSoldier, pObj ) ) + { + return FALSE; + } + + // some mercs will refuse to smoke + if ( Item[pObj->usItem].cigarette && pSoldier->GetBackgroundValue( BG_SMOKERTYPE ) == 2 ) + { + // merc gets slightly pissed by the player even suggesting this + TacticalCharacterDialogue( pSoldier, QUOTE_PRE_NOT_SMART ); + pSoldier->aiData.bMorale = max( 0, pSoldier->aiData.bMorale - 1 ); + + return FALSE; + } + } + + // Try to apply camo.... + // this returns true if camo can be applied, but APs were only used, and the action happened, if *pfGoodAPs is TRUE + if ( ApplyCamo( pSoldier, pObj->usItem, statusused ) ) + { + fDoSound = TRUE; + + // WANNE: We should only delete the face, if there was a camo we applied. + // This should fix the bug and crashes with missing faces + if ( gGameExternalOptions.fShowCamouflageFaces ) + { + // Flugente: refresh face regardless of result of SetCamoFace(), otherwise applying a rag will not clean the picture + SetCamoFace( pSoldier ); + DeleteSoldierFace( pSoldier );// remove face + pSoldier->iFaceIndex = InitSoldierFace( pSoldier );// create new face + } + } + + if ( ApplyCanteen( pSoldier, pObj->usItem, statusused ) ) + { + fDoSound = FALSE; + } + + if ( ApplyElixir( pSoldier, pObj->usItem, statusused ) ) + { + fDoSound = TRUE; + } + + if ( ApplyClothes( pSoldier, pObj->usItem, statusused ) ) + { + + } + + if ( ApplyFood( pSoldier, pObj, statusused ) ) + { + fDoSound = FALSE; + } + + if ( ApplyDrugs_New( pSoldier, pObj->usItem, statusused ) ) + { + // no sound on consuming cigarettes, as that is very annoying + if ( !Item[pObj->usItem].cigarette ) + { + fDoSound = TRUE; + } + } + + // use up object + UseKitPoints( pObj, statusused, pSoldier ); + + if ( fUseAPs ) + { + // Dirty + fInterfacePanelDirty = DIRTYLEVEL2; + } + + if ( fDoSound ) + { + // Say OK acknowledge.... + pSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 ); + } + + return TRUE; +} diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 3cc267cf..855c5c5c 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -355,7 +355,7 @@ enum // -------- added by Flugente: various flags for soldiers -------- // easier than adding 32 differently named variables. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!! -#define SOLDIER_DRUGGED 0x00000001 //1 // Soldier is on drugs +#define SOLDIER_DRUGGED 0x00000001 //1 // Soldier is on (non-alcoholic) drugs #define SOLDIER_NO_AP 0x00000002 //2 // Soldier has no APs this turn (fix for reinforcement bug) #define SOLDIER_COVERT_CIV 0x00000004 //4 // Soldier is currently disguised as a civilian #define SOLDIER_COVERT_SOLDIER 0x00000008 //8 // Soldier is currently disguised as an enemy soldier @@ -409,6 +409,7 @@ enum #define SOLDIER_INTERROGATE_CIVILIAN 0x00000100 //256 // interrogate civilian #define SOLDIER_POTENTIAL_VOLUNTEER 0x00000200 //512 // this civilian _might_ join us as a volunteer if conditions are right +#define SOLDIER_HUNGOVER 0x00000400 //1024 // we drank alcohol recently, and are now hungover #define SOLDIER_INTERROGATE_ALL 0x000001F8 // all interrogation flags // ---------------------------------------------------------------- @@ -911,6 +912,36 @@ public: INT8 bTimesDrugUsedSinceSleep[DRUG_TYPE_MAX]; }; +// Flugente: everything drug-related has been redone +enum { + DRUG_EFFECT_HP = 0, + DRUG_EFFECT_BP, + DRUG_EFFECT_AP, + DRUG_EFFECT_MORALE, + DRUG_EFFECT_PHYS_RES, + DRUG_EFFECT_STR, + DRUG_EFFECT_AGI, + DRUG_EFFECT_DEX, + DRUG_EFFECT_WIS, + + DRUG_EFFECT_MAX = 20, +}; + + +struct DRUGS +{ + UINT16 duration[DRUG_EFFECT_MAX]; + INT16 size[DRUG_EFFECT_MAX]; + + UINT8 drugpersonality; + UINT16 drugpersonality_duration; + + UINT8 drugdisability; + UINT16 drugdisability_duration; + + FLOAT drinkstaken; // number of alcoholic drinks we habe in our system, lowered by 1 every hour +}; + class STRUCT_TimeCounters//last edited at version 102 { public: @@ -1361,8 +1392,8 @@ public: INT8 bGoodContPath; UINT8 ubPendingActionInterrupted; INT8 bNoiseLevel; - INT8 bRegenerationCounter; - INT8 bRegenBoostersUsedToday; + INT8 bRegenerationCounter; // Flugente: not used anymore! + INT8 bRegenBoostersUsedToday; // Flugente: not used anymore! INT8 bNumPelletsHitBy; INT32 sSkillCheckGridNo; UINT8 ubLastEnemyCycledID; @@ -1520,7 +1551,8 @@ public: STRUCT_Flags flags; STRUCT_TimeChanges timeChanges; STRUCT_TimeCounters timeCounters; - STRUCT_Drugs drugs; + //STRUCT_Drugs drugs; // Flugente: drug values are now in newdrugs + DRUGS newdrugs; STRUCT_Statistics stats; STRUCT_Pathing pathing; @@ -1788,7 +1820,7 @@ public: INT8 GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubTargetProfile ); - void AddDrugValues(UINT8 uDrugType, UINT8 usEffect, UINT8 usTravelRate, UINT8 usSideEffect ); + //void AddDrugValues(UINT8 uDrugType, UINT8 usEffect, UINT8 usTravelRate, UINT8 usSideEffect ); void HandleFlashLights(); UINT8 GetBestEquippedFlashLightRange(); @@ -1876,6 +1908,8 @@ public: // Flugente: hourly breath regen calculation INT8 GetSleepBreathRegeneration(); + // Flugente: assumed character weight (without any items) + FLOAT GetBodyWeight(); ////////////////////////////////////////////////////////////////////////////// }; // SOLDIERTYPE; @@ -2728,6 +2762,9 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB // Flugente: decide whether pRecruiter can successfully recruit pTarget to be a volunteer void HandleVolunteerRecruitment( SOLDIERTYPE* pRecruiter, SOLDIERTYPE* pTarget ); +// Flugente: apply a consumable item on a soldier. Returns true if item was successfully interacted with +BOOLEAN ApplyConsumable( SOLDIERTYPE* pSoldier, OBJECTTYPE *pObject, BOOLEAN fForce, BOOLEAN fUseAPs ); + #endif diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index 1697794e..51edc9b7 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -3471,16 +3471,12 @@ void CreateAssassin(UINT8 disguisetype) if ( vestfound ) { - CreateItem( vestitem, 100, &gTempObject ); - - ApplyClothes(pSoldier, &gTempObject, FALSE); + ApplyClothes( pSoldier, vestitem, 100 ); } if ( pantsfound ) { - CreateItem( pantsitem, 100, &gTempObject ); - - ApplyClothes(pSoldier, &gTempObject, FALSE); + ApplyClothes( pSoldier, vestitem, 100 ); } // Dirty diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index bbf25dec..e04e0296 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -2297,7 +2297,7 @@ BOOLEAN MercIsHot( SOLDIERTYPE * pSoldier ) { // SANDRO - added argument // Flugente: drugs can temporarily cause a merc to be heat intolerant - if ( pSoldier->ubProfile != NO_PROFILE && (gMercProfiles[ pSoldier->ubProfile ].bDisability == HEAT_INTOLERANT || MercUnderTheInfluence(pSoldier, DRUG_TYPE_HEATINTOLERANT) ) && !pSoldier->MercInWater()) + if ( !pSoldier->MercInWater( ) && DoesMercHaveDisability( pSoldier, HEAT_INTOLERANT ) ) { if ((pSoldier->bSectorZ > 0) || (guiEnvWeather & ( WEATHER_FORECAST_SHOWERS | WEATHER_FORECAST_THUNDERSHOWERS ))) { @@ -2859,18 +2859,18 @@ INT8 CheckMercsNearForCharTraits( UINT8 ubProfileID, INT8 bCharTraitID ) { // Sociable - we are OK with everyone except those wicked malicious guys case CHAR_TRAIT_SOCIABLE: - if( gMercProfiles[ pTeammate->ubProfile ].bCharacterTrait != CHAR_TRAIT_MALICIOUS ) - bNumber++; + if ( !DoesMercHavePersonality( pTeammate, CHAR_TRAIT_MALICIOUS ) ) + ++bNumber; break; // Loner can tolerate one other loner around case CHAR_TRAIT_LONER: - if ( gMercProfiles[ pTeammate->ubProfile ].bCharacterTrait == CHAR_TRAIT_LONER && !fOnlyOneException ) + if ( !fOnlyOneException && DoesMercHavePersonality( pTeammate, CHAR_TRAIT_LONER ) ) { fOnlyOneException = TRUE; } else { - bNumber++; + ++bNumber; } break; // Show-off, depends on gender and appearance of others @@ -2885,9 +2885,9 @@ INT8 CheckMercsNearForCharTraits( UINT8 ubProfileID, INT8 bCharTraitID ) bNumber += 2; // However remove one if ugly one else if ( gMercProfiles[ pTeammate->ubProfile ].bAppearance == APPEARANCE_UGLY ) - bNumber--; + --bNumber; else - bNumber++; + ++bNumber; } } // If we are female @@ -2900,14 +2900,14 @@ INT8 CheckMercsNearForCharTraits( UINT8 ubProfileID, INT8 bCharTraitID ) bNumber += 2; // However remove one if ugly one else if ( gMercProfiles[ pTeammate->ubProfile ].bAppearance == APPEARANCE_UGLY ) - bNumber--; + --bNumber; else - bNumber++; + ++bNumber; } } break; default: - bNumber++; + ++bNumber; break; } } diff --git a/Tactical/TeamTurns.cpp b/Tactical/TeamTurns.cpp index e8703b81..d800c47c 100644 --- a/Tactical/TeamTurns.cpp +++ b/Tactical/TeamTurns.cpp @@ -1914,8 +1914,9 @@ INT8 CalcInterruptDuelPts( SOLDIERTYPE * pSoldier, UINT8 ubOpponentID, BOOLEAN f iPoints += gSkillTraitValues.ubNOIterruptsBonusInDark; } } + // Phlegmatics get a small penalty to interrupts - if ( gMercProfiles[ pSoldier->ubProfile ].bCharacterTrait == CHAR_TRAIT_PHLEGMATIC ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_PHLEGMATIC ) ) { iPoints -= 1; } diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 352a4550..17961063 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -1575,6 +1575,10 @@ void CheatCreateItem( ) { INT16 status = 100; FLOAT temperature = 0.0; + + if ( Item[usitem].foodtype ) + temperature = OVERHEATING_MAX_TEMPERATURE; + // Flugente: spawn items while debugging OBJECTTYPE newobj; CreateItem( usitem, status, &newobj ); diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index fb0ffbe7..59dbf540 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -6075,14 +6075,12 @@ else //Give 60% the normal stomp modifier as the aim mod iAimModifier += (FLOAT)iTraitModifier * 0.6f; } - //else - //{ - // Flugente: drugs can temporarily cause a merc to go psycho - if ( pSoldier->ubProfile != NO_PROFILE && (gMercProfiles[ pSoldier->ubProfile ].bDisability == PSYCHO || MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) ) - { - iAimModifier += gGameCTHConstants.AIM_PSYCHO; - } - //} + + // Flugente: drugs can temporarily cause a merc to go psycho + if ( DoesMercHaveDisability( pSoldier, PSYCHO ) ) + { + iAimModifier += gGameCTHConstants.AIM_PSYCHO; + } ////////////////////////////////////////// // Gun Handling modifiers @@ -7201,12 +7199,9 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, // HEADROCK HAM B2.6: Externalized the value iPenalty = __min( (UINT16)((float)pTarget->bTilesMoved * (float)gGameExternalOptions.iMovementEffectOnAiming), gGameExternalOptions.usMaxCTHPenaltyForMovingTarget ); /////////////////////////////////////////////////////////////////////////////////// - // SANDRO - fearless characters do not even take their head down no matter what - if ( gGameOptions.fNewTraitSystem && pTarget->ubProfile != NO_PROFILE ) - { - if ( gMercProfiles[ pTarget->ubProfile ].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) - iPenalty -= (iPenalty * 2 / 3); // two thirds only - } + // SANDRO - fearless characters do not even take their head down no matter what + if ( DoesMercHavePersonality( pTarget, CHAR_TRAIT_DAUNTLESS ) ) + iPenalty -= (iPenalty * 2 / 3); // two thirds only /////////////////////////////////////////////////////////////////////////////////// iChance -= iPenalty; @@ -9496,11 +9491,14 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, INT32 sOrigGridNo = 0; BOOLEAN fFragment = FALSE; INT32 iTotalArmourProtection=0; + UINT16 ammoitem = NOTHING; if (pBullet == NULL && pFirer ) { usAttackingWeapon = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType; sOrigGridNo = pFirer->sGridNo; + + ammoitem = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.usGunAmmoItem; } else { @@ -9543,6 +9541,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, // Flugente: check for underbarrel weapons and use that object if necessary OBJECTTYPE* pObj = pFirer->GetUsedWeapon( &pFirer->inv[pFirer->ubAttackingHand] ); ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType; + + ammoitem = (*pObj)[0]->data.gun.usGunAmmoItem; } else { @@ -9637,21 +9637,31 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, if ( iImpact > 0 && !TANK( pTarget ) ) { - // Flugente: ammo can now add the lifedamage drug effect. This will kill the target in a few turns. + // Flugente: any bullet can have drug effects it set so in the magazine item + if ( ammoitem != NOTHING ) + { + ApplyDrugs_New( pTarget, ammoitem, 100 ); + } + + /*// Flugente: ammo can now add the lifedamage drug effect. This will kill the target in a few turns. // this is intended to work on darts, but it is possible on any ammo if ( AmmoTypes[ubAmmoType].ammoflag & AMMO_NEUROTOXIN ) { pTarget->usSoldierFlagMask |= SOLDIER_DRUGGED; + ApplyDrugs_New( pTarget, ammoitem, 100 ); + // Add lifedamage effects pTarget->AddDrugValues( DRUG_TYPE_LIFEDAMAGE, Drug[DRUG_TYPE_LIFEDAMAGE].ubDrugEffect, Drug[DRUG_TYPE_LIFEDAMAGE].ubDrugTravelRate, Drug[DRUG_TYPE_LIFEDAMAGE].ubDrugSideEffect ); } - else if ( AmmoTypes[ubAmmoType].dart && sHitBy > 20 ) + else */ + if ( AmmoTypes[ubAmmoType].dart && sHitBy > 20 ) { if (pubSpecial) { *pubSpecial = FIRE_WEAPON_SLEEP_DART_SPECIAL; } + return( iImpact ); } @@ -9866,14 +9876,15 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, } BOOLEAN fMaliciousHit = FALSE; // SANDRO - Malicious characters inflict stat loss more often - if ( gGameOptions.fNewTraitSystem && pFirer && pFirer->ubProfile != NO_PROFILE && !fFragment) + if ( pFirer && !fFragment) { - if ( gMercProfiles[ pFirer->ubProfile ].bCharacterTrait == CHAR_TRAIT_MALICIOUS ) + if ( DoesMercHavePersonality( pFirer, CHAR_TRAIT_MALICIOUS ) ) { uiCritChance += 8; fMaliciousHit = TRUE; } } + // SANDRO - with new traits, the chance for stat loss is higher as we are now able to repair it if ((PreRandom( uiCritChance ) + 1) > (UINT8)(gGameOptions.fNewTraitSystem ? gSkillTraitValues.ubDamageNeededToLoseStats : CRITICAL_HIT_THRESHOLD)) { @@ -10374,7 +10385,7 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO } // bonus damage for aggressive characters - if ( gGameOptions.fNewTraitSystem && gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_AGGRESSIVE ) + if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_AGGRESSIVE ) ) { iBonus += 10; // +10% } @@ -10622,7 +10633,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi // psycho bonus - only with old traits - SANDRO // Flugente: drugs can temporarily cause a merc to go psycho - if ( !( gGameOptions.fNewTraitSystem ) && pAttacker->ubProfile != NO_PROFILE && (gMercProfiles[ pAttacker->ubProfile ].bDisability == PSYCHO || MercUnderTheInfluence(pAttacker, DRUG_TYPE_PSYCHO) ) ) + if ( !(gGameOptions.fNewTraitSystem) && DoesMercHaveDisability( pAttacker, PSYCHO ) ) { iAttRating += AIM_BONUS_PSYCHO; } @@ -10767,7 +10778,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi if ( gGameOptions.fNewTraitSystem && pAttacker->ubProfile != NO_PROFILE ) { // Sociable - better performance in groups - if ( gMercProfiles[ pAttacker->ubProfile ].bCharacterTrait == CHAR_TRAIT_SOCIABLE ) + if ( DoesMercHavePersonality( pAttacker, CHAR_TRAIT_SOCIABLE ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pAttacker->ubProfile, CHAR_TRAIT_SOCIABLE ); if ( bNumMercs > 2 ) @@ -10776,7 +10787,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi iAttRating += 2; } // Loner - better performance when alone - else if ( gMercProfiles[ pAttacker->ubProfile ].bCharacterTrait == CHAR_TRAIT_LONER ) + else if ( DoesMercHavePersonality( pAttacker, CHAR_TRAIT_LONER ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pAttacker->ubProfile, CHAR_TRAIT_LONER ); if ( bNumMercs == 0 ) @@ -10785,7 +10796,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi iAttRating += 2; } // Show-off - better performance if some babes around to impress - else if ( gMercProfiles[ pAttacker->ubProfile ].bCharacterTrait == CHAR_TRAIT_SHOWOFF ) + else if ( DoesMercHavePersonality( pAttacker, CHAR_TRAIT_SHOWOFF ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pAttacker->ubProfile, CHAR_TRAIT_SHOWOFF ); if ( bNumMercs > 1 ) @@ -11028,7 +11039,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi if ( gGameOptions.fNewTraitSystem && pDefender->ubProfile != NO_PROFILE ) { // Sociable - better performance in groups - if ( gMercProfiles[ pDefender->ubProfile ].bCharacterTrait == CHAR_TRAIT_SOCIABLE ) + if ( DoesMercHavePersonality( pDefender, CHAR_TRAIT_SOCIABLE ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pDefender->ubProfile, CHAR_TRAIT_SOCIABLE ); if ( bNumMercs > 2 ) @@ -11037,7 +11048,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi iDefRating += 2; } // Loner - better performance when alone - else if ( gMercProfiles[ pDefender->ubProfile ].bCharacterTrait == CHAR_TRAIT_LONER ) + else if ( DoesMercHavePersonality( pDefender, CHAR_TRAIT_LONER ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pDefender->ubProfile, CHAR_TRAIT_LONER ); if ( bNumMercs == 0 ) @@ -11046,7 +11057,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi iDefRating += 2; } // Show-off - better performance if some babes around to impress - else if ( gMercProfiles[ pDefender->ubProfile ].bCharacterTrait == CHAR_TRAIT_SHOWOFF ) + else if ( DoesMercHavePersonality( pDefender, CHAR_TRAIT_SHOWOFF ) ) { INT8 bNumMercs = CheckMercsNearForCharTraits( pDefender->ubProfile, CHAR_TRAIT_SHOWOFF ); if ( bNumMercs > 1 ) @@ -11054,7 +11065,7 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi else if ( bNumMercs > 0 ) iDefRating += 2; } - else if ( gMercProfiles[ pDefender->ubProfile ].bCharacterTrait == CHAR_TRAIT_DAUNTLESS ) + else if ( DoesMercHavePersonality( pDefender, CHAR_TRAIT_DAUNTLESS ) ) { iDefRating -= 5; } @@ -12330,7 +12341,7 @@ void EstimateBulletsLeft( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj ) // Is this Soldier a psycho? // Flugente: drugs can temporarily cause a merc to go psycho - if ( pSoldier->ubProfile != NO_PROFILE && (gMercProfiles[ pSoldier->ubProfile ].bDisability == PSYCHO || MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) ) + if ( DoesMercHaveDisability( pSoldier, PSYCHO ) ) { fPsycho = TRUE; } @@ -13058,7 +13069,7 @@ FLOAT CalcNewChanceToHitAimEffectBonus(SOLDIERTYPE *pSoldier) } // Flugente: drugs can temporarily cause a merc to go psycho - if ( pSoldier->ubProfile != NO_PROFILE && (gMercProfiles[ pSoldier->ubProfile ].bDisability == PSYCHO || MercUnderTheInfluence(pSoldier, DRUG_TYPE_PSYCHO) ) ) + if ( DoesMercHaveDisability( pSoldier, PSYCHO ) ) { fAimModifier += gGameCTHConstants.AIM_PSYCHO; } diff --git a/Tactical/XML.h b/Tactical/XML.h index 70fa274f..0cbadb4f 100644 --- a/Tactical/XML.h +++ b/Tactical/XML.h @@ -35,7 +35,16 @@ enum MERCHANT_CASH_DAILY, MERCHANT_COOLNESS, MERCHANT_FLAGS, - MERCHANT_REORDER + MERCHANT_REORDER, + + ELEMENT_DRUG_EFFECT, + ELEMENT_DRUG_EFFECT_PROPERTY, + ELEMENT_DISEASE_EFFECT, + ELEMENT_DISEASE_EFFECT_PROPERTY, + ELEMENT_DISABILITY_EFFECT, + ELEMENT_DISABILITY_EFFECT_PROPERTY, + ELEMENT_PERSONALITY_EFFECT, + ELEMENT_PERSONALITY_EFFECT_PROPERTY } typedef PARSE_STAGE; diff --git a/Tactical/XML_Background.cpp b/Tactical/XML_Background.cpp index e9b469e2..f62245de 100644 --- a/Tactical/XML_Background.cpp +++ b/Tactical/XML_Background.cpp @@ -130,6 +130,7 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha strcmp(name, "tracker_ability" ) == 0 || strcmp(name, "ambush_radius" ) == 0 || strcmp(name, "dislikebackground" ) == 0 || + strcmp(name, "smoker" ) == 0 || strcmp(name, "druguse") == 0 || strcmp(name, "xenophobic") == 0 || strcmp(name, "corruptionspread") == 0 || @@ -549,6 +550,11 @@ backgroundEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curBackground.value[BG_DISLIKEBG] = (INT16)atol( pData->szCharData ); } + else if ( strcmp( name, "smoker" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curBackground.value[BG_SMOKERTYPE] = min( 2, max( 0, (INT16)atol( pData->szCharData ) ) ); + } else if(strcmp(name, "druguse") == 0) { pData->curElement = ELEMENT; diff --git a/Tactical/XML_Disease.cpp b/Tactical/XML_Disease.cpp index e4f20904..f5c521b2 100644 --- a/Tactical/XML_Disease.cpp +++ b/Tactical/XML_Disease.cpp @@ -44,6 +44,9 @@ diseaseStartElementHandle( void *userData, const XML_Char *name, const XML_Char memset( &pData->curItem, 0, sizeof(DISEASE) ); + // default value + pData->curItem.moralemodifier = 1.0f; + pData->maxReadDepth++; //we are not skipping this element } else if ( pData->curElement == ELEMENT && @@ -86,7 +89,8 @@ diseaseStartElementHandle( void *userData, const XML_Char *name, const XML_Char strcmp( name, "sLifeRegenHundreds" ) == 0 || strcmp( name, "sNeedToSleep" ) == 0 || strcmp( name, "sDrinkModifier" ) == 0 || - strcmp( name, "sFoodModifier" ) == 0) ) + strcmp( name, "sFoodModifier" ) == 0 || + strcmp( name, "moralemodifier" ) == 0 ) ) { pData->curElement = ELEMENT_PROPERTY; @@ -345,6 +349,11 @@ diseaseEndElementHandle( void *userData, const XML_Char *name ) pData->curElement = ELEMENT; pData->curItem.sFoodModifier = (INT16)atol( pData->szCharData ); } + else if ( strcmp( name, "moralemodifier" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curItem.moralemodifier = (FLOAT)atof( pData->szCharData ); + } pData->maxReadDepth--; } @@ -468,6 +477,7 @@ BOOLEAN WriteDiseaseStats( ) FilePrintf( hFile, "\t\t%d\r\n", Disease[cnt].sNeedToSleep ); FilePrintf( hFile, "\t\t%d\r\n", Disease[cnt].sDrinkModifier ); FilePrintf( hFile, "\t\t%d\r\n", Disease[cnt].sFoodModifier ); + FilePrintf( hFile, "\t\t%3.2f\r\n", Disease[cnt].moralemodifier ); FilePrintf( hFile, "\t\r\n" ); } diff --git a/Tactical/XML_Drugs.cpp b/Tactical/XML_Drugs.cpp index 92c74385..a3ec3430 100644 --- a/Tactical/XML_Drugs.cpp +++ b/Tactical/XML_Drugs.cpp @@ -14,12 +14,17 @@ struct PARSE_STAGE curElement; CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1]; - DRUGTYPE curDrugs; - DRUGTYPE * curArray; - UINT32 maxArraySize; + DRUG curDrugs; + DRUG * curArray; + UINT32 maxArraySize; - UINT32 currentDepth; - UINT32 maxReadDepth; + UINT32 currentDepth; + UINT32 maxReadDepth; + + DRUG_EFFECT drug_effects; + DISEASE_EFFECT disease_effects; + DISABILITY_EFFECT disability_effects; + PERSONALITY_EFFECT personality_effects; } typedef drugsParseData; @@ -34,7 +39,7 @@ drugsStartElementHandle(void *userData, const XML_Char *name, const XML_Char **a { pData->curElement = ELEMENT_LIST; - memset(pData->curArray,0,sizeof(DRUGTYPE)*pData->maxArraySize); + memset(pData->curArray,0,sizeof(DRUG)*pData->maxArraySize); pData->maxReadDepth++; //we are not skipping this element } @@ -42,27 +47,106 @@ drugsStartElementHandle(void *userData, const XML_Char *name, const XML_Char **a { pData->curElement = ELEMENT; - memset(&pData->curDrugs,0,sizeof(DRUGTYPE)); + memset( &pData->curDrugs, 0, sizeof(DRUG) ); pData->maxReadDepth++; //we are not skipping this element } else if(pData->curElement == ELEMENT && - (strcmp(name, "ubType") == 0 || - strcmp(name, "name") == 0 || - strcmp(name, "ubDrugTravelRate") == 0 || - strcmp(name, "ubDrugWearoffRate") == 0 || - strcmp(name, "ubDrugEffect") == 0 || - strcmp(name, "ubDrugSideEffect") == 0 || - strcmp(name, "ubDrugSideEffectRate") == 0 || - strcmp(name, "ubMoralBacklash" ) == 0 || - strcmp(name, "ubMoralBacklash" ) == 0 || - strcmp(name, "ubDiseaseCure" ) == 0 )) + (strcmp(name, "uiIndex") == 0 || + strcmp(name, "szName") == 0 || + strcmp(name, "opinionevent" ) == 0 )) { pData->curElement = ELEMENT_PROPERTY; pData->maxReadDepth++; //we are not skipping this element } + else if ( pData->curElement == ELEMENT && + (strcmp( name, "DRUG_EFFECT" ) == 0) ) + { + pData->curElement = ELEMENT_DRUG_EFFECT; + // start of a new element: set default values + pData->drug_effects.effect = 0; + pData->drug_effects.duration = 0; + pData->drug_effects.size = 0; + pData->drug_effects.chance = 100; + + pData->maxReadDepth++; + } + else if ( pData->curElement == ELEMENT && + (strcmp( name, "DISEASE_EFFECT" ) == 0) ) + { + pData->curElement = ELEMENT_DISEASE_EFFECT; + + // start of a new element: set default values + pData->disease_effects.disease = 0; + pData->disease_effects.size = 0; + pData->disease_effects.chance = 100; + + pData->maxReadDepth++; + } + else if ( pData->curElement == ELEMENT && + (strcmp( name, "DISABILITY_EFFECT" ) == 0) ) + { + pData->curElement = ELEMENT_DISABILITY_EFFECT; + + // start of a new element: set default values + pData->disability_effects.disability = 0; + pData->disability_effects.duration = 0; + pData->disability_effects.chance = 100; + + pData->maxReadDepth++; + } + else if ( pData->curElement == ELEMENT && + (strcmp( name, "PERSONALITY_EFFECT" ) == 0) ) + { + pData->curElement = ELEMENT_PERSONALITY_EFFECT; + + // start of a new element: set default values + pData->personality_effects.personality = 0; + pData->personality_effects.duration = 0; + pData->personality_effects.chance = 100; + + pData->maxReadDepth++; + } + else if ( pData->curElement == ELEMENT_DRUG_EFFECT && + (strcmp( name, "effect" ) == 0 || + strcmp( name, "duration" ) == 0 || + strcmp( name, "size" ) == 0 || + strcmp( name, "chance" ) == 0 ) ) + { + pData->curElement = ELEMENT_DRUG_EFFECT_PROPERTY; + + pData->maxReadDepth++; //we are not skipping this element + } + else if ( pData->curElement == ELEMENT_DISEASE_EFFECT && + (strcmp( name, "disease" ) == 0 || + strcmp( name, "size" ) == 0 || + strcmp( name, "chance" ) == 0) ) + { + pData->curElement = ELEMENT_DISEASE_EFFECT_PROPERTY; + + pData->maxReadDepth++; //we are not skipping this element + } + else if ( pData->curElement == ELEMENT_DISABILITY_EFFECT && + (strcmp( name, "disability" ) == 0 || + strcmp( name, "duration" ) == 0 || + strcmp( name, "chance" ) == 0) ) + { + pData->curElement = ELEMENT_DISABILITY_EFFECT_PROPERTY; + + pData->maxReadDepth++; //we are not skipping this element + } + else if ( pData->curElement == ELEMENT_PERSONALITY_EFFECT && + (strcmp( name, "personality" ) == 0 || + strcmp( name, "duration" ) == 0 || + strcmp( name, "chance" ) == 0) ) + { + pData->curElement = ELEMENT_PERSONALITY_EFFECT_PROPERTY; + + pData->maxReadDepth++; //we are not skipping this element + } + pData->szCharData[0] = '\0'; } @@ -98,56 +182,127 @@ drugsEndElementHandle(void *userData, const XML_Char *name) { pData->curElement = ELEMENT_LIST; - // we do NOT want to read the first entry -> move stuff by 1 - if(pData->curDrugs.ubType < pData->maxArraySize + 1 && pData->curDrugs.ubType > 0) // do not write the first item into our array - { - pData->curArray[pData->curDrugs.ubType - 1] = pData->curDrugs; //write the drugs into the table - } + pData->curArray[pData->curDrugs.uiIndex] = pData->curDrugs; //write the drugs into the table } - else if(strcmp(name, "ubType") == 0) + else if(strcmp(name, "uiIndex") == 0) { pData->curElement = ELEMENT; - pData->curDrugs.ubType = (UINT8) atol(pData->szCharData); + pData->curDrugs.uiIndex = (UINT8)atol( pData->szCharData ); } - else if(strcmp(name, "name") == 0) + else if(strcmp(name, "szName") == 0) { pData->curElement = ELEMENT; // not needed, but its there for informational purposes + + MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curDrugs.szName, sizeof(pData->curDrugs.szName) / sizeof(pData->curDrugs.szName[0]) ); + pData->curDrugs.szName[sizeof(pData->curDrugs.szName) / sizeof(pData->curDrugs.szName[0]) - 1] = '\0'; } - else if(strcmp(name, "ubDrugTravelRate") == 0) + else if(strcmp(name, "opinionevent") == 0) { pData->curElement = ELEMENT; - pData->curDrugs.ubDrugTravelRate = (UINT8) atol(pData->szCharData); + pData->curDrugs.opinionevent = (BOOLEAN)atol( pData->szCharData ); } - else if(strcmp(name, "ubDrugWearoffRate") == 0) + + // Close opened Tags. + else if ( strcmp( name, "DRUG_EFFECT" ) == 0 ) { pData->curElement = ELEMENT; - pData->curDrugs.ubDrugWearoffRate = (UINT8) atol(pData->szCharData); + + pData->curDrugs.drug_effects.push_back( pData->drug_effects ); } - else if(strcmp(name, "ubDrugEffect") == 0) + else if ( strcmp( name, "DISEASE_EFFECT" ) == 0 ) { pData->curElement = ELEMENT; - pData->curDrugs.ubDrugEffect = (UINT8) atol(pData->szCharData); + + pData->curDrugs.disease_effects.push_back( pData->disease_effects ); } - else if(strcmp(name, "ubDrugSideEffect") == 0) + else if ( strcmp( name, "DISABILITY_EFFECT" ) == 0 ) { pData->curElement = ELEMENT; - pData->curDrugs.ubDrugSideEffect = (UINT8) atol(pData->szCharData); + + pData->curDrugs.disability_effects.push_back( pData->disability_effects ); } - else if(strcmp(name, "ubDrugSideEffectRate") == 0) + else if ( strcmp( name, "PERSONALITY_EFFECT" ) == 0 ) { pData->curElement = ELEMENT; - pData->curDrugs.ubDrugSideEffectRate = (UINT8) atol(pData->szCharData); + + pData->curDrugs.personality_effects.push_back( pData->personality_effects ); } - else if(strcmp(name, "ubMoralBacklash") == 0) + + else if ( pData->curElement == ELEMENT_DRUG_EFFECT_PROPERTY ) { - pData->curElement = ELEMENT; - pData->curDrugs.ubMoralBacklash = (UINT8) atol(pData->szCharData); + if ( strcmp( name, "effect" ) == 0 ) + { + pData->drug_effects.effect = (UINT8)atol( pData->szCharData ); + } + else if ( strcmp( name, "duration" ) == 0 ) + { + pData->drug_effects.duration = (UINT16)atol( pData->szCharData ); + } + else if ( strcmp( name, "size" ) == 0 ) + { + pData->drug_effects.size = (INT16)atol( pData->szCharData ); + } + else if ( strcmp( name, "chance" ) == 0 ) + { + pData->drug_effects.chance = (UINT8)atol( pData->szCharData ); + } + + pData->curElement = ELEMENT_DRUG_EFFECT; } - else if ( strcmp( name, "ubDiseaseCure" ) == 0 ) + + else if ( pData->curElement == ELEMENT_DISEASE_EFFECT_PROPERTY ) { - pData->curElement = ELEMENT; - pData->curDrugs.ubDiseaseCure = (UINT8)atol( pData->szCharData ); + if ( strcmp( name, "disease" ) == 0 ) + { + pData->disease_effects.disease = (UINT8)atol( pData->szCharData ); + } + else if ( strcmp( name, "size" ) == 0 ) + { + pData->disease_effects.size = (INT32)atol( pData->szCharData ); + } + else if ( strcmp( name, "chance" ) == 0 ) + { + pData->disease_effects.chance = (UINT8)atol( pData->szCharData ); + } + + pData->curElement = ELEMENT_DISEASE_EFFECT; + } + + else if ( pData->curElement == ELEMENT_DISABILITY_EFFECT_PROPERTY ) + { + if ( strcmp( name, "disability" ) == 0 ) + { + pData->disability_effects.disability = (UINT8)atol( pData->szCharData ); + } + else if ( strcmp( name, "duration" ) == 0 ) + { + pData->disability_effects.duration = (UINT16)atol( pData->szCharData ); + } + else if ( strcmp( name, "chance" ) == 0 ) + { + pData->disability_effects.chance = (UINT8)atol( pData->szCharData ); + } + + pData->curElement = ELEMENT_DISABILITY_EFFECT; + } + + else if ( pData->curElement == ELEMENT_PERSONALITY_EFFECT_PROPERTY ) + { + if ( strcmp( name, "personality" ) == 0 ) + { + pData->personality_effects.personality = (UINT8)atol( pData->szCharData ); + } + else if ( strcmp( name, "duration" ) == 0 ) + { + pData->personality_effects.duration = (UINT16)atol( pData->szCharData ); + } + else if ( strcmp( name, "chance" ) == 0 ) + { + pData->personality_effects.chance = (UINT8)atol( pData->szCharData ); + } + + pData->curElement = ELEMENT_PERSONALITY_EFFECT; } pData->maxReadDepth--; @@ -196,8 +351,8 @@ BOOLEAN ReadInDrugsStats(STR fileName) memset(&pData,0,sizeof(pData)); - pData.curArray = Drug; - pData.maxArraySize = DRUG_TYPE_MAX; + pData.curArray = NewDrug; + pData.maxArraySize = NEW_DRUGS_MAX; XML_SetUserData(parser, &pData); @@ -234,21 +389,42 @@ BOOLEAN WriteDrugsStats() return( FALSE ); { - UINT32 cnt; - FilePrintf(hFile,"\r\n"); - for(cnt = 0;cnt < DRUG_TYPE_MAX;cnt++) + for ( UINT32 cnt = 0; cnt < NEW_DRUGS_MAX; ++cnt ) { FilePrintf(hFile,"\t\r\n"); - FilePrintf(hFile,"\t\t%d\r\n", cnt ); - FilePrintf(hFile,"\t\t%d\r\n", Drug[cnt].ubDrugTravelRate ); - FilePrintf(hFile,"\t\t%d\r\n", Drug[cnt].ubDrugWearoffRate ); - FilePrintf(hFile,"\t\t%d\r\n", Drug[cnt].ubDrugEffect ); - FilePrintf(hFile,"\t\t%d\r\n", Drug[cnt].ubDrugSideEffect ); - FilePrintf(hFile,"\t\t%d\r\n", Drug[cnt].ubDrugSideEffectRate ); - FilePrintf(hFile,"\t\t%d\r\n", Drug[cnt].ubMoralBacklash ); - FilePrintf(hFile,"\t\t%d\r\n", Drug[cnt].ubDiseaseCure ); + FilePrintf(hFile,"\t\t%d\r\n", cnt ); + FilePrintf(hFile,"\t\t%d\r\n", NewDrug[cnt].opinionevent ); + + for ( std::vector::iterator it = NewDrug[cnt].drug_effects.begin( ); it != NewDrug[cnt].drug_effects.end( ); ++it ) + { + FilePrintf( hFile, "\t\t%d\r\n", (*it).effect ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).duration ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).size ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).chance ); + } + + for ( std::vector::iterator it = NewDrug[cnt].disease_effects.begin( ); it != NewDrug[cnt].disease_effects.end( ); ++it ) + { + FilePrintf( hFile, "\t\t%d\r\n", (*it).disease ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).size ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).chance ); + } + + for ( std::vector::iterator it = NewDrug[cnt].disability_effects.begin( ); it != NewDrug[cnt].disability_effects.end( ); ++it ) + { + FilePrintf( hFile, "\t\t%d\r\n", (*it).disability ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).duration ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).chance ); + } + + for ( std::vector::iterator it = NewDrug[cnt].personality_effects.begin( ); it != NewDrug[cnt].personality_effects.end( ); ++it ) + { + FilePrintf( hFile, "\t\t%d\r\n", (*it).personality ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).duration ); + FilePrintf( hFile, "\t\t%d\r\n", (*it).chance ); + } FilePrintf(hFile,"\t\r\n"); } diff --git a/Tactical/XML_Food.cpp b/Tactical/XML_Food.cpp index f2a45336..92eb00e7 100644 --- a/Tactical/XML_Food.cpp +++ b/Tactical/XML_Food.cpp @@ -51,7 +51,6 @@ foodStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "szName") == 0 || strcmp(name, "bFoodPoints") == 0 || strcmp(name, "bDrinkPoints") == 0 || - strcmp(name, "ubPortionSize") == 0 || strcmp(name, "usDecayRate") == 0 )) { pData->curElement = ELEMENT_PROPERTY; @@ -120,11 +119,6 @@ foodEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curFood.bDrinkPoints = (INT32) atol(pData->szCharData); } - else if(strcmp(name, "ubPortionSize") == 0) - { - pData->curElement = ELEMENT; - pData->curFood.ubPortionSize = (UINT16) atol(pData->szCharData); - } else if(strcmp(name, "usDecayRate") == 0) { pData->curElement = ELEMENT; @@ -225,7 +219,6 @@ BOOLEAN WriteFoodStats() FilePrintf(hFile,"\t\t%d\r\n", cnt ); FilePrintf(hFile,"\t\t%d\r\n", Food[cnt].bFoodPoints ); FilePrintf(hFile,"\t\t%d\r\n", Food[cnt].bDrinkPoints ); - FilePrintf(hFile,"\t\t%d\r\n", Food[cnt].ubPortionSize ); FilePrintf(hFile,"\t\t%4.2f\r\n", Food[cnt].usDecayRate ); FilePrintf(hFile,"\t\r\n"); diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index ae9f3cc2..7e3a11b2 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -4120,7 +4120,7 @@ void DebugSoldierPage1( ) gprintf( 350, LINE_HEIGHT * ubLine, L"%d", pSoldier->stats.bMedical); ubLine++; - SetFontShade(LARGEFONT1, FONT_SHADE_GREEN); + /*SetFontShade(LARGEFONT1, FONT_SHADE_GREEN); gprintf( 200, LINE_HEIGHT * ubLine, L"Drug Effects:"); SetFontShade(LARGEFONT1, FONT_SHADE_NEUTRAL); gprintf( 400, LINE_HEIGHT * ubLine, L"%d", pSoldier->drugs.bDrugEffect[0] ); @@ -4142,7 +4142,7 @@ void DebugSoldierPage1( ) gprintf( 200, LINE_HEIGHT * ubLine, L"Hangover Side Effects:"); SetFontShade(LARGEFONT1, FONT_SHADE_NEUTRAL); gprintf( 400, LINE_HEIGHT * ubLine, L"%d", pSoldier->drugs.bDrugSideEffect[1] ); - ubLine++; + ubLine++;*/ SetFontShade(LARGEFONT1, FONT_SHADE_GREEN); gprintf( 200, LINE_HEIGHT * ubLine, L"AI has Keys:"); @@ -5428,11 +5428,12 @@ UINT8 MovementNoise( SOLDIERTYPE *pSoldier ) iStealthSkill -= 20; // 20% penalty } - if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] ) + // Flugente: deleting this + /*if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] ) { // minus 3 percent per bonus AP from adrenaline iStealthSkill -= 3 * pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ]; - } + }*/ /* // if sneaker is too eager and impatient to "do it right" diff --git a/Tactical/soldier profile type.h b/Tactical/soldier profile type.h index 1e50792b..364b92d5 100644 --- a/Tactical/soldier profile type.h +++ b/Tactical/soldier profile type.h @@ -309,7 +309,7 @@ typedef enum } RacistLevels; // Flugente: dynamic opinons: number of profile flagmasks -#define OPINION_FLAGMASKS_NUMBER 5 +#define OPINION_FLAGMASKS_NUMBER 6 ////////////////////////////////////////////////////////////////////// diff --git a/TacticalAI/NPC.cpp b/TacticalAI/NPC.cpp index ed91b7f1..65fbb615 100644 --- a/TacticalAI/NPC.cpp +++ b/TacticalAI/NPC.cpp @@ -54,6 +54,7 @@ #include "BriefingRoom_Data.h" #include "Map Screen Helicopter.h" + #include "Drugs And Alcohol.h" // added by Flugente for DoesMercHavePersonality( ... ) #ifdef JA2UB #include "Ja25_Tactical.h" @@ -872,7 +873,7 @@ INT32 CalcThreateningEffectiveness( UINT8 ubMerc ) } // SANDRO - bonus for threatening for assertive people - if ( gGameOptions.fNewTraitSystem && gMercProfiles[pSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE ) + if ( gGameOptions.fNewTraitSystem && DoesMercHavePersonality( pSoldier, CHAR_TRAIT_ASSERTIVE ) ) { iDeadliness += 50; } @@ -899,10 +900,14 @@ UINT8 CalcDesireToTalk( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach ) // SANDRO - bonus for communication with people for assertive people if ( gGameOptions.fNewTraitSystem && bApproach != APPROACH_THREATEN) { - if ( pMercProfile->bCharacterTrait == CHAR_TRAIT_ASSERTIVE ) - iPersonalVal += 50; - else if ( pMercProfile->bCharacterTrait == CHAR_TRAIT_MALICIOUS ) - iPersonalVal -= 50; + INT16 id = GetSoldierIDFromMercID( ubMerc ); + if ( id > -1 ) + { + if ( DoesMercHavePersonality( MercPtrs[id], CHAR_TRAIT_ASSERTIVE ) ) + iPersonalVal += 50; + else if ( DoesMercHavePersonality( MercPtrs[id], CHAR_TRAIT_MALICIOUS ) ) + iPersonalVal -= 50; + } } // ARM: NOTE - for towns which don't use loyalty (San Mona, Estoni, Tixa, Orta ) diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 5b0e6949..32e42f02 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -5561,7 +5561,7 @@ BOOLEAN HandleAttachedExplosions(UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, IN IgniteExplosion( ubOwner, sX, sY, sZ, sGridNo, GAS_EXPLOSION, bLevel, DIRECTION_IRRELEVANT , NULL ); fAttFound = TRUE; } - if(Item[iter->usItem].alcohol) + if ( Item[iter->usItem].alcohol > 0.0f ) { IgniteExplosion( ubOwner, sX, sY, sZ, sGridNo, MOLOTOV_EXPLOSION, bLevel, DIRECTION_IRRELEVANT , NULL ); fAttFound = TRUE; diff --git a/Utils/Text.h b/Utils/Text.h index 4def2b49..56cba45d 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -489,6 +489,7 @@ enum MSG_MERC_CASTS_LIGHT_OFF, MSG_SQUAD_ACTIVE_STRING, + MSG_MERC_TOOK_CIGARETTE, TEXT_NUM_MSG, }; diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index 991a75d0..ae8de0ab 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -85,13 +85,16 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at if ( !localizedTextOnly ) memset(&pData->curItem,0,sizeof(INVTYPE)); + // Flugente: default value + pData->curItem.usPortionSize = 100; + // HEADROCK HAM 4: With the new stance-based variables, it is necessary to set vars to have an impossible // value. That way when they are later recorded in the item structs, a parent->child inheritence can occur // for children that do not have data put into them from XML. // -10000 has been selected to pose as "no value". Modders should never even reduce the value of any of // these tags below -100 anyway, and although it's not the best solution that's the only one I came up with. - for (INT8 X = 0; X < 3; X++) + for (INT8 X = 0; X < 3; ++X) { pData->curItem.flatbasemodifier[X] = -10000; pData->curItem.percentbasemodifier[X] = -10000; @@ -283,6 +286,8 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "usSpotting") == 0 || strcmp(name, "sBackpackWeightModifier") == 0 || strcmp(name, "fAllowClimbing") == 0 || + strcmp(name, "cigarette" ) == 0 || + strcmp(name, "usPortionSize" ) == 0 || strcmp(name, "diseaseprotectionface" ) == 0 || strcmp(name, "diseaseprotectionhand" ) == 0)) { @@ -941,7 +946,9 @@ itemEndElementHandle(void *userData, const XML_Char *name) else if(strcmp(name, "Alcohol") == 0) { pData->curElement = ELEMENT; - pData->curItem.alcohol = (BOOLEAN) atol(pData->szCharData); + pData->curItem.alcohol = (FLOAT) atof(pData->szCharData); + + pData->curItem.alcohol = max( 0.0f, pData->curItem.alcohol ); } else if(strcmp(name, "Hardware") == 0) { @@ -1453,6 +1460,16 @@ itemEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curItem.fAllowClimbing = (BOOLEAN)atol(pData->szCharData); } + else if ( strcmp( name, "cigarette" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curItem.cigarette = (BOOLEAN)atol( pData->szCharData ); + } + else if ( strcmp( name, "usPortionSize" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curItem.usPortionSize = (UINT8)atol( pData->szCharData ); + } // Flugente: simple tags in the xml get translated into flags else if ( strcmp( name, "diseaseprotectionface" ) == 0 ) { @@ -1986,7 +2003,7 @@ BOOLEAN WriteItemStats() FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].gasmask ); - FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].alcohol ); + FilePrintf(hFile,"\t\t%3.2f\r\n", Item[cnt].alcohol ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].hardware ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].medical ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].camouflagekit ); @@ -2095,8 +2112,10 @@ BOOLEAN WriteItemStats() FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usBuddyItem ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].ubSleepModifier ); FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usSpotting ); - FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].sBackpackWeightModifier); - FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].fAllowClimbing); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].sBackpackWeightModifier); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].fAllowClimbing); + FilePrintf(hFile, "\t\t%d\r\n", Item[cnt].cigarette ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].usPortionSize ); if ( Item[cnt].usItemFlag & DISEASEPROTECTION_1 ) FilePrintf( hFile, "\t\t%d\r\n", 1 ); diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 49fe3049..b44b1d5f 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -6207,6 +6207,7 @@ STR16 pMessageStrings[] = L"虚拟佣兵光照开启", L"虚拟佣兵光照关闭", L"Squad %s active.", //TODO.Translate + L"%s smoked %s.", }; @@ -8278,6 +8279,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", // TODO.Translate + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] = diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index da1ebc3b..f22f6073 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -6215,6 +6215,7 @@ STR16 pMessageStrings[] = L"Artificial Merc Light ON", // TODO.Translate L"Artificial Merc Light OFF", L"Squad %s active.", //TODO.Translate + L"%s smoked %s.", }; @@ -8291,6 +8292,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", // TODO.Translate + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] = // TODO.Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index b350c38b..257a1a39 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -6206,6 +6206,7 @@ STR16 pMessageStrings[] = L"Artificial Merc Light ON", L"Artificial Merc Light OFF", L"Squad %s active.", + L"%s smoked %s.", }; @@ -8276,6 +8277,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 3ddaeba3..a1faefc5 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -6217,6 +6217,7 @@ STR16 pMessageStrings[] = L"Éclairage du mercenaire activé", L"Éclairage du mercenaire désactivé", L"Squad %s active.", //TODO.Translate + L"%s smoked %s.", }; @@ -8277,6 +8278,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", // TODO.Translate + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] = diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 22795844..55fa6cfc 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -6052,6 +6052,7 @@ STR16 pMessageStrings[] = L"Artificial Merc Light ON", // TODO.Translate L"Artificial Merc Light OFF", L"Squad %s active.", //TODO.Translate + L"%s smoked %s.", }; CHAR16 ItemPickupHelpPopup[][40] = @@ -8108,6 +8109,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", // TODO.Translate + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] = // TODO.Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 0fc60898..d19adb23 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -6203,6 +6203,7 @@ STR16 pMessageStrings[] = L"Artificial Merc Light ON", // TODO.Translate L"Artificial Merc Light OFF", L"Squad %s active.", //TODO.Translate + L"%s smoked %s.", }; @@ -8286,6 +8287,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", // TODO.Translate + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] = // TODO.Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index c18d89f2..b54df6f7 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -6221,6 +6221,7 @@ STR16 pMessageStrings[] = L"Artificial Merc Light ON", // TODO.Translate L"Artificial Merc Light OFF", L"Squad %s active.", //TODO.Translate + L"%s smoked %s.", }; @@ -8303,6 +8304,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", // TODO.Translate + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] = // TODO.Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 41c21667..158d299d 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -6203,6 +6203,7 @@ STR16 pMessageStrings[] = L"Подсветка наемника включена", L"Подсветка наемника отключена", L"Squad %s active.", //TODO.Translate + L"%s smoked %s.", }; @@ -8275,6 +8276,8 @@ STR16 szBackgroundText_Value[]= L" %s%d%% initial distance to enemy in ambush\n", L" dislikes some other backgrounds", // TODO.Translate + L"Smoker", + L"Nonsmoker", }; STR16 szBackgroundTitleText[] =