From efd9ab472304a721a91dfc10496df9f2bd42b17a Mon Sep 17 00:00:00 2001 From: Flugente Date: Sat, 14 Jan 2017 20:20:11 +0000 Subject: [PATCH] New feature: Voicesets are now independent fom profile slots. Voiceset is set in MercProfiles.xml with . IMP voices are defined in IMPVoices.xml. This feature is savegame compatible. Requires GameDir >= r2357 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8364 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameVersion.cpp | 18 +-- GameVersion.h | 3 +- Init.cpp | 6 + Laptop/CharProfile.cpp | 5 +- Laptop/IMP Attribute Selection.cpp | 12 -- Laptop/IMP Color Choosing.cpp | 104 ---------------- Laptop/IMP Compile Character.cpp | 114 ++++-------------- Laptop/IMP Compile Character.h | 2 - Laptop/IMP Confirm.cpp | 7 ++ Laptop/IMP Confirm.h | 13 ++ Laptop/IMP Finish.cpp | 2 - Laptop/IMP MainPage.cpp | 70 ++--------- Laptop/IMP Voices.cpp | 155 ++++++++---------------- Laptop/IMP Voices.h | 2 + Laptop/Laptop_VS2005.vcproj | 4 + Laptop/Laptop_VS2008.vcproj | 4 + Laptop/Laptop_VS2010.vcxproj | 3 +- Laptop/Laptop_VS2010.vcxproj.filters | 3 + Laptop/Laptop_VS2013.vcxproj | 1 + Laptop/Laptop_VS2013.vcxproj.filters | 3 + Laptop/XML_IMPVoices.cpp | 174 +++++++++++++++++++++++++++ SaveLoadGame.cpp | 21 ++++ Tactical/Dialogue Control.cpp | 119 +++++++++--------- Tactical/Soldier Control.cpp | 9 +- Tactical/Soldier Profile.cpp | 9 +- Tactical/Soldier Profile.h | 2 + Tactical/XML.h | 2 + Tactical/XML_Opinions.cpp | 2 +- Tactical/XML_Profiles.cpp | 16 ++- Tactical/soldier profile type.h | 2 + 30 files changed, 425 insertions(+), 462 deletions(-) create mode 100644 Laptop/XML_IMPVoices.cpp diff --git a/GameVersion.cpp b/GameVersion.cpp index f47a102e..7a7b6b61 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -15,9 +15,9 @@ #ifdef JA2EDITOR #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8364 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8364 (Development Build)" }; #endif // ------------------------------ @@ -27,11 +27,11 @@ //DEBUG BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8364 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8364 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8364 (Development Build)" }; #endif #elif defined CRIPPLED_VERSION @@ -46,16 +46,16 @@ //RELEASE BUILD VERSION #ifdef JA2UB - CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8364 (Development Build)" }; #elif defined (JA113DEMO) - CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8364 (Development Build)" }; #else - CHAR16 zVersionLabel[256] = { L"Release v1.13.8345 (Development Build)" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.8364 (Development Build)" }; #endif #endif -CHAR8 czVersionNumber[16] = { "Build 16.12.11" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 17.01.14" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; // SAVE_GAME_VERSION is defined in header, change it there diff --git a/GameVersion.h b/GameVersion.h index 14f592fe..d7c0ee59 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 SEPARATE_VOICESETS 173 // Flugente: voice sets are now separate from profile slots, and we can have many more of them #define HACKABLE_SAMS 172 // Flugente: SAM sites now have a status for hacking #define LUA_MODDERDATA 171 // Flugente: modders can set and use data in an exclusive array #define WORKERS 170 // Flugente: train workers for facilities @@ -91,7 +92,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 HACKABLE_SAMS +#define SAVE_GAME_VERSION SEPARATE_VOICESETS //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/Init.cpp b/Init.cpp index ac393211..450254f6 100644 --- a/Init.cpp +++ b/Init.cpp @@ -1104,6 +1104,12 @@ BOOLEAN LoadExternalGameplayData(STR directoryName) LoadIMPPortraitsTEMP( ); + // Flugente: imp voices + strcpy( fileName, directoryName ); + strcat( fileName, IMPVOICES ); + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "LoadExternalGameplayData, fileName = %s", fileName ) ); + SGP_THROW_IFFALSE( ReadInIMPVoices( fileName ), IMPVOICES ); + // Flugente: soldier profiles if (!is_networked) { diff --git a/Laptop/CharProfile.cpp b/Laptop/CharProfile.cpp index cfa82e97..f5085398 100644 --- a/Laptop/CharProfile.cpp +++ b/Laptop/CharProfile.cpp @@ -130,16 +130,13 @@ void BtnIMPCancelCallback(GUI_BUTTON *btn,INT32 reason); BOOLEAN HasTheCurrentIMPPageBeenVisited( void ); extern void SetAttributes( void ); - void GameInitCharProfile() { LaptopSaveInfo.iIMPIndex = 0; iCurrentPortrait = 0; iCurrentProfileMode = 0; -// iCurrentVoice = 0; + iSelectedIMPVoiceSet = 0; iPortraitNumber = 0; - - return; } void EnterCharProfile() diff --git a/Laptop/IMP Attribute Selection.cpp b/Laptop/IMP Attribute Selection.cpp index 55a3eb8f..492dbc33 100644 --- a/Laptop/IMP Attribute Selection.cpp +++ b/Laptop/IMP Attribute Selection.cpp @@ -197,18 +197,6 @@ void EnterIMPAttributeSelection( void ) gpCurrentScrollBox = NULL; giCurrentlySelectedStat = -1; - - // does character have PROBLEMS!!?!?! - /* - if( DoesCharacterHaveAnAttitude() ) - { - iCurrentBonusPoints+= 10; - } - if( DoesCharacterHaveAPersoanlity( ) ) - { - iCurrentBonusPoints += 10; - } - */ } fReturnStatus = TRUE; fFirstIMPAttribTime = FALSE; diff --git a/Laptop/IMP Color Choosing.cpp b/Laptop/IMP Color Choosing.cpp index 9a66f169..a61e3aa2 100644 --- a/Laptop/IMP Color Choosing.cpp +++ b/Laptop/IMP Color Choosing.cpp @@ -186,110 +186,6 @@ void EnterIMPColorChoice( void ) bBigBody = gIMPValues[iPortraitNumber].bBigBody; } - // Based on the portrait chosen, set the default colors, when colors -/* switch( iPortraitNumber ) - { - case( 0 ): - iCurrentSkin = 3; - iCurrentHair = 0; - iCurrentShirt = 7; - iCurrentPants = 2; - bBigBody = TRUE; - break; - case( 1 ): - iCurrentSkin = 1; - iCurrentHair = 0; - iCurrentShirt = 4; - iCurrentPants = 3; - break; - case( 2 ): - iCurrentSkin = 1; - iCurrentHair = 0; - iCurrentShirt = 0; - iCurrentPants = 0; - break; - case( 3 ): - iCurrentSkin = 2; - iCurrentHair = 0; - iCurrentShirt = 0; - iCurrentPants = 1; - break; - case( 4 ): - iCurrentSkin = 1; - iCurrentHair = 0; - iCurrentShirt = 3; - iCurrentPants = 5; - break; - case( 5 ): - iCurrentSkin = 2; - iCurrentHair = 1; - iCurrentShirt = 3; - iCurrentPants = 1; - break; - case( 6 ): - iCurrentSkin = 1; - iCurrentHair = 0; - iCurrentShirt = 4; - iCurrentPants = 0; - bBigBody = TRUE; - break; - case( 7 ): - iCurrentSkin = 1; - iCurrentHair = 0; - iCurrentShirt = 10; - iCurrentPants = 1; - bBigBody = TRUE; - break; - case( 8 ): - iCurrentSkin = 1; - iCurrentHair = 0; - iCurrentShirt = 4; - iCurrentPants = 3; - break; - case( 9 ): - iCurrentSkin = 0; - iCurrentHair = 0; - iCurrentShirt = 4; - iCurrentPants = 4; - break; - case( 10 ): - iCurrentSkin = 1; - iCurrentHair = 1; - iCurrentShirt = 4; - iCurrentPants = 1; - break; - case( 11 ): - iCurrentSkin = 1; - iCurrentHair = 1; - iCurrentShirt = 10; - iCurrentPants = 1; - break; - case( 12 ): - iCurrentSkin = 0; - iCurrentHair = 0; - iCurrentShirt = 0; - iCurrentPants = 5; - break; - case( 13 ): - iCurrentSkin = 3; - iCurrentHair = 0; - iCurrentShirt = 3; - iCurrentPants = 1; - break; - case( 14 ): - iCurrentSkin = 1; - iCurrentHair = 4; - iCurrentShirt = 0; - iCurrentPants = 2; - break; - case( 15 ): - iCurrentSkin = 1; - iCurrentHair = 3; - iCurrentShirt = 4; - iCurrentPants = 5; - break; - } -*/ //add the buttons AddIMPColorChoiceButtons(); diff --git a/Laptop/IMP Compile Character.cpp b/Laptop/IMP Compile Character.cpp index 29d79a73..b84a9b99 100644 --- a/Laptop/IMP Compile Character.cpp +++ b/Laptop/IMP Compile Character.cpp @@ -27,6 +27,7 @@ #include "IMP Disability Trait.h" #include "IMP Color Choosing.h" #include "IMP Minor Trait.h" + #include "IMP Voices.h" #endif #include "IMP Confirm.h" @@ -116,17 +117,24 @@ void SetMercSkinAndHairColors( void ); BOOLEAN ShouldThisMercHaveABigBody( void ); - - - void CreateACharacterFromPlayerEnteredStats( void ) { - // Kaiden: Seems like as good a place as any to stash this function call to // ensure that these lists don't get overwritten or Nulled due to the amount // of changes and revisions that have been made to personalities and attitudes. CreatePlayersPersonalitySkillsAndAttitude(); + // Flugente: as the profile is no longer identical to the voice set, we need to determine a free slot + INT32 impslot = 0; + if ( fCharacterIsMale ) + impslot = GetFirstMaleSlot( ); + else + impslot = GetFirstFemaleSlot( ); + + INT32 impid = gGameExternalOptions.iaIMPSlots[impslot]; + + LaptopSaveInfo.iIMPIndex = GetFreeIMPSlot( impid, -1 ); + // copy over full name wcscpy( gMercProfiles[ LaptopSaveInfo.iIMPIndex ].zName, pFullName ); @@ -144,8 +152,7 @@ void CreateACharacterFromPlayerEnteredStats( void ) // female gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bSex = FEMALE; } - - + // attributes gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bLifeMax = ( INT8 )iHealth; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bLife = ( INT8 )iHealth; @@ -154,15 +161,13 @@ void CreateACharacterFromPlayerEnteredStats( void ) gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bDexterity = ( INT8 )iDexterity; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bWisdom = ( INT8 )iWisdom; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bLeadership = ( INT8 )iLeadership; - - + // skills gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bMarksmanship = ( INT8 )iMarksmanship; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bMedical = ( INT8 )iMedical; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bMechanical = ( INT8 )iMechanical; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bExplosive = ( INT8 )iExplosives; - - + // personality gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bDisability = ( INT8 )iPersonality; @@ -176,7 +181,7 @@ void CreateACharacterFromPlayerEnteredStats( void ) // Flugente: background gMercProfiles[ LaptopSaveInfo.iIMPIndex ].usBackground = usBackground; - // Flugente: sexism, racsim etc. + // Flugente: sexism, racism etc. gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bRace = ( INT8 )bRace; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bNationality = ( INT8 )bNationality; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bAppearance = ( INT8 )bAppearance; @@ -187,6 +192,10 @@ void CreateACharacterFromPlayerEnteredStats( void ) gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bHatedNationalityCareLevel = ( INT8 )bHatedNationalityCareLevel; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bRacist = ( INT8 )bRacist; gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bSexist = ( UINT8 )bSexist; + + // Flugente: voice set used + gMercProfiles[LaptopSaveInfo.iIMPIndex].usVoiceIndex = iSelectedIMPVoiceSet; + // WDS: Advanced start //gMercProfiles[ LaptopSaveInfo.iIMPIndex ].bExpLevel = gGameExternalOptions.ubIMPStartingLevel; @@ -201,69 +210,6 @@ void CreateACharacterFromPlayerEnteredStats( void ) // Option for badass added - SANDRO if (bBadAssSelected()) gMercProfiles[ LaptopSaveInfo.iIMPIndex ].uiBodyTypeSubFlags = 1; - - - return; - -} - - -BOOLEAN DoesCharacterHaveAnAttitude( void ) -{ - - // simply checks if caracter has an attitude other than normal - switch( iAttitude ) - { - case ATT_LONER: - case ATT_PESSIMIST: - case ATT_ARROGANT: - case ATT_BIG_SHOT: - case ATT_ASSHOLE: - case ATT_COWARD: - return( TRUE ); - default: - return( FALSE ); - } -} - - -BOOLEAN DoesCharacterHaveAPersoanlity( void ) -{ - - - if( iPersonality != NO_DISABILITY ) - { - // yep - return ( TRUE ); - } - else - { - // nope - return ( FALSE ); - } - - - // Kaiden: Following is the original UB section: - // The fist return( FALSE ); Statement was the only - // thing uncommented. -/* - // only one we can get is PSYCHO, and that is not much of a penalty - return( FALSE ); - - // simply checks if caracter has a personality other than normal - if( iPersonality != NO_DISABILITY ) - { - // yep - return ( TRUE ); - } - else - { - // nope - return ( FALSE ); - } - */ - - } void CreatePlayerAttitude( void ) @@ -286,8 +232,6 @@ void AddAnAttitudeToAttitudeList( INT8 bAttitude ) // increment attitude list counter iLastElementInAttitudeList++; } - - return; } @@ -317,8 +261,6 @@ void ClearAllSkillsList( void ) iLastElementInSkillsList = 0; } - - void RemoveSkillFromSkillsList( INT32 iIndex ) { INT32 iLoop; @@ -348,9 +290,7 @@ void RemoveSkillFromSkillsList( INT32 iIndex ) INT32 FindSkillInSkillsList( INT32 iSkill ) { - INT32 iLoop; - - for ( iLoop = 0; iLoop < iLastElementInSkillsList; iLoop++ ) + for ( INT32 iLoop = 0; iLoop < iLastElementInSkillsList; iLoop++ ) { if ( SkillsList[ iLoop ] == iSkill ) { @@ -389,7 +329,6 @@ void ValidateSkillsList( void ) if ( iIndex != -1 ) pProfile->bMechanical = 1; } - } // SANDRO - added to give 1 medical skill to doctors @@ -506,8 +445,6 @@ void AddAPersonalityToPersonalityList( INT8 bPersonlity ) // increment attitude list counter iLastElementInPersonalityList++; } - - return; } void CreatePlayerPersonality( void ) @@ -515,8 +452,6 @@ void CreatePlayerPersonality( void ) // DELETED UNUSED PART OF THE CODE - SANDRO iPersonality = iChosenDisabilityTrait(); - - return; } void CreatePlayersPersonalitySkillsAndAttitude( void ) @@ -531,14 +466,10 @@ void CreatePlayersPersonalitySkillsAndAttitude( void ) // attitude CreatePlayerAttitude( ); - - return; } - void ResetSkillsAttributesAndPersonality( void ) { - // reset count of skills attributes and personality iLastElementInPersonalityList = 0; @@ -546,10 +477,8 @@ void ResetSkillsAttributesAndPersonality( void ) iLastElementInSkillsList = 0; iLastElementInAttitudeList = 0; - } - void ResetIncrementCharacterAttributes( void ) { // this resets any increments due to character generation @@ -567,7 +496,6 @@ void ResetIncrementCharacterAttributes( void ) iAddExplosives = 0; iAddMedical = 0; iAddMechanical = 0; - } void SelectMercFace( void ) diff --git a/Laptop/IMP Compile Character.h b/Laptop/IMP Compile Character.h index d3487817..6a1d81a7 100644 --- a/Laptop/IMP Compile Character.h +++ b/Laptop/IMP Compile Character.h @@ -7,13 +7,11 @@ void AddAnAttitudeToAttitudeList( INT8 bAttitude ); void CreatePlayerAttitude( void ); -BOOLEAN DoesCharacterHaveAnAttitude( void ); void CreateACharacterFromPlayerEnteredStats( void ); void CreatePlayerSkills( void ); void CreatePlayersPersonalitySkillsAndAttitude( void ); void AddAPersonalityToPersonalityList( INT8 bPersonlity ); void CreatePlayerPersonality( void ); -BOOLEAN DoesCharacterHaveAPersoanlity( void ); void AddSkillToSkillList( INT8 bSkill ); void ResetSkillsAttributesAndPersonality( void ); void ResetIncrementCharacterAttributes( void ); diff --git a/Laptop/IMP Confirm.cpp b/Laptop/IMP Confirm.cpp index f0a3bb7a..c95c089d 100644 --- a/Laptop/IMP Confirm.cpp +++ b/Laptop/IMP Confirm.cpp @@ -1535,6 +1535,13 @@ BOOLEAN LoadImpCharacter( STR nickName ) DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 7 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, NULL); return FALSE; } + + /// Flugente: until the introduction of a separate variable for the voiceset, the voice was identical with the slot + if ( guiCurrentSaveGameVersion < SEPARATE_VOICESETS ) + { + gMercProfiles[iProfileId].usVoiceIndex = iProfileId; + } + guiCurrentSaveGameVersion = SAVE_GAME_VERSION; // close file diff --git a/Laptop/IMP Confirm.h b/Laptop/IMP Confirm.h index cf64dca9..463b1058 100644 --- a/Laptop/IMP Confirm.h +++ b/Laptop/IMP Confirm.h @@ -51,6 +51,19 @@ typedef struct extern IMP_VALUES gIMPValues[NUM_PROFILES]; +// Flugente: voicesets are no longer tied to a slot +typedef struct +{ + CHAR16 szVoiceSetName[20]; + UINT16 voiceset; + BOOLEAN bSex; + BOOLEAN exists; // set upon reading the xml: this voice exists +} IMP_VOICESET; + +#define NUM_IMP_VOICESETS 100 + +extern IMP_VOICESET gIMPVoice[NUM_IMP_VOICESETS]; + BOOLEAN AddCharacterToPlayersTeam( void ); BOOLEAN LoadImpCharacter( STR fileName ); void WriteOutCurrentImpCharacter( INT32 iProfileId ); diff --git a/Laptop/IMP Finish.cpp b/Laptop/IMP Finish.cpp index 6b5064c8..aeedc233 100644 --- a/Laptop/IMP Finish.cpp +++ b/Laptop/IMP Finish.cpp @@ -51,8 +51,6 @@ UINT32 uiVoiceSound = 0; // image handle UINT32 guiCHARACTERPORTRAIT; -extern INT32 iCurrentPortrait; -extern INT32 iCurrentVoice; // function definitions void CreateIMPFinishButtons( void ); diff --git a/Laptop/IMP MainPage.cpp b/Laptop/IMP MainPage.cpp index bc1b0e79..e165c9a5 100644 --- a/Laptop/IMP MainPage.cpp +++ b/Laptop/IMP MainPage.cpp @@ -85,8 +85,6 @@ BOOLEAN CheckIfFinishedCharacterGeneration( void ); INT32 iCurrentProfileMode = IMP__REGISTRY; -extern INT32 iCurrentVoice; - // Return a count of how many IMP slots there are in total INT32 CountIMPSlots() { @@ -269,11 +267,9 @@ BOOLEAN IsIMPSlotFree(INT32 iIMPId) void EnterIMPMainPage( void ) { - // turn off review mode fReviewStats = FALSE; - - + // create buttons CreateIMPMainPageButtons( ); @@ -288,8 +284,6 @@ void EnterIMPMainPage( void ) // entry into IMP about us page RenderIMPMainPage( ); - - return; } @@ -300,8 +294,6 @@ void ExitIMPMainPage( void ) // delete Buttons DeleteIMPMainPageButtons( ); DestoryMouseRegionsForIMPMainPageBasedOnCharGenStatus( ); - - return; } @@ -316,8 +308,6 @@ void RenderIMPMainPage( void ) //RenderIMPSymbol( 106, 1 ); // indent RenderMainIndentFrame( 164, 74 ); - - return; } @@ -331,7 +321,6 @@ void HandleIMPMainPage( void ) } // shade out buttons that should be shaded/unselectable //ShadeUnSelectableButtons( ); - return; } // @@ -340,12 +329,10 @@ void HandleIMPMainPage( void ) void CreateIMPMainPageButtons( void ) { CHAR16 sString[ 128 ]; - - + // the back button button giIMPMainPageButtonImage[0]= LoadButtonImage( "LAPTOP\\button_3.sti" ,-1,0,-1,1,-1 ); - - + /* giIMPMainPageButton[0] = QuickCreateButton( giIMPMainPageButtonImage[0], LAPTOP_SCREEN_UL_X + 10 , LAPTOP_SCREEN_WEB_UL_Y + ( 360 ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnIMPMainPageBackCallback); @@ -485,11 +472,7 @@ void CreateIMPMainPageButtons( void ) { SpecifyButtonIcon( giIMPMainPageButton[5], guiSMALLSILHOUETTE, 0, 33, 23, FALSE ); } - - - - - + SetButtonCursor(giIMPMainPageButton[ 0 ], CURSOR_WWW); SetButtonCursor(giIMPMainPageButton[ 1 ], CURSOR_WWW); SetButtonCursor(giIMPMainPageButton[ 2 ], CURSOR_WWW); @@ -507,7 +490,6 @@ void CreateIMPMainPageButtons( void ) SpecifyButtonTextWrappedWidth( giIMPMainPageButton[ 3 ], MAIN_PAGE_BUTTON_TEXT_WIDTH); SpecifyButtonTextWrappedWidth( giIMPMainPageButton[ 4 ], MAIN_PAGE_BUTTON_TEXT_WIDTH); SpecifyButtonTextWrappedWidth( giIMPMainPageButton[ 5 ], MAIN_PAGE_BUTTON_TEXT_WIDTH); - return; } @@ -538,9 +520,6 @@ void DeleteIMPMainPageButtons( void ) // begin voice button RemoveButton(giIMPMainPageButton[5] ); UnloadButtonImage(giIMPMainPageButtonImage[5] ); - - - return; } void BtnIMPMainPageBackCallback(GUI_BUTTON *btn,INT32 reason) @@ -570,10 +549,8 @@ void BtnIMPMainPageBackCallback(GUI_BUTTON *btn,INT32 reason) void BtnIMPMainPageBeginCallback(GUI_BUTTON *btn,INT32 reason) { - // btn callback for Main Page Begin Profiling - if (!(btn->uiFlags & BUTTON_ENABLED)) return; @@ -666,9 +643,7 @@ void BtnIMPMainPageAttributesCallback(GUI_BUTTON *btn,INT32 reason) btn->uiFlags&=~(BUTTON_CLICKED_ON); return; } - - - + if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags|=(BUTTON_CLICKED_ON); @@ -697,9 +672,7 @@ void BtnIMPMainPagePortraitCallback(GUI_BUTTON *btn,INT32 reason) btn->uiFlags&=~(BUTTON_CLICKED_ON); return; } - - - + if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags|=(BUTTON_CLICKED_ON); @@ -715,10 +688,8 @@ void BtnIMPMainPagePortraitCallback(GUI_BUTTON *btn,INT32 reason) } } - void BtnIMPMainPageVoiceCallback(GUI_BUTTON *btn,INT32 reason) { - // btn callback for Main Page Begin Profiling if (!(btn->uiFlags & BUTTON_ENABLED)) @@ -729,9 +700,7 @@ void BtnIMPMainPageVoiceCallback(GUI_BUTTON *btn,INT32 reason) btn->uiFlags&=~(BUTTON_CLICKED_ON); return; } - - - + if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags|=(BUTTON_CLICKED_ON); @@ -749,7 +718,6 @@ void BtnIMPMainPageVoiceCallback(GUI_BUTTON *btn,INT32 reason) } } - void NextProfilingMode( void ) { // this function will change to mode the player is in for profiling @@ -757,8 +725,6 @@ void NextProfilingMode( void ) // if less than done if(iCurrentProfileMode < IMP__VOICE) iCurrentProfileMode++; - - return; } BOOLEAN CheckIfFinishedCharacterGeneration( void ) @@ -792,7 +758,6 @@ void ShadeUnSelectableButtons( void ) } fMarkButtonsDirtyFlag = FALSE; - return; } @@ -936,22 +901,12 @@ void CreateMouseRegionsForIMPMainPageBasedOnCharGenStatus( void ) // mask for voice page button MSYS_DefineRegion( &pIMPMainPageMouseRegions[ 3 ],LAPTOP_SCREEN_UL_X + 373 , LAPTOP_SCREEN_WEB_UL_Y + ( 245 ), LAPTOP_SCREEN_UL_X + 373 + 115 , LAPTOP_SCREEN_WEB_UL_Y + ( 245 ) + 93 , MSYS_PRIORITY_HIGH+5, CURSOR_WWW, MSYS_NO_CALLBACK, IMPMainPageNotSelectableBtnCallback ); - - - - - - - return; } - - void DestoryMouseRegionsForIMPMainPageBasedOnCharGenStatus( void ) { // will destroy button masks for the char gen pages - MSYS_RemoveRegion( &pIMPMainPageMouseRegions[ 0 ]); MSYS_RemoveRegion( &pIMPMainPageMouseRegions[ 1 ]); @@ -959,15 +914,10 @@ void DestoryMouseRegionsForIMPMainPageBasedOnCharGenStatus( void ) MSYS_RemoveRegion( &pIMPMainPageMouseRegions[ 2 ]); MSYS_RemoveRegion( &pIMPMainPageMouseRegions[ 3 ]); - - - - return; } void IMPMainPageNotSelectableBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ) { - if (iReason & MSYS_CALLBACK_REASON_INIT) { @@ -978,8 +928,6 @@ void IMPMainPageNotSelectableBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ) { DoLapTopMessageBox( MSG_BOX_IMP_STYLE, pImpPopUpStrings[ 4 ], LAPTOP_SCREEN, MSG_BOX_FLAG_OK, BeginMessageBoxCallBack); } - - return; } // WDS: Allow flexible numbers of IMPs of each sex @@ -1007,7 +955,6 @@ INT32 CountFilledIMPSlots( INT8 iSex ) return iCount; } - INT32 CountEmptyIMPSlots( INT8 iSex ) { INT32 i; @@ -1161,8 +1108,6 @@ BOOLEAN IMP_CanWeDisplayAttributeGraph( ) } } - - BOOLEAN IMP_CanWeDisplaySpecialtiesGraph( ) { if( iCurrentProfileMode == IMP__ATTRIBUTES || @@ -1176,7 +1121,6 @@ BOOLEAN IMP_CanWeDisplaySpecialtiesGraph( ) } } - BOOLEAN IMP_CanWeDisplayVoiceGraph( ) { if( iCurrentProfileMode == IMP__ATTRIBUTES || diff --git a/Laptop/IMP Voices.cpp b/Laptop/IMP Voices.cpp index 07865ccc..2d75253d 100644 --- a/Laptop/IMP Voices.cpp +++ b/Laptop/IMP Voices.cpp @@ -19,20 +19,17 @@ #include "soldier profile type.h" #include "GameSettings.h" #include "LaptopSave.h" + #include "IMP Confirm.h" #endif INT32 iCurrentVoice = 0; +UINT32 iSelectedIMPVoiceSet = 0; UINT32 uiVocVoiceSound = 0; // buttons needed for the IMP Voices screen INT32 giIMPVoicesButton[ 3 ]; INT32 giIMPVoicesButtonImage[ 3 ]; - -// hacks to be removeed later -BOOLEAN fVoiceAVisited = FALSE, fVoiceBVisited = FALSE, fVoiceCVisited = FALSE; - - // redraw protrait screen BOOLEAN fReDrawVoicesScreenFlag = FALSE; @@ -57,20 +54,17 @@ void IMPPortraitRegionButtonCallback(MOUSE_REGION * pRegion, INT32 iReason ); void EnterIMPVoices( void ) { - fVoiceAVisited = FALSE; - fVoiceBVisited = FALSE; - fVoiceCVisited = FALSE; - // Set the initial voice - if (fCharacterIsMale == TRUE) + for ( int i = 0; i < NUM_IMP_VOICESETS; ++i ) { - iCurrentVoice = GetFirstFreeSlot(MALE); + // MALE is 0, FEMALE is 1, thus the negation + if ( gIMPVoice[i].exists && !fCharacterIsMale == gIMPVoice[i].bSex ) + { + iCurrentVoice = i; + break; + } } - else - { - iCurrentVoice = GetFirstFreeSlot(FEMALE); - } - + // create buttons CreateIMPVoicesButtons( ); @@ -82,15 +76,10 @@ void EnterIMPVoices( void ) // play voice once uiVocVoiceSound = PlayVoice( ); - - return; } - void RenderIMPVoices( void ) { - - // render background RenderProfileBackGround( ); @@ -108,11 +97,8 @@ void RenderIMPVoices( void ) // text PrintImpText( ); - - return; } - void ExitIMPVoices( void ) { // destroy buttons for IMP Voices page @@ -120,96 +106,68 @@ void ExitIMPVoices( void ) // destroy mouse regions for this screen DestroyIMPVoiceMouseRegions( ); - - - return; } void HandleIMPVoices( void ) { - // do we need to re write screen if ( fReDrawVoicesScreenFlag == TRUE ) { - RenderIMPVoices( ); + RenderIMPVoices( ); // reset redraw flag fReDrawVoicesScreenFlag = FALSE; } - return; } - - -// WDS: Allow flexible numbers of IMPs of each sex -// Ensure the voice is within the valid range -void FixVoiceRange() +void IncrementVoice() { - if (fCharacterIsMale == TRUE) + ++iCurrentVoice; + + for ( int i = iCurrentVoice; i < NUM_IMP_VOICESETS; ++i ) { - if (iCurrentVoice > GetLastMaleSlot()) - iCurrentVoice = GetFirstMaleSlot(); - else if (iCurrentVoice < GetFirstMaleSlot()) - iCurrentVoice = GetLastMaleSlot(); - } - else - { - if (iCurrentVoice > GetLastFemaleSlot()) - iCurrentVoice = GetFirstFemaleSlot(); - else if (iCurrentVoice < GetFirstFemaleSlot()) - iCurrentVoice = GetLastFemaleSlot(); - } -} - - -void IncrementVoice( void ) -{ - INT32 iIMPIndex = -1; - INT32 i; - - iCurrentVoice++; - FixVoiceRange(); - - // Just to be safe (so we use no endless loop) - for (i = 0; i < CountIMPSlots(); i++) - { - if (IsIMPSlotFree(gGameExternalOptions.iaIMPSlots[iCurrentVoice]) == TRUE) + if ( gIMPVoice[i].exists && !fCharacterIsMale == gIMPVoice[i].bSex ) { - // This is a free imp index - iIMPIndex = gGameExternalOptions.iaIMPSlots[iCurrentVoice]; - break; + iCurrentVoice = i; + return; } + } - iCurrentVoice++; - FixVoiceRange(); + // still here? Start from the beginning then + for ( int i = 0; i < NUM_IMP_VOICESETS; ++i ) + { + if ( gIMPVoice[i].exists && !fCharacterIsMale == gIMPVoice[i].bSex ) + { + iCurrentVoice = i; + return; + } } } - void DecrementVoice( void ) { - INT32 iIMPIndex = -1; - INT32 i; + --iCurrentVoice; - iCurrentVoice--; - FixVoiceRange(); - - // Just to be safe (so we use no endless loop) - for (i = 0; i < CountIMPSlots(); i++) + for ( int i = iCurrentVoice; i > 0; --i ) { - if (IsIMPSlotFree(gGameExternalOptions.iaIMPSlots[iCurrentVoice]) == TRUE) + if ( gIMPVoice[i].exists && !fCharacterIsMale == gIMPVoice[i].bSex ) { - // This is the free imp index - iIMPIndex = gGameExternalOptions.iaIMPSlots[iCurrentVoice]; - break; + iCurrentVoice = i; + return; } + } - iCurrentVoice--; - FixVoiceRange(); + // still here? Start from the beginning then + for ( int i = NUM_IMP_VOICESETS - 1; i > 0; --i ) + { + if ( gIMPVoice[i].exists && !fCharacterIsMale == gIMPVoice[i].bSex ) + { + iCurrentVoice = i; + return; + } } } - void CreateIMPVoicesButtons( void ) { // will create buttons need for the IMP Voices screen @@ -226,8 +184,7 @@ void CreateIMPVoicesButtons( void ) TEXT_CJUSTIFIED, LAPTOP_SCREEN_UL_X + ( 343 ), LAPTOP_SCREEN_WEB_UL_Y + ( 205 ),BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnIMPVoicesNextCallback); - - + // previous button giIMPVoicesButtonImage[ 1 ]= LoadButtonImage( "LAPTOP\\voicearrows.sti" ,-1,0,-1,2,-1 ); /* giIMPVoicesButton[ 1 ] = QuickCreateButton( giIMPVoicesButtonImage[ 1 ], LAPTOP_SCREEN_UL_X + ( 18 ), LAPTOP_SCREEN_WEB_UL_Y + ( 254 ), @@ -240,8 +197,7 @@ void CreateIMPVoicesButtons( void ) TEXT_CJUSTIFIED, LAPTOP_SCREEN_UL_X + ( 93), LAPTOP_SCREEN_WEB_UL_Y + ( 205 ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnIMPVoicesPreviousCallback); - - + // done button giIMPVoicesButtonImage[ 2 ]= LoadButtonImage( "LAPTOP\\button_5.sti" ,-1,0,-1,1,-1 ); /* giIMPVoicesButton[ 2 ] = QuickCreateButton( giIMPVoicesButtonImage[ 1 ], LAPTOP_SCREEN_UL_X + ( 349 ), LAPTOP_SCREEN_WEB_UL_Y + ( 220 ), @@ -254,17 +210,13 @@ void CreateIMPVoicesButtons( void ) TEXT_CJUSTIFIED, LAPTOP_SCREEN_UL_X + ( 187 ), LAPTOP_SCREEN_WEB_UL_Y + ( 330 ), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnIMPVoicesDoneCallback); - - - + SetButtonCursor(giIMPVoicesButton[0], CURSOR_WWW); SetButtonCursor(giIMPVoicesButton[1], CURSOR_WWW); SetButtonCursor(giIMPVoicesButton[2], CURSOR_WWW); } - - void DestroyIMPVoicesButtons( void ) { // will destroy buttons created for IMP Voices screen @@ -285,7 +237,6 @@ void DestroyIMPVoicesButtons( void ) void BtnIMPVoicesNextCallback( GUI_BUTTON *btn, INT32 reason ) { - // btn callback for IMP attrbite begin button if ( !(btn->uiFlags & BUTTON_ENABLED) ) return; @@ -320,7 +271,6 @@ void BtnIMPVoicesNextCallback( GUI_BUTTON *btn, INT32 reason ) void BtnIMPVoicesPreviousCallback( GUI_BUTTON *btn, INT32 reason ) { - // btn callback for IMP attrbite begin button if ( !(btn->uiFlags & BUTTON_ENABLED) ) return; @@ -355,7 +305,6 @@ void BtnIMPVoicesPreviousCallback( GUI_BUTTON *btn, INT32 reason ) void BtnIMPVoicesDoneCallback( GUI_BUTTON *btn, INT32 reason ) { - // btn callback for IMP attrbite begin button if ( !(btn->uiFlags & BUTTON_ENABLED) ) return; @@ -372,11 +321,8 @@ void BtnIMPVoicesDoneCallback( GUI_BUTTON *btn, INT32 reason ) // Changed to continue to color choosing - SANDRO iCurrentImpPage = IMP_COLOR_CHOICE_PAGE; - // Following part removed - - // set voice id, to grab character slot - // WDS: Allow flexible numbers of IMPs of each sex - LaptopSaveInfo.iIMPIndex = gGameExternalOptions.iaIMPSlots[iCurrentVoice]; + + iSelectedIMPVoiceSet = gIMPVoice[iCurrentVoice].voiceset; // set button up image pending fButtonPendingFlag = TRUE; @@ -400,7 +346,7 @@ UINT32 PlayVoice( void ) { CHAR8 zFileName[164]; - INT32 iSlot = gGameExternalOptions.iaIMPSlots[iCurrentVoice]; + UINT16 iSlot = gIMPVoice[iCurrentVoice].voiceset; Assert( (iSlot >= 0) && (iSlot <= 999) ); sprintf( zFileName, "Speech\\%03d_001.ogg", iSlot ); @@ -412,7 +358,6 @@ UINT32 PlayVoice( void ) return(PlayJA2SampleFromFile( zFileName, RATE_11025, MIDVOLUME, 1, MIDDLEPAN )); } - void CreateIMPVoiceMouseRegions( void ) { // will create mouse regions needed for the IMP voices page @@ -428,7 +373,6 @@ void DestroyIMPVoiceMouseRegions( void ) MSYS_RemoveRegion( &gVoicePortraitRegion ); } - void IMPPortraitRegionButtonCallback( MOUSE_REGION * pRegion, INT32 iReason ) { // callback handler for imp portrait region button events @@ -446,14 +390,13 @@ void IMPPortraitRegionButtonCallback( MOUSE_REGION * pRegion, INT32 iReason ) } } - void RenderVoiceIndex( void ) { - CHAR16 sString[32]; + CHAR16 sString[100]; INT16 sX, sY; // render the voice index value on the the blank portrait - swprintf( sString, L"%s %d", pIMPVoicesStrings[0], GetVoiceCountFromVoiceSlot( iCurrentVoice ) ); + swprintf( sString, L"%s", gIMPVoice[iCurrentVoice].szVoiceSetName ); FindFontCenterCoordinates( 290 + LAPTOP_UL_X, 0, 100, 0, sString, FONT12ARIAL, &sX, &sY ); diff --git a/Laptop/IMP Voices.h b/Laptop/IMP Voices.h index afb731ae..e65f264b 100644 --- a/Laptop/IMP Voices.h +++ b/Laptop/IMP Voices.h @@ -7,4 +7,6 @@ void ExitIMPVoices( void ); void HandleIMPVoices( void ); UINT32 PlayVoice( void ); +extern UINT32 iSelectedIMPVoiceSet; + #endif \ No newline at end of file diff --git a/Laptop/Laptop_VS2005.vcproj b/Laptop/Laptop_VS2005.vcproj index db46f889..b1dd93f0 100644 --- a/Laptop/Laptop_VS2005.vcproj +++ b/Laptop/Laptop_VS2005.vcproj @@ -1072,6 +1072,10 @@ RelativePath=".\XML_IMPPortraits.cpp" > + + diff --git a/Laptop/Laptop_VS2008.vcproj b/Laptop/Laptop_VS2008.vcproj index 59c51cb4..815c062b 100644 --- a/Laptop/Laptop_VS2008.vcproj +++ b/Laptop/Laptop_VS2008.vcproj @@ -1074,6 +1074,10 @@ RelativePath=".\XML_IMPPortraits.cpp" > + + diff --git a/Laptop/Laptop_VS2010.vcxproj b/Laptop/Laptop_VS2010.vcxproj index 7ce8eee5..ec73d4b3 100644 --- a/Laptop/Laptop_VS2010.vcxproj +++ b/Laptop/Laptop_VS2010.vcxproj @@ -208,7 +208,8 @@ - + + diff --git a/Laptop/Laptop_VS2010.vcxproj.filters b/Laptop/Laptop_VS2010.vcxproj.filters index 7db1c7ea..4b6c4d8b 100644 --- a/Laptop/Laptop_VS2010.vcxproj.filters +++ b/Laptop/Laptop_VS2010.vcxproj.filters @@ -499,6 +499,9 @@ Source Files + + + Source Files Source Files diff --git a/Laptop/Laptop_VS2013.vcxproj b/Laptop/Laptop_VS2013.vcxproj index 0e7e2dd4..c3cc9b2c 100644 --- a/Laptop/Laptop_VS2013.vcxproj +++ b/Laptop/Laptop_VS2013.vcxproj @@ -208,6 +208,7 @@ + diff --git a/Laptop/Laptop_VS2013.vcxproj.filters b/Laptop/Laptop_VS2013.vcxproj.filters index 2d4de900..c55d11d5 100644 --- a/Laptop/Laptop_VS2013.vcxproj.filters +++ b/Laptop/Laptop_VS2013.vcxproj.filters @@ -566,5 +566,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Laptop/XML_IMPVoices.cpp b/Laptop/XML_IMPVoices.cpp new file mode 100644 index 00000000..f337aee3 --- /dev/null +++ b/Laptop/XML_IMPVoices.cpp @@ -0,0 +1,174 @@ +#ifdef PRECOMPILEDHEADERS +#include "Tactical All.h" +#else +#include "sgp.h" +#include "Debug Control.h" +#include "expat.h" +#include "XML.h" +#include "IMP Confirm.h" +#endif + +struct +{ + PARSE_STAGE curElement; + + CHAR8 szCharData[MAX_CHAR_DATA_LENGTH + 1]; + IMP_VOICESET curIMPVoice; + IMP_VOICESET* curArray; + + UINT32 maxArraySize; + UINT32 curIndex; + UINT32 currentDepth; + UINT32 maxReadDepth; +} +typedef impVoiceParseData; + +IMP_VOICESET gIMPVoice[NUM_IMP_VOICESETS]; + +static void XMLCALL +impVoicesStartElementHandle( void *userData, const XML_Char *name, const XML_Char **atts ) +{ + impVoiceParseData * pData = (impVoiceParseData *)userData; + + if ( pData->currentDepth <= pData->maxReadDepth ) //are we reading this element? + { + if ( strcmp( name, "IMPVOICELIST" ) == 0 && pData->curElement == ELEMENT_NONE ) + { + pData->curElement = ELEMENT_LIST; + + pData->maxReadDepth++; //we are not skipping this element + } + else if ( strcmp( name, "VOICE" ) == 0 && pData->curElement == ELEMENT_LIST ) + { + pData->curElement = ELEMENT; + + pData->maxReadDepth++; //we are not skipping this element + } + else if ( pData->curElement == ELEMENT && + (strcmp( name, "szVoiceSetName" ) == 0 || + strcmp( name, "voiceset" ) == 0 || + strcmp( name, "bSex" ) == 0 ) ) + { + pData->curElement = ELEMENT_PROPERTY; + + pData->maxReadDepth++; //we are not skipping this element + } + + pData->szCharData[0] = '\0'; + } + + pData->currentDepth++; +} + +static void XMLCALL +impVoicesCharacterDataHandle( void *userData, const XML_Char *str, int len ) +{ + impVoiceParseData * pData = (impVoiceParseData *)userData; + + if ( (pData->currentDepth <= pData->maxReadDepth) && + (strlen( pData->szCharData ) < MAX_CHAR_DATA_LENGTH) ) + { + strncat( pData->szCharData, str, __min( (unsigned int)len, MAX_CHAR_DATA_LENGTH - strlen( pData->szCharData ) ) ); + } +} + +static void XMLCALL +impVoicesEndElementHandle( void *userData, const XML_Char *name ) +{ + impVoiceParseData * pData = (impVoiceParseData *)userData; + + if ( pData->currentDepth <= pData->maxReadDepth ) + { + if ( strcmp( name, "IMPVOICELIST" ) == 0 ) + { + pData->curElement = ELEMENT_NONE; + } + else if ( strcmp( name, "VOICE" ) == 0 ) + { + pData->curElement = ELEMENT_LIST; + + wcscpy( gIMPVoice[pData->curIndex].szVoiceSetName, pData->curIMPVoice.szVoiceSetName ); + gIMPVoice[pData->curIndex].voiceset = pData->curIMPVoice.voiceset; + gIMPVoice[pData->curIndex].bSex = pData->curIMPVoice.bSex; + gIMPVoice[pData->curIndex].exists = TRUE; + + ++pData->curIndex; + } + else if ( strcmp( name, "szVoiceSetName" ) == 0 ) + { + pData->curElement = ELEMENT; + + MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curIMPVoice.szVoiceSetName, sizeof(pData->curIMPVoice.szVoiceSetName) / sizeof(pData->curIMPVoice.szVoiceSetName[0]) ); + pData->curIMPVoice.szVoiceSetName[sizeof(pData->curIMPVoice.szVoiceSetName) / sizeof(pData->curIMPVoice.szVoiceSetName[0]) - 1] = '\0'; + } + else if ( strcmp( name, "voiceset" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curIMPVoice.voiceset = (UINT16)atol( pData->szCharData ); + } + else if ( strcmp( name, "bSex" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curIMPVoice.bSex = (BOOLEAN)atol( pData->szCharData ); + } + + pData->maxReadDepth--; + } + pData->currentDepth--; +} + +BOOLEAN ReadInIMPVoices( STR fileName ) +{ + HWFILE hFile; + UINT32 uiBytesRead; + UINT32 uiFSize; + CHAR8 * lpcBuffer; + XML_Parser parser = XML_ParserCreate( NULL ); + + impVoiceParseData pData; + pData.curIndex = 0; + + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Loading IMPVoices.xml" ); + + // Open file + hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE ); + if ( !hFile ) + return(FALSE); + + uiFSize = FileGetSize( hFile ); + lpcBuffer = (CHAR8 *)MemAlloc( uiFSize + 1 ); + + //Read in block + if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) ) + { + MemFree( lpcBuffer ); + return(FALSE); + } + + lpcBuffer[uiFSize] = 0; //add a null terminator + + FileClose( hFile ); + + XML_SetElementHandler( parser, impVoicesStartElementHandle, impVoicesEndElementHandle ); + XML_SetCharacterDataHandler( parser, impVoicesCharacterDataHandle ); + + memset( &pData, 0, sizeof(pData) ); + XML_SetUserData( parser, &pData ); + + if ( !XML_Parse( parser, lpcBuffer, uiFSize, TRUE ) ) + { + CHAR8 errorBuf[511]; + + sprintf( errorBuf, "XML Parser Error in IMPVoices.xml: %s at line %d", XML_ErrorString( XML_GetErrorCode( parser ) ), XML_GetCurrentLineNumber( parser ) ); + LiveMessage( errorBuf ); + + MemFree( lpcBuffer ); + return FALSE; + } + + MemFree( lpcBuffer ); + + XML_ParserFree( parser ); + + return(TRUE); +} diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 90f9c47c..b2a0c658 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -1626,6 +1626,15 @@ BOOLEAN MERCPROFILESTRUCT::Load(HWFILE hFile, bool forceLoadOldVersion, bool for } } } + + // Flugente: voice set + if ( guiCurrentSaveGameVersion >= SEPARATE_VOICESETS ) + { + if ( !FileRead( hFile, &this->usVoiceIndex, sizeof(UINT32), &uiNumBytesRead ) ) + { + return(FALSE); + } + } } if ( this->uiProfileChecksum != this->GetChecksum() ) @@ -1731,6 +1740,12 @@ BOOLEAN MERCPROFILESTRUCT::Save(HWFILE hFile) { return(FALSE); } + + // Flugente: voice set used + if ( !FileWrite( hFile, &this->usVoiceIndex, sizeof(UINT32), &uiNumBytesWritten ) ) + { + return(FALSE); + } return TRUE; } @@ -6677,6 +6692,12 @@ BOOLEAN LoadSavedMercProfiles( HWFILE hFile ) // if not then overwrite with the previously stored data if ( gMercProfiles[cnt].bLifeMax <= 0 ) gMercProfiles[cnt] = tempMercProfile; + + /// Flugente: until the introduction of a separate varriable for the voiceset, the voice was identical with the slot + if ( guiCurrentSaveGameVersion < SEPARATE_VOICESETS ) + { + gMercProfiles[cnt].usVoiceIndex = cnt; + } } return( TRUE ); diff --git a/Tactical/Dialogue Control.cpp b/Tactical/Dialogue Control.cpp index 51c819df..da0b3189 100644 --- a/Tactical/Dialogue Control.cpp +++ b/Tactical/Dialogue Control.cpp @@ -2021,11 +2021,11 @@ BOOLEAN ExecuteCharacterDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 // Check face index CHECKF( iFaceIndex != -1 ); - + if ( !GetDialogue( ubCharacterNum, usQuoteNum, DIALOGUESIZE, gzQuoteStr, &uiSoundID, zSoundString) ) { - return( FALSE ); + return( FALSE ); } if( bUIHandlerID == DIALOGUE_EXTERNAL_NPC_UI ) @@ -2142,9 +2142,12 @@ CHAR8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN { static CHAR8 zFileName[164]; static CHAR8 zFileNameExists[164]; - UINT8 ubFileNumID; + UINT32 ubFileNumID; BOOLEAN isBartenderSantos = FALSE; + // Flugente: For the voice set itself, use this number + UINT32 usVoiceSet = gMercProfiles[ubCharacterNum].usVoiceIndex; + // Are we an NPC OR an RPC that has not been recruited? // ATE: Did the || clause here to allow ANY RPC that talks while the talking menu is up to use an npc quote file if ( gfUseAlternateDialogueFile ) @@ -2163,10 +2166,10 @@ CHAR8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN // #else if ( gSoundProfileValue[ubCharacterNum].EnabledSound == TRUE ) { - sprintf( zFileName,"NPC_SPEECH\\d_%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); + sprintf( zFileName, "NPC_SPEECH\\d_%03d_%03d.ogg", usVoiceSet, usQuoteNum ); if ( !FileExists( zFileName ) ) { - sprintf( zFileName,"NPC_SPEECH\\d_%03d_%03d.wav",ubCharacterNum,usQuoteNum ); + sprintf( zFileName, "NPC_SPEECH\\d_%03d_%03d.wav", usVoiceSet, usQuoteNum ); } } // #endif @@ -2174,7 +2177,7 @@ CHAR8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN else { // assume EDT files are in EDT directory on HARD DRIVE - sprintf( zFileName,"NPCDATA\\d_%03d.EDT", ubCharacterNum ); + sprintf( zFileName, "NPCDATA\\d_%03d.EDT", usVoiceSet ); } } //else if ( ubCharacterNum >= FIRST_RPC && ubCharacterNum < GASTON && @@ -2186,7 +2189,7 @@ CHAR8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN ) { - ubFileNumID = ubCharacterNum; + ubFileNumID = usVoiceSet; if ( ubCharacterNum == HERVE ) { @@ -2221,7 +2224,7 @@ CHAR8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN ubFileNumID = CARLO; } - #ifdef JA2UB +#ifdef JA2UB if ( ubCharacterNum == MANUEL_UB ) { sprintf( (char *)zFileNameExists,"NPCDATA\\%03d.EDT", MANUEL_UB ); @@ -2294,7 +2297,7 @@ CHAR8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN ubFileNumID = RUDY_UB; } - #endif +#endif // If we are character #155, check fact! if ( ubCharacterNum == MANNY && !gubFact[ FACT_MANNY_IS_BARTENDER ] ) @@ -2339,68 +2342,69 @@ CHAR8 *GetDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN { if ( fWavFile ) { - #ifdef RUSSIAN +#ifdef RUSSIAN // if( ubCharacterNum >= FIRST_RPC && ubCharacterNum < GASTON && gMercProfiles[ ubCharacterNum ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) //new profiles by Jazz if ( ( gProfilesRPC[ubCharacterNum].ProfilId == ubCharacterNum || gProfilesNPC[ubCharacterNum].ProfilId == ubCharacterNum || gProfilesVehicle[ubCharacterNum].ProfilId == ubCharacterNum ) && gMercProfiles[ ubCharacterNum ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) { - //inshy: fix for UB-1.13 version only sprintf( zFileName,"SPEECH\\r_%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); - if ( gSoundProfileValue[ubCharacterNum].EnabledSound == TRUE ) - { - - #ifdef JA2UB - sprintf( zFileName,"SPEECH\\%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); - if ( !FileExists( zFileName ) ) - { - sprintf( zFileName,"SPEECH\\%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); - } - #else - sprintf( zFileName,"SPEECH\\r_%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); - #endif - if ( !FileExists( zFileName ) ) - { - //inshy: fix for UB-1.13 version only - #ifdef JA2UB - sprintf( zFileName,"SPEECH\\%03d_%03d.wav",ubCharacterNum,usQuoteNum ); - - if ( !FileExists( zFileName ) ) - { - sprintf( zFileName,"SPEECH\\%03d_%03d.wav",ubCharacterNum,usQuoteNum ); - } - #else - sprintf( zFileName,"SPEECH\\r_%03d_%03d.wav",ubCharacterNum,usQuoteNum ); - #endif - // Also check for Russian Gold sound files (identical to international ones) - if(! FileExists( zFileName ) ) + //inshy: fix for UB-1.13 version only sprintf( zFileName,"SPEECH\\r_%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); + if ( gSoundProfileValue[ubCharacterNum].EnabledSound == TRUE ) + { + #ifdef JA2UB + sprintf( zFileName,"SPEECH\\%03d_%03d.ogg",usVoiceSet,usQuoteNum ); + if ( !FileExists( zFileName ) ) { - sprintf( zFileName,"SPEECH\\%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); + sprintf( zFileName,"SPEECH\\%03d_%03d.ogg",usVoiceSet,usQuoteNum ); + } + #else + sprintf( zFileName,"SPEECH\\r_%03d_%03d.ogg",usVoiceSet,usQuoteNum ); + #endif + if ( !FileExists( zFileName ) ) + { + //inshy: fix for UB-1.13 version only + #ifdef JA2UB + sprintf( zFileName,"SPEECH\\%03d_%03d.wav",usVoiceSet,usQuoteNum ); + if ( !FileExists( zFileName ) ) { - sprintf( zFileName,"SPEECH\\%03d_%03d.wav",ubCharacterNum,usQuoteNum ); + sprintf( zFileName,"SPEECH\\%03d_%03d.wav",usVoiceSet,usQuoteNum ); + } + #else + sprintf( zFileName,"SPEECH\\r_%03d_%03d.wav",usVoiceSet,usQuoteNum ); + #endif + + // Also check for Russian Gold sound files (identical to international ones) + if(! FileExists( zFileName ) ) + { + sprintf( zFileName,"SPEECH\\%03d_%03d.ogg",usVoiceSet,usQuoteNum ); + if ( !FileExists( zFileName ) ) + { + sprintf( zFileName,"SPEECH\\%03d_%03d.wav",usVoiceSet,usQuoteNum ); + } } - } // - } + } } } else - #endif +#endif { if ( gSoundProfileValue[ubCharacterNum].EnabledSound == TRUE ) { - // build name of wav file (characternum + quotenum) - sprintf( zFileName,"SPEECH\\%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); - if ( !FileExists( zFileName ) ) - { - sprintf( zFileName,"SPEECH\\%03d_%03d.wav",ubCharacterNum,usQuoteNum ); - } + // build name of wav file (characternum + quotenum) + sprintf( zFileName, "SPEECH\\%03d_%03d.ogg", usVoiceSet, usQuoteNum ); + + if ( !FileExists( zFileName ) ) + { + sprintf( zFileName, "SPEECH\\%03d_%03d.wav", usVoiceSet, usQuoteNum ); + } } } } else { // assume EDT files are in EDT directory on HARD DRIVE - sprintf( zFileName,"MERCEDT\\%03d.EDT", ubCharacterNum ); + sprintf( zFileName, "MERCEDT\\%03d.EDT", usVoiceSet ); } } @@ -2412,6 +2416,9 @@ CHAR8 *GetSnitchDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, B static CHAR8 zFileName[164]; static CHAR8 zFileNameExists[164]; + // Flugente: For the voice set itself, use this number + UINT32 usVoiceSet = gMercProfiles[ubCharacterNum].usVoiceIndex; + if ( fWavFile ) { if ( gSoundProfileValue[ubCharacterNum].EnabledSound == TRUE ) @@ -2419,18 +2426,18 @@ CHAR8 *GetSnitchDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, B // build name of wav file (characternum + quotenum) if(fName) { - sprintf( zFileName,"SPEECH\\SNITCH\\NAMES\\%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); + sprintf( zFileName, "SPEECH\\SNITCH\\NAMES\\%03d_%03d.ogg", usVoiceSet, usQuoteNum ); if ( !FileExists( zFileName ) ) { - sprintf( zFileName,"SPEECH\\SNITCH\\NAMES\\%03d_%03d.wav",ubCharacterNum,usQuoteNum ); + sprintf( zFileName, "SPEECH\\SNITCH\\NAMES\\%03d_%03d.wav", usVoiceSet, usQuoteNum ); } } else { - sprintf( zFileName,"SPEECH\\SNITCH\\%03d_%03d.ogg",ubCharacterNum,usQuoteNum ); + sprintf( zFileName, "SPEECH\\SNITCH\\%03d_%03d.ogg", usVoiceSet, usQuoteNum ); if ( !FileExists( zFileName ) ) { - sprintf( zFileName,"SPEECH\\SNITCH\\%03d_%03d.wav",ubCharacterNum,usQuoteNum ); + sprintf( zFileName, "SPEECH\\SNITCH\\%03d_%03d.wav", usVoiceSet, usQuoteNum ); } } } @@ -2439,9 +2446,9 @@ CHAR8 *GetSnitchDialogueDataFilename( UINT8 ubCharacterNum, UINT16 usQuoteNum, B { // assume EDT files are in EDT directory on HARD DRIVE if(fName) - sprintf( zFileName,"MERCEDT\\SNITCH\\NAMES\\%03d.EDT", ubCharacterNum ); + sprintf( zFileName, "MERCEDT\\SNITCH\\NAMES\\%03d.EDT", usVoiceSet ); else - sprintf( zFileName,"MERCEDT\\SNITCH\\%03d.EDT", ubCharacterNum ); + sprintf( zFileName, "MERCEDT\\SNITCH\\%03d.EDT", usVoiceSet ); } return( zFileName ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 0a28374b..4cb72398 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1548,6 +1548,8 @@ void MERCPROFILESTRUCT::initialize( ) memset( &usDynamicOpinionFlagmask, 0, sizeof(usDynamicOpinionFlagmask) ); memset( &sDynamicOpinionLongTerm, 0, sizeof(sDynamicOpinionLongTerm) ); + + memset( &usVoiceIndex, 0, sizeof(UINT32) ); } // Initialize the soldier. @@ -10749,11 +10751,14 @@ BOOLEAN SOLDIERTYPE::InternalDoMercBattleSound( UINT8 ubBattleSoundID, INT8 bSpe // OK, build file and play! if ( pSoldier->ubProfile != NO_PROFILE ) { - sprintf( zFilename, "BATTLESNDS\\%03d_%s.ogg", pSoldier->ubProfile, gBattleSndsData[ubSoundID].zName ); + // Flugente: For the voice set itself, use this number + UINT32 usVoiceSet = gMercProfiles[pSoldier->ubProfile].usVoiceIndex; + + sprintf( zFilename, "BATTLESNDS\\%03d_%s.ogg", usVoiceSet, gBattleSndsData[ubSoundID].zName ); if ( !FileExists( zFilename ) ) { - sprintf( zFilename, "BATTLESNDS\\%03d_%s.wav", pSoldier->ubProfile, gBattleSndsData[ubSoundID].zName ); + sprintf( zFilename, "BATTLESNDS\\%03d_%s.wav", usVoiceSet, gBattleSndsData[ubSoundID].zName ); } if ( !FileExists( zFilename ) ) diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index e3f914ee..a1ebe8ea 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -798,6 +798,12 @@ BOOLEAN LoadMercProfiles(void) FileClose( fptr ); return(FALSE); } + + /// Flugente: until the introduction of a separate varriable for the voiceset, the voice was identical with the slot + // as we are loading from a .dat file, we always have to account for that + { + gMercProfiles[uiLoop].usVoiceIndex = uiLoop; + } // WANNE: For the new WF merc, there is no entry in prof.dat, so we have to reset some flags manually! if (uiLoop >= 170) @@ -864,7 +870,7 @@ BOOLEAN LoadMercProfiles(void) } //if the Dialogue exists for the merc, allow the merc to be hired - if( DialogueDataFileExistsForProfile( (UINT8)uiLoop, 0, FALSE, NULL ) ) + if ( DialogueDataFileExistsForProfile( gMercProfiles[uiLoop].usVoiceIndex, 0, FALSE, NULL ) ) { gMercProfiles[uiLoop].bMercStatus = 0; } @@ -2742,6 +2748,7 @@ void OverwriteMercProfileWithXMLData( UINT32 uiLoop ) gMercProfiles[ uiLoop ].bTown = tempProfiles[uiLoop].bTown; gMercProfiles[ uiLoop ].bTownAttachment = tempProfiles[uiLoop].bTownAttachment; gMercProfiles[ uiLoop ].usBackground = tempProfiles[uiLoop].usBackground; + gMercProfiles[ uiLoop ].usVoiceIndex = tempProfiles[uiLoop].usVoiceIndex; //None if ( tempProfiles[uiLoop].Type == 0 ) diff --git a/Tactical/Soldier Profile.h b/Tactical/Soldier Profile.h index 49a59bfc..f852b36d 100644 --- a/Tactical/Soldier Profile.h +++ b/Tactical/Soldier Profile.h @@ -420,6 +420,8 @@ typedef struct // Flugente: backgrounds UINT16 usBackground; + UINT32 usVoiceIndex; + } TEMPPROFILETYPE; extern TEMPPROFILETYPE tempProfiles[NUM_PROFILES+1]; diff --git a/Tactical/XML.h b/Tactical/XML.h index 37326ae9..ef237c23 100644 --- a/Tactical/XML.h +++ b/Tactical/XML.h @@ -217,6 +217,7 @@ typedef PARSE_STAGE; #define FACEGEARFILENAME "FaceGear.xml" #define HIDDENNAMESFILENAME "HiddenNames.xml" #define IMPPORTRAITS "IMPPortraits.xml" +#define IMPVOICES "IMPVoices.xml" #define MERCAVAILABILITY "MercAvailability.xml" #define MERCOPINIONSFILENAME "MercOpinions.xml" #define MERCPROFILESFILENAME "MercProfiles.xml" @@ -502,6 +503,7 @@ extern BOOLEAN ReadInSenderNameList(STR fileName, BOOLEAN localizedVersion); extern BOOLEAN ReadInEnemyRank(STR fileName, BOOLEAN localizedVersion); extern BOOLEAN WriteEnemyRank( STR fileName); extern BOOLEAN ReadInIMPPortraits(STR fileName, BOOLEAN localizedVersion); +extern BOOLEAN ReadInIMPVoices( STR fileName ); extern void LoadIMPPortraitsTEMP(); // Flugente: backgrounds diff --git a/Tactical/XML_Opinions.cpp b/Tactical/XML_Opinions.cpp index f6729038..74768a05 100644 --- a/Tactical/XML_Opinions.cpp +++ b/Tactical/XML_Opinions.cpp @@ -227,7 +227,7 @@ BOOLEAN ReadInMercOpinions(STR fileName) { CHAR8 errorBuf[511]; - sprintf(errorBuf, "XML Parser Error in MercProfiles.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); + sprintf(errorBuf, "XML Parser Error in MercOpinions.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); LiveMessage(errorBuf); MemFree(lpcBuffer); diff --git a/Tactical/XML_Profiles.cpp b/Tactical/XML_Profiles.cpp index 1cdb937f..e165e044 100644 --- a/Tactical/XML_Profiles.cpp +++ b/Tactical/XML_Profiles.cpp @@ -71,6 +71,7 @@ profileStartElementHandle(void *userData, const XML_Char *name, const XML_Char * strcmp(name, "zNickname") == 0 || strcmp(name, "uiIndex") == 0 || strcmp(name, "ubFaceIndex") == 0 || + strcmp(name, "usVoiceIndex" ) == 0 || strcmp(name, "usEyesX") == 0 || strcmp(name, "usEyesY") == 0 || strcmp(name, "usMouthX") == 0 || @@ -190,8 +191,8 @@ profileStartElementHandle(void *userData, const XML_Char *name, const XML_Char * strcmp(name, "ubCivilianGroup") == 0 || strcmp(name, "bTown") == 0 || strcmp(name, "bTownAttachment") == 0 || - strcmp(name, "usBackground") == 0 - + strcmp(name, "usBackground") == 0 + )) { pData->curElement = ELEMENT_PROPERTY; @@ -358,7 +359,8 @@ profileEndElementHandle(void *userData, const XML_Char *name) tempProfiles[pData->curIndex].bTown = pData->curProfile.bTown; tempProfiles[pData->curIndex].bTownAttachment = pData->curProfile.bTownAttachment; tempProfiles[pData->curIndex].usBackground = pData->curProfile.usBackground; - + tempProfiles[pData->curIndex].usVoiceIndex = pData->curProfile.usVoiceIndex; + tempProfiles[pData->curIndex].fGoodGuy = pData->curProfile.fGoodGuy; memcpy( &(tempProfiles[pData->curIndex].usApproachFactor), &(pData->curProfile.usApproachFactor), 4 * sizeof (UINT16)); @@ -1087,7 +1089,11 @@ profileEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curProfile.usBackground = (UINT16) atol(pData->szCharData); } - + else if ( strcmp( name, "usVoiceIndex" ) == 0 ) + { + pData->curElement = ELEMENT; + pData->curProfile.usVoiceIndex = (UINT32)atol( pData->szCharData ); + } pData->maxReadDepth--; } @@ -1328,6 +1334,7 @@ BOOLEAN WriteMercProfiles() // FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].ubFaceIndex); + FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[cnt].usVoiceIndex ); FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].usEyesX); FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].usEyesY); FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].usMouthX); @@ -1664,7 +1671,6 @@ BOOLEAN WriteMercProfiles() FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].bTownAttachment); FilePrintf(hFile,"\t\t%d\r\n", gMercProfiles[ cnt ].usBackground); - FilePrintf(hFile,"\t\r\n"); } FilePrintf(hFile,"\r\n"); diff --git a/Tactical/soldier profile type.h b/Tactical/soldier profile type.h index dafbba30..119fcfce 100644 --- a/Tactical/soldier profile type.h +++ b/Tactical/soldier profile type.h @@ -969,6 +969,8 @@ public: INT8 sDynamicOpinionLongTerm[NUM_PROFILES]; + // Flugente: voice set used + UINT32 usVoiceIndex; }; // MERCPROFILESTRUCT; // WANNE - BMP: DONE!