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"