diff --git a/GameSettings.cpp b/GameSettings.cpp index 27237afa..aa657d7d 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -1246,6 +1246,10 @@ void LoadGameExternalOptions() //Enemy Rank by Jazz gGameExternalOptions.fEnemyRank = iniReader.ReadBoolean("Tactical Gameplay Settings","INDIVIDUAL_ENEMY_RANK",FALSE); + // Flugente: soldier profiles + gGameExternalOptions.fSoldierProfiles_Enemy = iniReader.ReadBoolean("Tactical Gameplay Settings", "SOLDIER_PROFILES_ENEMY", TRUE); + gGameExternalOptions.fSoldierProfiles_Militia = iniReader.ReadBoolean("Tactical Gameplay Settings", "SOLDIER_PROFILES_MILITIA", TRUE); + // *** ddd - BEGIN gGameExternalOptions.fExtMouseKeyEnabled = iniReader.ReadBoolean("Tactical Interface Settings", "ENABLE_EXT_MOUSE_KEYS", FALSE); diff --git a/GameSettings.h b/GameSettings.h index 7364b824..a50a1f19 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -1138,6 +1138,10 @@ typedef struct //Enemy Rank Legion 2 by Jazz BOOLEAN fEnemyRank; + + // Flugente: soldier profiles + BOOLEAN fSoldierProfiles_Enemy; + BOOLEAN fSoldierProfiles_Militia; BOOLEAN fShowCamouflageFaces; diff --git a/GameVersion.h b/GameVersion.h index 4ba87f75..356eb1f5 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 SOLDIER_PROFILES 143 // Flugente: profiles for enemy and militia (possibly any non-NPC/RPC character) #define DYNAMIC_FLASHLIGHTS 142 // Flugente: had to add variables to LIGHTEFFECT-struct #define ENLARGED_OPINIONS 141 // Flugente: increased numberof merc opinions to 255, thus need to change savegame reading #define MODULARIZED_AI 140 // Flugente: new savegame version due to modularized AI @@ -61,7 +62,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 DYNAMIC_FLASHLIGHTS +#define SAVE_GAME_VERSION SOLDIER_PROFILES //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Init.cpp b/Init.cpp index d608f425..ec42ce7a 100644 --- a/Init.cpp +++ b/Init.cpp @@ -1011,6 +1011,43 @@ BOOLEAN LoadExternalGameplayData(STR directoryName) } #endif + // Flugente: soldier profiles + strcpy(fileName, directoryName); + strcat(fileName, ENEMY_ADMIN_PROFILE_FILENAME); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); + SGP_THROW_IFFALSE(ReadInSoldierProfiles(zSoldierProfile[0], fileName), ENEMY_ADMIN_PROFILE_FILENAME); + num_found_soldier_profiles[0] = num_found_profiles; + + strcpy(fileName, directoryName); + strcat(fileName, ENEMY_REGULAR_PROFILE_FILENAME); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); + SGP_THROW_IFFALSE(ReadInSoldierProfiles(zSoldierProfile[1], fileName), ENEMY_REGULAR_PROFILE_FILENAME); + num_found_soldier_profiles[1] = num_found_profiles; + + strcpy(fileName, directoryName); + strcat(fileName, ENEMY_ELITE_PROFILE_FILENAME); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); + SGP_THROW_IFFALSE(ReadInSoldierProfiles(zSoldierProfile[2], fileName), ENEMY_ELITE_PROFILE_FILENAME); + num_found_soldier_profiles[2] = num_found_profiles; + + strcpy(fileName, directoryName); + strcat(fileName, MILITIA_GREEN_PROFILE_FILENAME); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); + SGP_THROW_IFFALSE(ReadInSoldierProfiles(zSoldierProfile[3], fileName), MILITIA_GREEN_PROFILE_FILENAME); + num_found_soldier_profiles[3] = num_found_profiles; + + strcpy(fileName, directoryName); + strcat(fileName, MILITIA_REGULAR_PROFILE_FILENAME); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); + SGP_THROW_IFFALSE(ReadInSoldierProfiles(zSoldierProfile[4], fileName), MILITIA_REGULAR_PROFILE_FILENAME); + num_found_soldier_profiles[4] = num_found_profiles; + + strcpy(fileName, directoryName); + strcat(fileName, MILITIA_VETERAN_PROFILE_FILENAME); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); + SGP_THROW_IFFALSE(ReadInSoldierProfiles(zSoldierProfile[5], fileName), MILITIA_VETERAN_PROFILE_FILENAME); + num_found_soldier_profiles[5] = num_found_profiles; + LoadIMPPortraitsTEMP(); //Sound profile by jazz diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 1cb80b71..f8f120a3 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -2042,7 +2042,23 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) numBytesRead = ReadFieldByField(hFile, &this->usMultiTurnAction, sizeof(usMultiTurnAction), sizeof(UINT8), numBytesRead); numBytesRead = ReadFieldByField(hFile, &this->bAIIndex, sizeof(bAIIndex), sizeof(UINT16), numBytesRead); - numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead); + if ( guiCurrentSaveGameVersion >= SOLDIER_PROFILES ) + { + numBytesRead = ReadFieldByField(hFile, &this->usSoldierProfile, sizeof(usSoldierProfile), sizeof(UINT16), numBytesRead); + + numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead); + } + else + { + this->usSoldierProfile = 0; + + // as we added new variables, fillersize was reduced, here we account for that. We have to also read the existing fillers that now do not exist anymore + const UINT8 tmp = sizeof(usSoldierProfile); + UINT8 blarg[tmp]; + numBytesRead = ReadFieldByField(hFile, &blarg, tmp, sizeof(UINT8), numBytesRead); + + numBytesRead = ReadFieldByField(hFile, &this->ubFiller, sizeof(ubFiller), sizeof(UINT8), numBytesRead); + } } else { @@ -2050,9 +2066,11 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) this->sMTActionGridNo = NOWHERE; this->usMultiTurnAction = 0; this->bAIIndex = 0; + this->usSoldierProfile = 0; // as we added new variables, fillersize was reduced, here we account for that. We have to also read the existing fillers that now do not exist anymore - const UINT8 tmp = sizeof(bOverTurnAPS) + sizeof(this->sMTActionGridNo) + sizeof(usMultiTurnAction); + // +1 for padding + const UINT8 tmp = sizeof(bOverTurnAPS) + sizeof(this->sMTActionGridNo) + sizeof(usMultiTurnAction) + sizeof(bAIIndex) + 1 + sizeof(usSoldierProfile); UINT8 blarg[tmp]; numBytesRead = ReadFieldByField(hFile, &blarg, tmp, sizeof(UINT8), numBytesRead); @@ -2082,6 +2100,31 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile) while((buffer%4) > 0) buffer++; + for(int i = 0; i < sizeof(bOverTurnAPS); ++i) + buffer++; + while((buffer%4) > 0) + buffer++; + + for(int i = 0; i < sizeof(sMTActionGridNo); ++i) + buffer++; + while((buffer%4) > 0) + buffer++; + + for(int i = 0; i < sizeof(usMultiTurnAction); ++i) + buffer++; + while((buffer%4) > 0) + buffer++; + + for(int i = 0; i < sizeof(bAIIndex); ++i) + buffer++; + while((buffer%4) > 0) + buffer++; + + for(int i = 0; i < sizeof(usSoldierProfile); ++i) + buffer++; + while((buffer%4) > 0) + buffer++; + for(int i = 0; i < sizeof(ubFiller); ++i) buffer++; while((buffer%4) > 0) diff --git a/Tactical/Interface.cpp b/Tactical/Interface.cpp index 9da4da6a..ab4836c1 100644 --- a/Tactical/Interface.cpp +++ b/Tactical/Interface.cpp @@ -100,9 +100,13 @@ int INV_INTERFACE_START_Y;// = ( SCREEN_HEIGHT - INV_INTERFACE_HEIGHT ); HIDDEN_NAMES_VALUES zHiddenNames[500]; //legion2 Jazz ENEMY_NAMES_VALUES zEnemyName[500]; -ENEMY_RANK_VALUES zEnemyRank[20]; // Flugente: set this to 20, which should be way enough, as there are onyl 10 exp levels +ENEMY_RANK_VALUES zEnemyRank[20]; // Flugente: set this to 20, which should be way enough, as there are only 10 exp levels CIV_NAMES_VALUES zCivGroupName[NUM_CIV_GROUPS]; +// Flugente: soldier profiles +SOLDIER_PROFILE_VALUES zSoldierProfile[6][NUM_SOLDIER_PROFILES]; +UINT16 num_found_soldier_profiles[6]; // the correct number is set on reading the xml + BOOLEAN gfInMovementMenu = FALSE; INT32 giMenuAnchorX, giMenuAnchorY; @@ -2058,7 +2062,20 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) { if ( pSoldier->bTeam == ENEMY_TEAM ) { - if (gGameExternalOptions.fEnemyNames == TRUE && gGameExternalOptions.fEnemyRank == FALSE) + // Flugente: soldier profiles + if ( gGameExternalOptions.fSoldierProfiles_Enemy && pSoldier->usSoldierProfile ) + { + swprintf(NameStr, pSoldier->GetName()); + + SetFont( TINYFONT1 ); + SetFontBackground( FONT_MCOLOR_BLACK ); + SetFontForeground( FONT_YELLOW ); + + FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY ); + gprintfdirty( sX, sY, NameStr ); + mprintf( sX, sY, NameStr ); + } + else if (gGameExternalOptions.fEnemyNames == TRUE && gGameExternalOptions.fEnemyRank == FALSE) { for( iCounter2 = 0; iCounter2 < 500; ++iCounter2 ) { @@ -2107,6 +2124,20 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) } } } + // Flugente: soldier profiles + else if ( pSoldier->bTeam == MILITIA_TEAM && gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile ) + { + // get a proper chaos name + swprintf(NameStr, pSoldier->GetName()); + + SetFont( TINYFONT1 ); + SetFontBackground( FONT_MCOLOR_BLACK ); + SetFontForeground( FONT_YELLOW ); + + FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY ); + gprintfdirty( sX, sY, NameStr ); + mprintf( sX, sY, NameStr ); + } else if (gGameExternalOptions.fCivGroupName == TRUE && pSoldier->ubCivilianGroup > 0 ) { if (zCivGroupName[pSoldier->ubCivilianGroup].Enabled == 1) @@ -2181,7 +2212,21 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) #endif if ( pSoldier->bTeam == ENEMY_TEAM ) { - if (gGameExternalOptions.fEnemyNames == TRUE && gGameExternalOptions.fEnemyRank == FALSE) + // Flugente: soldier profiles + if ( gGameExternalOptions.fSoldierProfiles_Enemy && pSoldier->usSoldierProfile ) + { + // get a proper chaos name + swprintf(NameStr, pSoldier->GetName()); + + SetFont( TINYFONT1 ); + SetFontBackground( FONT_MCOLOR_BLACK ); + SetFontForeground( FONT_YELLOW ); + + FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY ); + gprintfdirty( sX, sY, NameStr ); + mprintf( sX, sY, NameStr ); + } + else if (gGameExternalOptions.fEnemyNames == TRUE && gGameExternalOptions.fEnemyRank == FALSE) { for( iCounter2 = 0; iCounter2 < 500; ++iCounter2 ) { @@ -2230,6 +2275,20 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID ) } } } + // Flugente: soldier profiles + else if ( pSoldier->bTeam == MILITIA_TEAM && gGameExternalOptions.fSoldierProfiles_Militia && pSoldier->usSoldierProfile ) + { + // get a proper chaos name + swprintf(NameStr, pSoldier->GetName()); + + SetFont( TINYFONT1 ); + SetFontBackground( FONT_MCOLOR_BLACK ); + SetFontForeground( FONT_YELLOW ); + + FindFontCenterCoordinates( sXPos, (INT16)( sYPos + 20 ), (INT16)(80 ), 1, NameStr, TINYFONT1, &sX, &sY ); + gprintfdirty( sX, sY, NameStr ); + mprintf( sX, sY, NameStr ); + } else if (gGameExternalOptions.fCivGroupName == TRUE && pSoldier->ubCivilianGroup > 0 ) { if (zCivGroupName[pSoldier->ubCivilianGroup].Enabled == 1) diff --git a/Tactical/Interface.h b/Tactical/Interface.h index 8178761e..36063cbc 100644 --- a/Tactical/Interface.h +++ b/Tactical/Interface.h @@ -87,6 +87,25 @@ typedef struct extern CIV_NAMES_VALUES zCivGroupName[NUM_CIV_GROUPS]; +// Flugente: soldier profiles +typedef struct +{ + UINT16 uiIndex; + CHAR16 szName[MAX_ENEMY_NAMES_CHARS]; + UINT8 uiBodyType; + UINT8 uiHair; + UINT8 uiSkin; + UINT8 uiTrait[3]; + UINT32 uiFlags; +} SOLDIER_PROFILE_VALUES; + +#define NUM_SOLDIER_PROFILES 100 + +extern SOLDIER_PROFILE_VALUES zSoldierProfile[6][NUM_SOLDIER_PROFILES]; + +extern UINT16 num_found_soldier_profiles[6]; // the correct number is set on reading the xml +extern UINT16 num_found_profiles; // a helper variable during reading xmls + extern int INTERFACE_WIDTH; // 640 extern int INTERFACE_HEIGHT; // 120 extern int INV_INTERFACE_HEIGHT; // 140 diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index adcfdf9a..645e45fe 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -10151,3 +10151,41 @@ BOOLEAN AllowedToStealFromTeamMate( UINT8 ubID, UINT8 ubTargetID ) return FALSE; } + +// Flugente: is a soldier profile already used? +BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr) +{ + if ( aType < 0 || aType > 5 ) + return FALSE; + + UINT8 searchedclass = SOLDIER_CLASS_ADMINISTRATOR; + switch( aType ) + { + case 1: + searchedclass = SOLDIER_CLASS_ARMY; + break; + case 2: + searchedclass = SOLDIER_CLASS_ELITE; + break; + case 3: + searchedclass = SOLDIER_CLASS_GREEN_MILITIA; + break; + case 4: + searchedclass = SOLDIER_CLASS_REG_MILITIA; + break; + case 5: + searchedclass = SOLDIER_CLASS_ELITE_MILITIA; + break; + } + + SOLDIERTYPE* pSoldier = NULL; + for( INT32 i = gTacticalStatus.Team[ usTeam ].bFirstID; i <= gTacticalStatus.Team[ usTeam ].bLastID; ++i ) + { + pSoldier = MercPtrs[ i ]; + + if ( pSoldier && pSoldier->ubSoldierClass == searchedclass && pSoldier->usSoldierProfile == aNr ) + return TRUE; + } + + return FALSE; +} diff --git a/Tactical/Overhead.h b/Tactical/Overhead.h index 0a1d98c8..0f9606a8 100644 --- a/Tactical/Overhead.h +++ b/Tactical/Overhead.h @@ -361,5 +361,8 @@ void TeamDropAll(UINT8 bTeam, BOOLEAN fForce = FALSE); // are we allowed to steal access this guy's inventory? BOOLEAN AllowedToStealFromTeamMate( UINT8 aAccessorID, UINT8 aTargetID ); +// Flugente: is an soldier profile already used? +BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr); + #endif diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index c5d819b9..7cb6aef2 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1020,6 +1020,7 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src) this->usStarveDamageHealth = 0; this->usStarveDamageStrength = 0; this->bAIIndex = 0; + this->usSoldierProfile = 0; } return *this; } @@ -16074,6 +16075,13 @@ STR16 SOLDIERTYPE::GetName() tmpname[tmpuser][0] = '\0' ; wcscat( tmpname[tmpuser], this->name ); + if ( this->usSoldierProfile ) + { + INT8 type = this->GetSoldierProfileType(this->bTeam); + if ( type > -1 ) + wcscpy( tmpname[tmpuser], zSoldierProfile[type][this->usSoldierProfile].szName ); + } + return tmpname[tmpuser]; } @@ -16414,6 +16422,46 @@ UINT8 SOLDIERTYPE::GetBestEquippedFlashLightRange() return( bestrange ); } +// Flugente: soldier profiles +// retrieves the correct sub-array +INT8 SOLDIERTYPE::GetSoldierProfileType(UINT8 usTeam) +{ + INT8 type = -1; + + if ( usTeam == ENEMY_TEAM && gGameExternalOptions.fSoldierProfiles_Enemy ) + { + switch( this->ubSoldierClass ) + { + case SOLDIER_CLASS_ELITE : + type = 2; + break; + case SOLDIER_CLASS_ARMY : + type = 1; + break; + case SOLDIER_CLASS_ADMINISTRATOR : + type = 0; + break; + } + } + else if ( usTeam == ENEMY_TEAM && gGameExternalOptions.fSoldierProfiles_Enemy ) + { + switch( this->ubSoldierClass ) + { + case SOLDIER_CLASS_ELITE_MILITIA : + type = 5; + break; + case SOLDIER_CLASS_REG_MILITIA : + type = 4; + break; + case SOLDIER_CLASS_GREEN_MILITIA : + type = 3; + break; + } + } + + return type; +} + INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) { INT8 bBandaged; //,savedOurTurn; diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index ccf8b954..576a5b0a 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -1270,10 +1270,13 @@ public: INT32 sMTActionGridNo; // gridno on which we perfrom our multi-turn action UINT8 usMultiTurnAction; // specifies which multi-turn action we are currently performing, 0: none - INT16 bAIIndex; // PlanFactory from the modularized tactical AI that shall be used + INT16 bAIIndex; // feynman: PlanFactory from the modularized tactical AI that shall be used + + UINT16 usSoldierProfile; // Flugente: allow linking to a xml-based profile specifiying name, visuals, traits etc. + // Flugente: Decrease this filler by 1 for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!! // Note that we also have to account for padding, so you might need to substract more than just the size of the new variables - UINT8 ubFiller[10]; + UINT8 ubFiller[8]; #ifdef JA2UB //ja25 @@ -1563,6 +1566,9 @@ public: void HandleFlashLights(); UINT8 GetBestEquippedFlashLightRange(); + + // Flugente: soldier profiles + INT8 GetSoldierProfileType(UINT8 usTeam); // retrieves the correct sub-array ////////////////////////////////////////////////////////////////////////////// }; // SOLDIERTYPE; diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index 6d045bdd..ff1151be 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -44,6 +44,7 @@ #include "Strategic Mines.h" #include "math.h" #include "Game Clock.h" // added this one - SANDRO + #include "Interface.h" // added by Flugente #endif #include "connect.h" @@ -1434,6 +1435,21 @@ void GeneratePaletteForSoldier( SOLDIERTYPE *pSoldier, UINT8 ubSoldierClass ) //choose random skin tone which will limit the choice of hair colors. skin = (INT8)Random( NUMSKINS ); + + //Choose hair color which uses the skin color to limit choices + hair = ChooseHairColor( pSoldier, skin ); + + if ( pSoldier->usSoldierProfile ) + { + INT8 type = pSoldier->GetSoldierProfileType(pSoldier->bTeam); + + if ( type > -1 && zSoldierProfile[type][pSoldier->usSoldierProfile].uiSkin ) + skin = zSoldierProfile[type][pSoldier->usSoldierProfile].uiSkin - 1; + + if ( type > -1 && zSoldierProfile[type][pSoldier->usSoldierProfile].uiHair ) + hair = zSoldierProfile[type][pSoldier->usSoldierProfile].uiHair - 1; + } + switch( skin ) { case PINKSKIN: @@ -1453,8 +1469,6 @@ void GeneratePaletteForSoldier( SOLDIERTYPE *pSoldier, UINT8 ubSoldierClass ) break; } - //Choose hair color which uses the skin color to limit choices - hair = ChooseHairColor( pSoldier, skin ); switch( hair ) { case BROWNHEAD: SET_PALETTEREP_ID( pSoldier->HeadPal, "BROWNHEAD" ); break; @@ -1631,6 +1645,63 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT pSoldier->flags.bHasKeys = pCreateStruct->fHasKeys; pSoldier->ubSoldierClass = pCreateStruct->ubSoldierClass; + // Flugente: soldier profiles + if ( 1 ) + { + INT8 type = -1; + if ( pCreateStruct->bTeam == ENEMY_TEAM && gGameExternalOptions.fSoldierProfiles_Enemy ) + { + switch( pCreateStruct->ubSoldierClass ) + { + case SOLDIER_CLASS_ELITE : + type = 2; + break; + case SOLDIER_CLASS_ARMY : + type = 1; + break; + case SOLDIER_CLASS_ADMINISTRATOR : + type = 0; + break; + } + } + else if ( pCreateStruct->bTeam == ENEMY_TEAM && gGameExternalOptions.fSoldierProfiles_Enemy ) + { + switch( pCreateStruct->ubSoldierClass ) + { + case SOLDIER_CLASS_ELITE_MILITIA : + type = 5; + break; + case SOLDIER_CLASS_REG_MILITIA : + type = 4; + break; + case SOLDIER_CLASS_GREEN_MILITIA : + type = 3; + break; + } + } + + if ( type > -1 ) + { + INT16 availablenames[NUM_SOLDIER_PROFILES]; + UINT16 cnt = 0; + + for (UINT16 i = 1; i < num_found_soldier_profiles[type]; ++i) + { + // make sure the name isn't already currently in use! + if ( !IsProfileInUse(pCreateStruct->bTeam, type, i) ) + availablenames[cnt++] = i; + } + + if ( cnt > 0 ) + { + pSoldier->usSoldierProfile = availablenames[Random(cnt)]; + + if ( zSoldierProfile[type][pSoldier->usSoldierProfile].uiBodyType > 0 && zSoldierProfile[type][pSoldier->usSoldierProfile].uiBodyType < 5 ) + pSoldier->ubBodyType = zSoldierProfile[type][pSoldier->usSoldierProfile].uiBodyType - 1; + } + } + } + if( pCreateStruct->fVisible ) { sprintf( pSoldier->HeadPal, pCreateStruct->HeadPal ); @@ -3997,6 +4068,33 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre ubProgress = HighestPlayerProgressPercentage(); ubSolClass = pSoldier->ubSoldierClass; + // Flugente: soldier profiles - if any traits are in the xml, use them, but fill up empty slots afterwards + if ( pSoldier->usSoldierProfile ) + { + INT8 type = pSoldier->GetSoldierProfileType(pCreateStruct->bTeam); + + if ( type > -1 ) + { + if ( zSoldierProfile[type][pSoldier->usSoldierProfile].uiTrait[0] > 0 ) + { + pSoldier->stats.ubSkillTraits[0] = zSoldierProfile[type][pSoldier->usSoldierProfile].uiTrait[0]; + ATraitAssigned = TRUE; + } + + if ( zSoldierProfile[type][pSoldier->usSoldierProfile].uiTrait[1] > 0 ) + { + pSoldier->stats.ubSkillTraits[1] = zSoldierProfile[type][pSoldier->usSoldierProfile].uiTrait[1]; + BTraitAssigned = TRUE; + } + + if ( zSoldierProfile[type][pSoldier->usSoldierProfile].uiTrait[2] > 0 ) + { + pSoldier->stats.ubSkillTraits[2] = zSoldierProfile[type][pSoldier->usSoldierProfile].uiTrait[2]; + CTraitAssigned = TRUE; + } + } + } + // First determine who will be the squadleader for this group (administrators do not get a squadleader if ( gGameOptions.fNewTraitSystem && bNumSquadleadersInArmy < ((ubSolClass == SOLDIER_CLASS_ELITE || ubSolClass == SOLDIER_CLASS_ARMY) ? gGameOptions.ubDifficultyLevel : 2 ) && ( ubSolClass == SOLDIER_CLASS_ELITE || ubSolClass == SOLDIER_CLASS_ELITE_MILITIA || diff --git a/Tactical/Tactical_VS2005.vcproj b/Tactical/Tactical_VS2005.vcproj index 2b361a0b..36f79409 100644 --- a/Tactical/Tactical_VS2005.vcproj +++ b/Tactical/Tactical_VS2005.vcproj @@ -1164,6 +1164,10 @@ RelativePath=".\XML_SectorLoadscreens.cpp" > + + diff --git a/Tactical/Tactical_VS2008.vcproj b/Tactical/Tactical_VS2008.vcproj index 31ac4aa1..5feda15b 100644 --- a/Tactical/Tactical_VS2008.vcproj +++ b/Tactical/Tactical_VS2008.vcproj @@ -1166,6 +1166,10 @@ RelativePath="XML_SectorLoadscreens.cpp" > + + diff --git a/Tactical/Tactical_VS2010.vcxproj b/Tactical/Tactical_VS2010.vcxproj index dc240e44..f273fba1 100644 --- a/Tactical/Tactical_VS2010.vcxproj +++ b/Tactical/Tactical_VS2010.vcxproj @@ -230,6 +230,7 @@ + diff --git a/Tactical/Tactical_VS2010.vcxproj.filters b/Tactical/Tactical_VS2010.vcxproj.filters index 5534d926..a7744310 100644 --- a/Tactical/Tactical_VS2010.vcxproj.filters +++ b/Tactical/Tactical_VS2010.vcxproj.filters @@ -641,5 +641,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Tactical/XML.h b/Tactical/XML.h index b2b0cff1..71ed5cca 100644 --- a/Tactical/XML.h +++ b/Tactical/XML.h @@ -233,6 +233,13 @@ typedef PARSE_STAGE; #define VEHICLESFILENAME "Vehicles.xml" #define SQUADNAMEFILENAME "SquadNames.xml" +#define ENEMY_ADMIN_PROFILE_FILENAME "Profiles\\SoldierProfileEnemyAdmin.xml" +#define ENEMY_REGULAR_PROFILE_FILENAME "Profiles\\SoldierProfileEnemyRegular.xml" +#define ENEMY_ELITE_PROFILE_FILENAME "Profiles\\SoldierProfileEnemyElite.xml" +#define MILITIA_GREEN_PROFILE_FILENAME "Profiles\\SoldierProfileMilitiaGreen.xml" +#define MILITIA_REGULAR_PROFILE_FILENAME "Profiles\\SoldierProfileMilitiaRegular.xml" +#define MILITIA_VETERAN_PROFILE_FILENAME "Profiles\\SoldierProfileMilitiaVeteran.xml" + extern BOOLEAN ReadInItemStats(STR fileName, BOOLEAN localizedVersion); extern BOOLEAN WriteItemStats(); @@ -307,6 +314,10 @@ extern BOOLEAN WriteSquadNamesStats(); extern BOOLEAN ReadInLoadScreenHints(STR fileName); extern BOOLEAN WriteLoadScreenHints(); +// Flugente: soldier profiles +extern BOOLEAN ReadInSoldierProfiles(SOLDIER_PROFILE_VALUES* pProfiles, STR fileName); +extern BOOLEAN WriteSoldierProfiles(); + extern BOOLEAN ReadInAmmoStats(STR fileName); extern BOOLEAN WriteAmmoStats(); diff --git a/aniviewscreen.cpp b/aniviewscreen.cpp index 602ea063..44bc71f2 100644 --- a/aniviewscreen.cpp +++ b/aniviewscreen.cpp @@ -23,7 +23,7 @@ #include "Event Pump.h" #include "Render Dirty.h" #include "Sys Globals.h" - #include "interface.h" + #include "Interface.h" #include #include #include "english.h"