From aaeea9aac8d5009c7f6f1a172f6e64248012aa51 Mon Sep 17 00:00:00 2001 From: rftrdev <102184004+rftrdev@users.noreply.github.com> Date: Wed, 9 Aug 2023 18:36:44 -0700 Subject: [PATCH] Replace evolution with growth rates (#201) --- GameSettings.cpp | 5 +- GameSettings.h | 7 +- GameVersion.h | 3 +- Laptop/personnel.cpp | 194 ++++++++++++++++++++++++++++++-- SaveLoadGame.cpp | 121 +++++++++++++++++++- Strategic/mapscreen.cpp | 20 ++-- Tactical/Campaign.cpp | 70 ++++++------ Tactical/Campaign.h | 4 +- Tactical/Interface Panels.cpp | 20 ++-- Tactical/Soldier Control.cpp | 2 +- Tactical/Soldier Profile.cpp | 47 +++++++- Tactical/Soldier Profile.h | 13 ++- Tactical/XML_Profiles.cpp | 94 +++++++++++++++- Tactical/soldier profile type.h | 28 ++--- TacticalAI/NPC.cpp | 12 +- Utils/Text.h | 30 +++++ Utils/_ChineseText.cpp | 22 ++-- Utils/_DutchText.cpp | 22 ++-- Utils/_EnglishText.cpp | 22 ++-- Utils/_FrenchText.cpp | 22 ++-- Utils/_GermanText.cpp | 22 ++-- Utils/_ItalianText.cpp | 22 ++-- Utils/_PolishText.cpp | 22 ++-- Utils/_RussianText.cpp | 22 ++-- 24 files changed, 685 insertions(+), 161 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 3791ae0c..28bf1151 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1079,6 +1079,9 @@ void LoadGameExternalOptions() gGameExternalOptions.ubMercRandomExpRange = iniReader.ReadInteger("Recruitment Settings", "MERCS_RANDOM_EXP_RANGE", 1, 0, 4); gGameExternalOptions.fMercRandomStartSalary = iniReader.ReadBoolean("Recruitment Settings", "MERCS_RANDOM_START_SALARY", FALSE); gGameExternalOptions.ubMercRandomStartSalaryPercentMod = iniReader.ReadInteger("Recruitment Settings", "MERCS_RANDOM_START_SALARY_PERCENTAGE_MAX_MODIFIER", 30, 0, 100); + gGameExternalOptions.fMercGrowthModifiersEnabled = iniReader.ReadBoolean("Recruitment Settings", "MERCS_GROWTH_MODIFIERS_ENABLED", FALSE); + gGameExternalOptions.fMercRandomGrowthModifiers = iniReader.ReadBoolean("Recruitment Settings", "MERCS_RANDOM_GROWTH_MODIFIERS", FALSE); + gGameExternalOptions.iMercRandomGrowthModifiersRange = iniReader.ReadInteger("Recruitment Settings", "MERCS_RANDOM_GROWTH_MODIFIERS_RANGE", 5, -50, 50); //################# Financial Settings ################# @@ -2480,8 +2483,6 @@ void LoadGameExternalOptions() gGameExternalOptions.ubTeachBonusToTrain = iniReader.ReadInteger("Strategic Assignment Settings","TEACHER_TRAIT_BONUS_TO_TRAINING_EFFICIENCY",30, 0, 100); gGameExternalOptions.ubMinSkillToTeach = iniReader.ReadInteger("Strategic Assignment Settings","MIN_SKILL_REQUIRED_TO_TEACH_OTHER",25, 0, 100); - gGameExternalOptions.bDisableEvolution = iniReader.ReadBoolean("Strategic Assignment Settings", "DISABLE_EVOLUTION", TRUE ); - // HEADROCK HAM B2.8: New Trainer Relations: 2 = Trainees will go to sleep when their trainer goes to sleep. 3 = Trainer will go to sleep if all trainees are asleep. 1 = Both. 0 = Neither. gGameExternalOptions.ubSmartTrainingSleep = iniReader.ReadInteger("Strategic Assignment Settings","SYNCHRONIZED_SLEEPING_HOURS_WHEN_TRAINING_TOGETHER", 0, 0, 3); diff --git a/GameSettings.h b/GameSettings.h index 5bdeb6dc..735538f3 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -816,9 +816,6 @@ typedef struct INT32 ubRpcBonusToTrainMilitia; INT32 ubMinSkillToTeach; - // Flugente: disable evolution setting in MercProfiles.xml - BOOLEAN bDisableEvolution; - INT32 ubLowActivityLevel; INT32 ubMediumActivityLevel; INT32 ubHighActivityLevel; @@ -1440,6 +1437,10 @@ typedef struct UINT8 ubMercRandomStartSalaryPercentMod; + BOOLEAN fMercGrowthModifiersEnabled; + BOOLEAN fMercRandomGrowthModifiers; + INT16 iMercRandomGrowthModifiersRange; + BOOLEAN fBobbyRayFastShipments; BOOLEAN fGridExitInTurnBased; diff --git a/GameVersion.h b/GameVersion.h index d322980c..b516b225 100644 --- a/GameVersion.h +++ b/GameVersion.h @@ -23,6 +23,7 @@ extern CHAR16 zBuildInformation[256]; // Keeps track of the saved game version. Increment the saved game version whenever // you will invalidate the saved game file +#define GROWTH_MODIFIERS 184 #define REBELCOMMAND 183 #define DRAGSTRUCTURE 182 // Flugente: we can drag structures behind us #define DISABILITYFLAGMASK 181 // Flugente: disabilities get a flagmask @@ -104,7 +105,7 @@ extern CHAR16 zBuildInformation[256]; #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 REBELCOMMAND +#define SAVE_GAME_VERSION GROWTH_MODIFIERS //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Laptop/personnel.cpp b/Laptop/personnel.cpp index beb0e873..e2576e33 100644 --- a/Laptop/personnel.cpp +++ b/Laptop/personnel.cpp @@ -2170,7 +2170,7 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot) for ( int i = APPROACH_FRIENDLY; i <= APPROACH_RECRUIT; ++i ) { - mprintf( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + 15), szLaptopStatText[7 + i] ); + mprintf( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + 15), szLaptopStatText[LAPTOP_STAT_TEXT_FRIENDLY_APPROACH-1 + i] ); // APPROACH_FRIENDLY is 1 so fix the offset CHAR16 sStr[200]; swprintf( sStr, L"" ); @@ -2180,7 +2180,7 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot) swprintf( sStr, L"%d", val ); - FindFontRightCoordinates( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH - 20, 0, sStr, PERS_FONT, &sX, &sY ); + FindFontRightCoordinates( (INT16)(pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, sStr, PERS_FONT, &sX, &sY ); mprintf( sX, (pPersonnelScreenPoints[loc].y + 15), sStr ); // Add specific region for fast help window @@ -2205,10 +2205,10 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot) if ( (gMercProfiles[pSoldier->ubProfile].ubMiscFlags3 & PROFILE_MISC_FLAG3_GOODGUY) ) { CHAR16 sStr1[200]; - swprintf( sStr1, szLaptopStatText[6] ); + swprintf( sStr1, szLaptopStatText[LAPTOP_STAT_TEXT_GOOD_GUY] ); CHAR16 sStr2[200]; - swprintf( sStr2, szLaptopStatText[7], pSoldier->GetName( ) ); + swprintf( sStr2, szLaptopStatText[LAPTOP_STAT_TEXT_REFUSES_TO_ATTACK_NON_HOSTILES], pSoldier->GetName( ) ); sX = pPersonnelScreenPoints[loc].x + (iSlot*TEXT_BOX_WIDTH); @@ -2233,15 +2233,189 @@ void DisplayCharPersonality(INT32 iId, INT32 iSlot) ++region; } - if ( !gGameExternalOptions.bDisableEvolution ) + if (gGameExternalOptions.fMercGrowthModifiersEnabled) { - CHAR16 sStr2[200]; - swprintf( sStr2, szLaptopStatText[12 + gMercProfiles[pSoldier->ubProfile].bEvolution], pSoldier->GetName() ); + if (gMercProfiles[pSoldier->ubProfile].fRegresses) + { + CHAR16 sStr2[200]; + swprintf(sStr2, szLaptopStatText[LAPTOP_STAT_TEXT_MERC_REGRESSES]); - mprintf( (INT16)( pPersonnelScreenPoints[loc].x + ( iSlot*TEXT_BOX_WIDTH ) ), ( pPersonnelScreenPoints[loc].y + 15 ), sStr2 ); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + 15), sStr2); - ++loc; - ++region; + ++loc; + ++region; + } + else + { + const int THRESHOLD_FAST = -3; // this value and below: "fast" + const int THRESHOLD_SLOW = 3; // this value and above: "slow" + int yOffset = 15; + CHAR16 statTxt[200]; + // health + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_HEALTH_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLife <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLife >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // strength + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_STRENGTH_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierStrength <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierStrength >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // agility + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_AGILITY_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierAgility <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierAgility >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // dexterity + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_DEXTERITY_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierDexterity <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierDexterity >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // wisdom + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_WISDOM_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierWisdom <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierWisdom >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // marksmanship + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_MARKSMANSHIP_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMarksmanship <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMarksmanship >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // explosives + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_EXPLOSIVES_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExplosive <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExplosive >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // leadership + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_LEADERSHIP_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLeadership <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierLeadership >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // medical + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_MEDICAL_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMedical <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMedical >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // mechanical + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_MECHANICAL_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMechanical <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierMechanical >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + yOffset += 10; + } + // exp level + { + swprintf(statTxt, szLaptopStatText[LAPTOP_STAT_TEXT_EXPERIENCE_SPEED]); + mprintf((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + + if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExpLevel <= THRESHOLD_FAST) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_FAST]); + else if (gMercProfiles[pSoldier->ubProfile].bGrowthModifierExpLevel >= THRESHOLD_SLOW) + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_SLOW]); + else + swprintf(statTxt, L"%s", szLaptopStatText[LAPTOP_STAT_TEXT_AVERAGE]); + FindFontRightCoordinates((INT16)(pPersonnelScreenPoints[loc].x + (iSlot * TEXT_BOX_WIDTH)), 0, TEXT_BOX_WIDTH, 0, statTxt, PERS_FONT, &sX, &sY); + mprintf(sX, (pPersonnelScreenPoints[loc].y + yOffset), statTxt); + } + } } } diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 5c245e84..37eca4c5 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -1294,7 +1294,16 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for numBytesRead = ReadFieldByField( hFile, &this->bSex, sizeof(this->bSex), sizeof(INT8), numBytesRead); numBytesRead = ReadFieldByField( hFile, &this->bArmourAttractiveness, sizeof(this->bArmourAttractiveness), sizeof(INT8), numBytesRead); numBytesRead = ReadFieldByField( hFile, &this->ubMiscFlags2, sizeof(this->ubMiscFlags2), sizeof(UINT8), numBytesRead); - numBytesRead = ReadFieldByField( hFile, &this->bEvolution, sizeof(this->bEvolution), sizeof(INT8), numBytesRead); + if (guiCurrentSaveGameVersion < GROWTH_MODIFIERS) + { + numBytesRead = ReadFieldByField( hFile, &this->fRegresses, sizeof(this->fRegresses), sizeof(INT8), numBytesRead); + // convert old evolution to regresses boolean + this->fRegresses = this->fRegresses == 2 ? TRUE : FALSE; // 2 == CharacterEvolution::DEVOLVES + } + else + { + numBytesRead = ReadFieldByField( hFile, &this->fRegresses, sizeof(this->fRegresses), sizeof(INT8), numBytesRead); + } numBytesRead = ReadFieldByField( hFile, &this->ubMiscFlags, sizeof(this->ubMiscFlags), sizeof(UINT8), numBytesRead); numBytesRead = ReadFieldByField( hFile, &this->bSexist, sizeof(this->bSexist), sizeof(UINT8), numBytesRead); numBytesRead = ReadFieldByField( hFile, &this->bLearnToHate, sizeof(this->bLearnToHate), sizeof(UINT8), numBytesRead); @@ -1637,6 +1646,70 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for return( FALSE ); } } + + // rftr: growth modifiers + if (guiCurrentSaveGameVersion >= GROWTH_MODIFIERS) + { + if (!FileRead(hFile, &this->bGrowthModifierLife, sizeof(INT8), &uiNumBytesRead)) + { + return(FALSE); + } + if ( !FileRead( hFile, &this->bGrowthModifierStrength, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierAgility, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierDexterity, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierWisdom, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierMarksmanship, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierExplosive, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierLeadership, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierMedical, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierMechanical, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + if ( !FileRead( hFile, &this->bGrowthModifierExpLevel, sizeof(INT8), &uiNumBytesRead) ) + { + return( FALSE ); + } + } + else + { + // zero out growth modifiers for upgrading savegames + this->bGrowthModifierLife = 0; + this->bGrowthModifierStrength = 0; + this->bGrowthModifierAgility = 0; + this->bGrowthModifierDexterity = 0; + this->bGrowthModifierWisdom = 0; + this->bGrowthModifierMarksmanship = 0; + this->bGrowthModifierExplosive = 0; + this->bGrowthModifierLeadership = 0; + this->bGrowthModifierMedical = 0; + this->bGrowthModifierMechanical = 0; + this->bGrowthModifierExpLevel = 0; + } } if ( this->uiProfileChecksum != this->GetChecksum() ) @@ -1753,6 +1826,52 @@ BOOLEAN MERCPROFILESTRUCT::Save(HWFILE hFile) { return( FALSE ); } + + // rftr: growth modifiers + if (!FileWrite(hFile, &this->bGrowthModifierLife, sizeof(INT8), &uiNumBytesWritten)) + { + return(FALSE); + } + if ( !FileWrite( hFile, &this->bGrowthModifierStrength, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierAgility, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierDexterity, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierWisdom, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierMarksmanship, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierExplosive, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierLeadership, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierMedical, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierMechanical, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } + if ( !FileWrite( hFile, &this->bGrowthModifierExpLevel, sizeof(INT8), &uiNumBytesWritten) ) + { + return( FALSE ); + } return TRUE; } diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index 11c39563..4d387161 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -3372,7 +3372,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.AGL.iX; const auto y = UI_CHARPANEL.Attr.AGL.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3387,7 +3387,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.DEX.iX; const auto y = UI_CHARPANEL.Attr.DEX.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3402,7 +3402,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.STR.iX; const auto y = UI_CHARPANEL.Attr.STR.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3417,7 +3417,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.WIS.iX; const auto y = UI_CHARPANEL.Attr.WIS.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3432,7 +3432,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.MRK.iX; const auto y = UI_CHARPANEL.Attr.MRK.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3447,7 +3447,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.LDR.iX; const auto y = UI_CHARPANEL.Attr.LDR.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3462,7 +3462,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.MEC.iX; const auto y = UI_CHARPANEL.Attr.MEC.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3477,7 +3477,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.EXP.iX; const auto y = UI_CHARPANEL.Attr.EXP.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3492,7 +3492,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.MED.iX; const auto y = UI_CHARPANEL.Attr.MED.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT,0); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; @@ -3507,7 +3507,7 @@ void DisplayCharacterInfo( void ) const auto x = UI_CHARPANEL.Attr.LVL.iX; const auto y = UI_CHARPANEL.Attr.LVL.iY; - ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, pSoldier->stats.bExpLevel); + ubBarWidth = (STAT_WIDTH * (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, &gMercProfiles[pSoldier->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, STAT_WIDTH)); ClipRect.iTop = (y-1); ClipRect.iBottom = (y-1) + STAT_HEIGHT; diff --git a/Tactical/Campaign.cpp b/Tactical/Campaign.cpp index d128fb75..54d1c78c 100644 --- a/Tactical/Campaign.cpp +++ b/Tactical/Campaign.cpp @@ -167,25 +167,14 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh INT8 bCurrentRating; UINT16 *psStatGainPtr; BOOLEAN fAffectedByWisdom = TRUE; - INT8 evolution = NORMAL_EVOLUTION; Assert(pProfile != NULL); - if ( !gGameExternalOptions.bDisableEvolution ) - evolution = pProfile->bEvolution; - - if ( evolution == NO_EVOLUTION ) - return; // No change possible, quit right away - - // if this is a Reverse-Evolving merc who attempting to train - if ( ( ubReason == FROM_TRAINING ) && ( evolution == DEVOLVE ) ) - return; // he doesn't get any benefit, but isn't penalized either - if (usNumChances == 0) return; - usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile->bExpLevel); - usSubpointsPerLevel = SubpointsPerPoint(EXPERAMT, pProfile->bExpLevel); + usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile); + usSubpointsPerLevel = SubpointsPerPoint(EXPERAMT, pProfile); switch (ubStat) { @@ -255,7 +244,6 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh return; } - if (ubReason == FROM_TRAINING) { // training always affected by wisdom @@ -271,7 +259,7 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh // loop once for each chance to improve for (uiCnt = 0; uiCnt < usNumChances; ++uiCnt) { - if ( evolution != DEVOLVE) // Evolves! + if (pProfile->fRegresses == FALSE) // Evolves! { // if this is improving from a failure, and a successful roll would give us enough to go up a point if ((ubReason == FROM_FAILURE) && ((*psStatGainPtr + 1) >= usSubpointsPerPoint)) @@ -302,7 +290,7 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh // if there IS a usChance, adjust it for high or low wisdom (50 is avg) if (usChance > 0 && fAffectedByWisdom) { - usChance += (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile->bExpLevel)) - 50)) / 100; + usChance += (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile)) - 50)) / 100; } // rftr: reduced growth rates at 80+ and 90+ (to make mercs with higher base stats more valuable) @@ -315,14 +303,6 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh usChance = min(gGameExternalOptions.ubMaxGrowthChanceAt80, usChance); } -/* - // if the stat is Marksmanship, and the guy is a hopeless shot - if ((ubStat == MARKAMT) && (pProfile->bSpecialTrait == HOPELESS_SHOT)) - { - usChance /= 5; // MUCH slower to improve, divide usChance by 5 - } -*/ - // SANDRO - penalty for primitive people, they get lesser chance to gain point for certain skills if ( gGameOptions.fNewTraitSystem && (usChance > 10) && (ubStat != EXPERAMT) && (pProfile->bCharacterTrait == CHAR_TRAIT_PRIMITIVE) ) { @@ -338,14 +318,6 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh } } - // Buggler: more evolution rate choices - if ( evolution == THREEQUARTER_EVOLUTION) - usChance = max(1, usChance * 0.75); - else if ( evolution == HALF_EVOLUTION) - usChance = max(1, usChance * 0.5); - else if ( evolution == ONEQUARTER_EVOLUTION) - usChance = max(1, usChance * 0.25); - // maximum possible usChance is 99% if (usChance > 99) { @@ -413,7 +385,7 @@ void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumCh // if there IS a usChance, adjust it for high or low wisdom (50 is avg) if (usChance > 0 && fAffectedByWisdom) { - usChance -= (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile->bExpLevel)) - 50)) / 100; + usChance -= (usChance * (pProfile->bWisdom + (pProfile->sWisdomGain / SubpointsPerPoint(WISDOMAMT, pProfile)) - 50)) / 100; } // if there's ANY usChance, minimum usChance is 1% regardless of wisdom @@ -497,7 +469,7 @@ void ChangeStat( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UINT8 ubSta UINT16 usSubpointsPerPoint; INT8 bDamagedStatToRaise = -1; // added by SANDRO - usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile->bExpLevel ); + usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile ); // build ptrs to appropriate profiletype stat fields switch( ubStat ) @@ -923,7 +895,7 @@ void ProcessUpdateStats( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UIN // set default min & max, subpoints/pt. bMinStatValue = 1; bMaxStatValue = MAX_STAT_VALUE; - usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile->bExpLevel); + usSubpointsPerPoint = SubpointsPerPoint(ubStat, pProfile); // build ptrs to appropriate profiletype stat fields switch( ubStat ) @@ -1166,7 +1138,7 @@ UINT32 RoundOffSalary(UINT32 uiSalary) } -UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel) +UINT16 SubpointsPerPoint(UINT8 ubStat, MERCPROFILESTRUCT* pProfile) { UINT16 usSubpointsPerPoint; @@ -1187,40 +1159,62 @@ UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel) // Attributes case HEALTHAMT: usSubpointsPerPoint = HEALTH_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierLife; + usSubpointsPerPoint = max(usSubpointsPerPoint, HEALTH_SUBPOINTS_TO_IMPROVE/2); break; case AGILAMT: usSubpointsPerPoint = AGILITY_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierAgility; + usSubpointsPerPoint = max(usSubpointsPerPoint, AGILITY_SUBPOINTS_TO_IMPROVE/2); break; case DEXTAMT: usSubpointsPerPoint = DEXTERITY_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierDexterity; + usSubpointsPerPoint = max(usSubpointsPerPoint, DEXTERITY_SUBPOINTS_TO_IMPROVE/2); break; case WISDOMAMT: usSubpointsPerPoint = WISDOM_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierWisdom; + usSubpointsPerPoint = max(usSubpointsPerPoint, WISDOM_SUBPOINTS_TO_IMPROVE/2); break; case STRAMT: usSubpointsPerPoint = STRENGTH_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierStrength; + usSubpointsPerPoint = max(usSubpointsPerPoint, STRENGTH_SUBPOINTS_TO_IMPROVE/2); break; // Skills case MEDICALAMT: usSubpointsPerPoint = MEDICAL_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierMedical; + usSubpointsPerPoint = max(usSubpointsPerPoint, MEDICAL_SUBPOINTS_TO_IMPROVE/2); break; case EXPLODEAMT: usSubpointsPerPoint = EXPLOSIVES_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierExplosive; + usSubpointsPerPoint = max(usSubpointsPerPoint, EXPLOSIVES_SUBPOINTS_TO_IMPROVE/2); break; case MECHANAMT: usSubpointsPerPoint = MECHANICAL_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierMechanical; + usSubpointsPerPoint = max(usSubpointsPerPoint, MECHANICAL_SUBPOINTS_TO_IMPROVE/2); break; case MARKAMT: usSubpointsPerPoint = MARKSMANSHIP_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierMarksmanship; + usSubpointsPerPoint = max(usSubpointsPerPoint, MARKSMANSHIP_SUBPOINTS_TO_IMPROVE/2); break; case LDRAMT: usSubpointsPerPoint = LEADERSHIP_SUBPOINTS_TO_IMPROVE; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierLeadership; + usSubpointsPerPoint = max(usSubpointsPerPoint, LEADERSHIP_SUBPOINTS_TO_IMPROVE/2); break; // Experience case EXPERAMT: - usSubpointsPerPoint = LEVEL_SUBPOINTS_TO_IMPROVE * bExpLevel; + usSubpointsPerPoint = LEVEL_SUBPOINTS_TO_IMPROVE * pProfile->bExpLevel; + if (gGameExternalOptions.fMercGrowthModifiersEnabled) usSubpointsPerPoint += pProfile->bGrowthModifierExpLevel; + usSubpointsPerPoint = max(usSubpointsPerPoint, LEVEL_SUBPOINTS_TO_IMPROVE * pProfile->bExpLevel / 2); break; default: @@ -1797,7 +1791,7 @@ void TestDumpStatChanges(void) // print days served fprintf(FDump, "%3d ", pProfile->usTotalDaysServed); // print evolution type - fprintf(FDump, "%c ", cEvolutionChars[ pProfile->bEvolution ]); + fprintf(FDump, "%c ", cEvolutionChars[ pProfile->fRegresses ]); // now print all non-zero stats for( ubStat = FIRST_CHANGEABLE_STAT; ubStat <= LAST_CHANGEABLE_STAT; ubStat++ ) diff --git a/Tactical/Campaign.h b/Tactical/Campaign.h index a5f54276..7523fb11 100644 --- a/Tactical/Campaign.h +++ b/Tactical/Campaign.h @@ -73,7 +73,7 @@ void ProcessUpdateStats( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier, UIN UINT32 CalcNewSalary(UINT32 uiOldSalary, BOOLEAN fIncrease, UINT32 uiMaxLimit, UINT32 uiIncreaseCap); UINT32 RoundOffSalary(UINT32 uiSalary); -UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel); +UINT16 SubpointsPerPoint(UINT8 ubStat, MERCPROFILESTRUCT* pProfile); void HandleUnhiredMercImprovement( MERCPROFILESTRUCT *pProfile ); void HandleUnhiredMercDeaths( INT32 iProfileID ); @@ -92,4 +92,4 @@ void BuildStatChangeString( STR16 wString, STR16 wName, BOOLEAN fIncrease, INT16 void MERCMercWentUpALevelSendEmail( UINT8 ubMercMercIdValue ); -#endif \ No newline at end of file +#endif diff --git a/Tactical/Interface Panels.cpp b/Tactical/Interface Panels.cpp index e3757a03..4bbbeebd 100644 --- a/Tactical/Interface Panels.cpp +++ b/Tactical/Interface Panels.cpp @@ -2598,7 +2598,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // AGI if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_AGI_Y-1); ClipRect.iBottom = (SM_AGI_Y-1) + SM_STATS_HEIGHT; @@ -2610,7 +2610,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // DEX if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_DEX_Y-1); ClipRect.iBottom = (SM_DEX_Y-1) + SM_STATS_HEIGHT; @@ -2622,7 +2622,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // STR if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_STR_Y-1); ClipRect.iBottom = (SM_STR_Y-1) + SM_STATS_HEIGHT; @@ -2634,7 +2634,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // WIS if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_WIS_Y-1); ClipRect.iBottom = (SM_WIS_Y-1) + SM_STATS_HEIGHT; @@ -2646,7 +2646,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // MRK if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_MRKM_Y-1); ClipRect.iBottom = (SM_MRKM_Y-1) + SM_STATS_HEIGHT; @@ -2658,7 +2658,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // LDR if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_CHAR_Y-1); ClipRect.iBottom = (SM_CHAR_Y-1) + SM_STATS_HEIGHT; @@ -2670,7 +2670,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // MECH if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_MECH_Y-1); ClipRect.iBottom = (SM_MECH_Y-1) + SM_STATS_HEIGHT; @@ -2682,7 +2682,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // EXPLO if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_EXPL_Y-1); ClipRect.iBottom = (SM_EXPL_Y-1) + SM_STATS_HEIGHT; @@ -2694,7 +2694,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // MED if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT,0); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_MED_Y-1); ClipRect.iBottom = (SM_MED_Y-1) + SM_STATS_HEIGHT; @@ -2706,7 +2706,7 @@ void RenderSMPanel( BOOLEAN *pfDirty ) // EXPLEVEL if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain) { - ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, gpSMCurrentMerc->stats.bExpLevel); + ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, &gMercProfiles[gpSMCurrentMerc->ubProfile]); ubBarWidth = __max(0, __min(ubBarWidth, SM_STATS_WIDTH)); ClipRect.iTop = (SM_EXPLVL_Y-1); ClipRect.iBottom = (SM_EXPLVL_Y-1) + SM_STATS_HEIGHT; diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index d6c3738c..9a594ee2 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1339,7 +1339,7 @@ MERCPROFILESTRUCT& MERCPROFILESTRUCT::operator=(const OLD_MERCPROFILESTRUCT_101& this->bSex = src.bSex; this->bArmourAttractiveness = src.bArmourAttractiveness; this->ubMiscFlags2 = src.ubMiscFlags2; - this->bEvolution = src.bEvolution; + this->fRegresses = src.bEvolution == 2; // formerly, 2 == CharacterEvolution::DEVOLVES this->ubMiscFlags = src.ubMiscFlags; this->bSexist = src.bSexist; this->bLearnToHate = src.bLearnToHate; diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index c307da6d..37052fb0 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -98,6 +98,7 @@ extern UINT8 gubItemDroppableFlag[NUM_INV_SLOTS]; //Random Stats RANDOM_STATS_VALUES gRandomStatsValue[NUM_PROFILES]; void RandomStats(); +void RandomGrowthModifiers(); void RandomStartSalary(); //Jenilee @@ -459,6 +460,35 @@ void RandomStats() ExitRandomMercs(); } } +void RandomGrowthModifiers() +{ + UINT32 cnt; + MERCPROFILESTRUCT * pProfile; + BOOLEAN useBellCurve = TRUE; + + if (gGameExternalOptions.fMercRandomGrowthModifiers == TRUE) + { + for (cnt = 0; cnt < NUM_PROFILES; cnt++) + { + pProfile = &(gMercProfiles[cnt]); + + // cap minimum growth modifier to negative half subpoints. this is effectively double speed using default values (subpoints = 50) + // cap maximum growth modifier to 30000. this would make a merc take 600x as long to level up a stat using default values + pProfile->bGrowthModifierExpLevel = RandomAbsoluteRange( pProfile->bGrowthModifierExpLevel, -gGameExternalOptions.usLevelSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierLife = RandomAbsoluteRange( pProfile->bGrowthModifierLife, -gGameExternalOptions.usHealthSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierAgility = RandomAbsoluteRange( pProfile->bGrowthModifierAgility, -gGameExternalOptions.usAgilitySubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierDexterity = RandomAbsoluteRange( pProfile->bGrowthModifierDexterity, -gGameExternalOptions.usDexteritySubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierStrength = RandomAbsoluteRange( pProfile->bGrowthModifierStrength, -gGameExternalOptions.usStrengthSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierLeadership = RandomAbsoluteRange( pProfile->bGrowthModifierLeadership, -gGameExternalOptions.usLeadershipSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierWisdom = RandomAbsoluteRange( pProfile->bGrowthModifierWisdom, -gGameExternalOptions.usWisdomSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierMarksmanship = RandomAbsoluteRange( pProfile->bGrowthModifierMarksmanship, -gGameExternalOptions.usMarksmanshipSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierMechanical = RandomAbsoluteRange( pProfile->bGrowthModifierMechanical, -gGameExternalOptions.usMechanicalSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierExplosive = RandomAbsoluteRange( pProfile->bGrowthModifierExplosive, -gGameExternalOptions.usExplosivesSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + pProfile->bGrowthModifierMedical = RandomAbsoluteRange( pProfile->bGrowthModifierMedical, -gGameExternalOptions.usMedicalSubpointsToImprove/2, 30000, gGameExternalOptions.iMercRandomGrowthModifiersRange, useBellCurve ); + } + } +} + void RandomStartSalary() { UINT32 cnt; @@ -996,6 +1026,8 @@ for( int i = 0; i < NUM_PROFILES; i++ ) // --------------- RandomStats (); //random stats by Jazz + + RandomGrowthModifiers(); // Buggler: random starting salary RandomStartSalary (); @@ -2522,7 +2554,7 @@ void OverwriteMercProfileWithXMLData( UINT32 uiLoop ) gMercProfiles[ uiLoop ].bMechanical = tempProfiles[ uiLoop ].bMechanical ; gMercProfiles[ uiLoop ].bExpLevel = tempProfiles[ uiLoop ].bExpLevel ; - gMercProfiles[ uiLoop ].bEvolution = tempProfiles[ uiLoop ].bEvolution ; + gMercProfiles[uiLoop].fRegresses = tempProfiles[ uiLoop ].fRegresses; ////////////////////////////////////////////////////////////////////////////////////// // SANDRO - Check old/new traits and repair possible errors if (gGameOptions.fNewTraitSystem) @@ -2637,6 +2669,19 @@ void OverwriteMercProfileWithXMLData( UINT32 uiLoop ) gMercProfiles[ uiLoop ].usVoiceIndex = tempProfiles[uiLoop].usVoiceIndex; gMercProfiles[ uiLoop ].Type = tempProfiles[uiLoop].Type; + gMercProfiles[uiLoop].fRegresses = tempProfiles[uiLoop].fRegresses; + gMercProfiles[uiLoop].bGrowthModifierLife = tempProfiles[uiLoop].bGrowthModifierLife; + gMercProfiles[uiLoop].bGrowthModifierStrength = tempProfiles[uiLoop].bGrowthModifierStrength; + gMercProfiles[uiLoop].bGrowthModifierAgility = tempProfiles[uiLoop].bGrowthModifierAgility; + gMercProfiles[uiLoop].bGrowthModifierDexterity = tempProfiles[uiLoop].bGrowthModifierDexterity; + gMercProfiles[uiLoop].bGrowthModifierWisdom = tempProfiles[uiLoop].bGrowthModifierWisdom; + gMercProfiles[uiLoop].bGrowthModifierMarksmanship = tempProfiles[uiLoop].bGrowthModifierMarksmanship; + gMercProfiles[uiLoop].bGrowthModifierExplosive = tempProfiles[uiLoop].bGrowthModifierExplosive; + gMercProfiles[uiLoop].bGrowthModifierLeadership = tempProfiles[uiLoop].bGrowthModifierLeadership; + gMercProfiles[uiLoop].bGrowthModifierMedical = tempProfiles[uiLoop].bGrowthModifierMedical; + gMercProfiles[uiLoop].bGrowthModifierMechanical = tempProfiles[uiLoop].bGrowthModifierMechanical; + gMercProfiles[uiLoop].bGrowthModifierExpLevel = tempProfiles[uiLoop].bGrowthModifierExpLevel; + gProfileType[uiLoop] = gMercProfiles[uiLoop].Type; switch ( tempProfiles[uiLoop].Type ) diff --git a/Tactical/Soldier Profile.h b/Tactical/Soldier Profile.h index 9eef6079..39e0860e 100644 --- a/Tactical/Soldier Profile.h +++ b/Tactical/Soldier Profile.h @@ -314,7 +314,18 @@ typedef struct INT8 bExpLevel; - INT8 bEvolution; + BOOLEAN fRegresses; + INT16 bGrowthModifierLife; + INT16 bGrowthModifierStrength; + INT16 bGrowthModifierAgility; + INT16 bGrowthModifierDexterity; + INT16 bGrowthModifierWisdom; + INT16 bGrowthModifierMarksmanship; + INT16 bGrowthModifierExplosive; + INT16 bGrowthModifierLeadership; + INT16 bGrowthModifierMedical; + INT16 bGrowthModifierMechanical; + INT16 bGrowthModifierExpLevel; // changed by SANDRO INT8 bOldSkillTrait; INT8 bOldSkillTrait2; diff --git a/Tactical/XML_Profiles.cpp b/Tactical/XML_Profiles.cpp index ba3aafbb..380fffb1 100644 --- a/Tactical/XML_Profiles.cpp +++ b/Tactical/XML_Profiles.cpp @@ -101,7 +101,19 @@ profileStartElementHandle(void *userData, const XML_Char *name, const XML_Char * strcmp(name, "bMedical") == 0 || strcmp(name, "bMechanical") == 0 || strcmp(name, "bExpLevel") == 0 || - strcmp(name, "bEvolution") == 0 || + strcmp(name, "fRegresses") == 0 || + // rftr: growth rates are intended to replace the tag, letting each stat have its own growth modifier + strcmp(name, "bGrowthModifierLife") == 0 || + strcmp(name, "bGrowthModifierStrength") == 0 || + strcmp(name, "bGrowthModifierAgility") == 0 || + strcmp(name, "bGrowthModifierDexterity") == 0 || + strcmp(name, "bGrowthModifierWisdom") == 0 || + strcmp(name, "bGrowthModifierMarksmanship") == 0 || + strcmp(name, "bGrowthModifierExplosive") == 0 || + strcmp(name, "bGrowthModifierLeadership") == 0 || + strcmp(name, "bGrowthModifierMedical") == 0 || + strcmp(name, "bGrowthModifierMechanical") == 0 || + strcmp(name, "bGrowthModifierExpLevel") == 0 || // added by SANDRO strcmp(name, "bOldSkillTrait") == 0 || strcmp(name, "bOldSkillTrait2") == 0 || @@ -280,7 +292,18 @@ profileEndElementHandle(void *userData, const XML_Char *name) tempProfiles[pData->curIndex].bMechanical = pData->curProfile.bMechanical; tempProfiles[pData->curIndex].bExpLevel = pData->curProfile.bExpLevel; - tempProfiles[pData->curIndex].bEvolution = pData->curProfile.bEvolution; + tempProfiles[pData->curIndex].fRegresses = pData->curProfile.fRegresses; + tempProfiles[pData->curIndex].bGrowthModifierLife = pData->curProfile.bGrowthModifierLife; + tempProfiles[pData->curIndex].bGrowthModifierStrength = pData->curProfile.bGrowthModifierStrength; + tempProfiles[pData->curIndex].bGrowthModifierAgility = pData->curProfile.bGrowthModifierAgility; + tempProfiles[pData->curIndex].bGrowthModifierDexterity = pData->curProfile.bGrowthModifierDexterity; + tempProfiles[pData->curIndex].bGrowthModifierWisdom = pData->curProfile.bGrowthModifierWisdom; + tempProfiles[pData->curIndex].bGrowthModifierMarksmanship = pData->curProfile.bGrowthModifierMarksmanship; + tempProfiles[pData->curIndex].bGrowthModifierExplosive = pData->curProfile.bGrowthModifierExplosive; + tempProfiles[pData->curIndex].bGrowthModifierLeadership = pData->curProfile.bGrowthModifierLeadership; + tempProfiles[pData->curIndex].bGrowthModifierMedical = pData->curProfile.bGrowthModifierMedical; + tempProfiles[pData->curIndex].bGrowthModifierMechanical = pData->curProfile.bGrowthModifierMechanical; + tempProfiles[pData->curIndex].bGrowthModifierExpLevel = pData->curProfile.bGrowthModifierExpLevel; // added by SANDRO tempProfiles[pData->curIndex].bOldSkillTrait = pData->curProfile.bOldSkillTrait; tempProfiles[pData->curIndex].bOldSkillTrait2 = pData->curProfile.bOldSkillTrait2; @@ -586,11 +609,70 @@ profileEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curProfile.bExpLevel = (UINT32) strtoul(pData->szCharData, NULL, 0); } - - else if(strcmp(name, "bEvolution") == 0) + + else if(strcmp(name, "fRegresses") == 0) { pData->curElement = ELEMENT; - pData->curProfile.bEvolution = (UINT32) strtoul(pData->szCharData, NULL, 0); + pData->curProfile.fRegresses = (BOOLEAN) strtoul(pData->szCharData, NULL, 0); + } + + else if (strncmp(name, "bGrowthModifier", 11) == 0) // doing this to avoid C1061 + { + if (strcmp(name, "bGrowthModifierLife") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierLife = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierStrength") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierStrength = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierAgility") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierAgility = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierDexterity") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierDexterity = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierWisdom") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierWisdom = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierMarksmanship") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierMarksmanship = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierExplosive") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierExplosive = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierLeadership") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierLeadership = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierMedical") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierMedical = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierMechanical") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierMechanical = (UINT32)strtoul(pData->szCharData, NULL, 0); + } + else if(strcmp(name, "bGrowthModifierExpLevel") == 0) + { + pData->curElement = ELEMENT; + pData->curProfile.bGrowthModifierExpLevel = (UINT32)strtoul(pData->szCharData, NULL, 0); + } } //////////////////////////////////////////////////////////////////////////// // SANDRO was here - messed this a bit @@ -1600,7 +1682,7 @@ BOOLEAN WriteMercProfiles() FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].bMedical); FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].bMechanical); FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].bExpLevel); - FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].bEvolution); + FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].fRegresses); //////////////////////////////////////////////////////////////////////////////////////////// // SANDRO - old/new traits if (gGameOptions.fNewTraitSystem) diff --git a/Tactical/soldier profile type.h b/Tactical/soldier profile type.h index a85653ea..8d427a5b 100644 --- a/Tactical/soldier profile type.h +++ b/Tactical/soldier profile type.h @@ -402,18 +402,7 @@ typedef enum NUM_SEXIST } SexistLevels; - - -// training defines for evolution, no stat increase, stat decrease( de-evolve ) -typedef enum -{ - NORMAL_EVOLUTION =0, - NO_EVOLUTION, - DEVOLVE, - THREEQUARTER_EVOLUTION, - HALF_EVOLUTION, - ONEQUARTER_EVOLUTION, -} CharacterEvolution; +// rftr: removed the CharacterEvolution enum as it was replaced by growth modifiers #define BUDDY_MERC( prof, bud ) ((prof)->bBuddy[0] == (bud) || (prof)->bBuddy[1] == (bud) || (prof)->bBuddy[2] == (bud) || (prof)->bBuddy[3] == (bud) || (prof)->bBuddy[4] == (bud) || ( (prof)->bLearnToLike == (bud) && (prof)->bLearnToLikeCount == 0 ) ) #define HATED_MERC( prof, hat ) ((prof)->bHated[0] == (hat) || (prof)->bHated[1] == (hat) || (prof)->bHated[2] == (hat) || (prof)->bHated[3] == (hat) || (prof)->bHated[4] == (hat) || ( (prof)->bLearnToHate == (hat) && (prof)->bLearnToHateCount == 0 ) ) @@ -789,7 +778,7 @@ public: INT8 bSex; INT8 bArmourAttractiveness; UINT8 ubMiscFlags2; - INT8 bEvolution; + BOOLEAN fRegresses; UINT8 ubMiscFlags; UINT8 bSexist; UINT8 bLearnToHate; @@ -1009,6 +998,19 @@ public: // Flugente: type of profile UINT32 Type; + + // rftr: growth modifiers - ignored if fRegresses is TRUE + INT16 bGrowthModifierLife; + INT16 bGrowthModifierStrength; + INT16 bGrowthModifierAgility; + INT16 bGrowthModifierDexterity; + INT16 bGrowthModifierWisdom; + INT16 bGrowthModifierMarksmanship; + INT16 bGrowthModifierExplosive; + INT16 bGrowthModifierLeadership; + INT16 bGrowthModifierMedical; + INT16 bGrowthModifierMechanical; + INT16 bGrowthModifierExpLevel; }; // MERCPROFILESTRUCT; // WANNE - BMP: DONE! diff --git a/TacticalAI/NPC.cpp b/TacticalAI/NPC.cpp index cf8d86c4..55606e27 100644 --- a/TacticalAI/NPC.cpp +++ b/TacticalAI/NPC.cpp @@ -808,7 +808,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt if ( apStr ) { - swprintf( atStr, szLaptopStatText[0], threateneffectiveness ); + swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_THREATEN_EFFECTIVENESS], threateneffectiveness ); wcscat( apStr, atStr ); } @@ -818,7 +818,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt { if ( apStr ) { - swprintf( atStr, szLaptopStatText[1], gMercProfiles[usProfile].bLeadership ); + swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_LEADERSHIP], gMercProfiles[usProfile].bLeadership ); wcscat( apStr, atStr ); } @@ -829,7 +829,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt if ( apStr ) { - swprintf( atStr, szLaptopStatText[2], approachfactor ); + swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_APPROACH_MODIFIER], approachfactor ); wcscat( apStr, atStr ); } @@ -855,7 +855,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt if ( apStr ) { - swprintf( atStr, szLaptopStatText[3], bgmodifier ); + swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_BACKGROUND_MODIFIER], bgmodifier ); wcscat( apStr, atStr ); } @@ -868,7 +868,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt swprintf( atStr, L" \n" ); wcscat( apStr, atStr ); - swprintf( atStr, szLaptopStatText[4] ); + swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_ASSERTIVE] ); wcscat( apStr, atStr ); } else if ( DoesMercHavePersonality( pSoldier, CHAR_TRAIT_MALICIOUS ) ) @@ -876,7 +876,7 @@ INT32 GetEffectiveApproachValue( UINT8 usProfile, UINT8 usApproach, CHAR16* apSt swprintf( atStr, L" \n" ); wcscat( apStr, atStr ); - swprintf( atStr, szLaptopStatText[5] ); + swprintf( atStr, szLaptopStatText[LAPTOP_STAT_TEXT_MALICIOUS] ); wcscat( apStr, atStr ); } } diff --git a/Utils/Text.h b/Utils/Text.h index 21037737..e2c3251c 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -3084,6 +3084,36 @@ extern STR16 szSMilitiaResourceText[]; extern STR16 szInteractiveActionText[]; extern STR16 szLaptopStatText[]; +enum +{ + LAPTOP_STAT_TEXT_THREATEN_EFFECTIVENESS, + LAPTOP_STAT_TEXT_LEADERSHIP, + LAPTOP_STAT_TEXT_APPROACH_MODIFIER, + LAPTOP_STAT_TEXT_BACKGROUND_MODIFIER, + LAPTOP_STAT_TEXT_ASSERTIVE, + LAPTOP_STAT_TEXT_MALICIOUS, + LAPTOP_STAT_TEXT_GOOD_GUY, + LAPTOP_STAT_TEXT_REFUSES_TO_ATTACK_NON_HOSTILES, + LAPTOP_STAT_TEXT_FRIENDLY_APPROACH, + LAPTOP_STAT_TEXT_DIRECT_APPROACH, + LAPTOP_STAT_TEXT_THREATEN_APPROACH, + LAPTOP_STAT_TEXT_RECRUIT_APPROACH, + LAPTOP_STAT_TEXT_MERC_REGRESSES, + LAPTOP_STAT_TEXT_FAST, + LAPTOP_STAT_TEXT_AVERAGE, + LAPTOP_STAT_TEXT_SLOW, + LAPTOP_STAT_TEXT_HEALTH_SPEED, + LAPTOP_STAT_TEXT_STRENGTH_SPEED, + LAPTOP_STAT_TEXT_AGILITY_SPEED, + LAPTOP_STAT_TEXT_DEXTERITY_SPEED, + LAPTOP_STAT_TEXT_WISDOM_SPEED, + LAPTOP_STAT_TEXT_MARKSMANSHIP_SPEED, + LAPTOP_STAT_TEXT_EXPLOSIVES_SPEED, + LAPTOP_STAT_TEXT_LEADERSHIP_SPEED, + LAPTOP_STAT_TEXT_MEDICAL_SPEED, + LAPTOP_STAT_TEXT_MECHANICAL_SPEED, + LAPTOP_STAT_TEXT_EXPERIENCE_SPEED, +}; // Flugente: gear templates extern STR16 szGearTemplateText[]; diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 2a943df5..e587df2d 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -11655,13 +11655,21 @@ STR16 szLaptopStatText[] = L"威胁对话", //L"Threaten approach", L"招募对话", //L"Recruit approach", - L"%s正以正常速度学习。", //L"%s learns with normal speed.", - L"%s根本没有在学习。", //L"%s does not learn at all.", - L"%s遗忘了技能。", //L"%s unlearns his skills.", - L"%s正以3/4的速度学习。", //L"%s learns with 3/4 speed.", - - L"%s正以1/2的速度学习。", //L"%s learns with 1/2 speed.", - L"%s正以1/4的速度学习。", //L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; STR16 szGearTemplateText[] = diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 00abf9fc..4c56a70b 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -11664,13 +11664,21 @@ STR16 szLaptopStatText[] = // TODO.Translate L"Threaten approach", L"Recruit approach", - L"%s learns with normal speed.", // TODO.Translate - L"%s does not learn at all.", - L"%s unlearns his skills.", - L"%s learns with 3/4 speed.", - - L"%s learns with 1/2 speed.", - L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; STR16 szGearTemplateText[] = // TODO.Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 5f4b9f5e..d2684b28 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -11655,13 +11655,21 @@ STR16 szLaptopStatText[] = L"Threaten approach", L"Recruit approach", - L"%s learns with normal speed.", - L"%s does not learn at all.", - L"%s unlearns his skills.", - L"%s learns with 3/4 speed.", - - L"%s learns with 1/2 speed.", - L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; STR16 szGearTemplateText[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index f97f68de..77fc295f 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -11646,13 +11646,21 @@ STR16 szLaptopStatText[] = // TODO.Translate L"Threaten approach", L"Recruit approach", - L"%s learns with normal speed.", // TODO.Translate - L"%s does not learn at all.", - L"%s unlearns his skills.", - L"%s learns with 3/4 speed.", - - L"%s learns with 1/2 speed.", - L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; STR16 szGearTemplateText[] = // TODO.Translate diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 0e86f7f6..62bc2deb 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -11560,13 +11560,21 @@ STR16 szLaptopStatText[] = L"Threaten approach", L"Recruit approach", - L"%s learns with normal speed.", // TODO.Translate - L"%s does not learn at all.", - L"%s unlearns his skills.", - L"%s learns with 3/4 speed.", - - L"%s learns with 1/2 speed.", - L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; // TODO.Translate diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 272ff9da..1968ae29 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -11655,13 +11655,21 @@ STR16 szLaptopStatText[] = // TODO.Translate L"Threaten approach", L"Recruit approach", - L"%s learns with normal speed.", // TODO.Translate - L"%s does not learn at all.", - L"%s unlearns his skills.", - L"%s learns with 3/4 speed.", - - L"%s learns with 1/2 speed.", - L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; STR16 szGearTemplateText[] = // TODO.Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 35548ba1..379f3f5a 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -11668,13 +11668,21 @@ STR16 szLaptopStatText[] = // TODO.Translate L"Threaten approach", L"Recruit approach", - L"%s learns with normal speed.", // TODO.Translate - L"%s does not learn at all.", - L"%s unlearns his skills.", - L"%s learns with 3/4 speed.", - - L"%s learns with 1/2 speed.", - L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; STR16 szGearTemplateText[] = // TODO.Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 0345b830..9b9b99e2 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -11650,13 +11650,21 @@ STR16 szLaptopStatText[] = // TODO.Translate L"Threaten approach", L"Recruit approach", - L"%s learns with normal speed.", // TODO.Translate - L"%s does not learn at all.", - L"%s unlearns his skills.", - L"%s learns with 3/4 speed.", - - L"%s learns with 1/2 speed.", - L"%s learns with 1/4 speed.", + L"Stats will regress.", + L"Fast", + L"Average", + L"Slow", + L"Health growth", + L"Strength growth", + L"Agility growth", + L"Dexterity growth", + L"Wisdom growth", + L"Marksmanship growth", + L"Explosives growth", + L"Leadership growth", + L"Medical growth", + L"Mechanical growth", + L"Experience growth", }; STR16 szGearTemplateText[] = // TODO.Translate